Files
wled-screen-controller-mixed/server/src/wled_controller/static/js/app.js
alexei.dolgolyov 0a000cc44c Fix Toggle All button state, stop icons, and Disable tooltip
- Fix Toggle All button always showing Start: /picture-targets list
  endpoint does not include processing state; now fetches
  /picture-targets/{id}/state per-target in parallel in both
  loadProfiles() and toggleProfileTargets()
- Replace pause icons (⏸) with stop icons (⏹) in dashboard
- Change profile automation toggle tooltip from 'Disabled' (status)
  to 'Disable' (action); add profiles.action.disable i18n key

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 22:35:24 +03:00

363 lines
10 KiB
JavaScript

/**
* Entry point — imports all modules, registers globals, initializes app.
*/
// Layer 0: state
import { apiKey, setApiKey, refreshInterval } from './core/state.js';
import { Modal } from './core/modal.js';
// Layer 1: api, i18n
import { loadServerInfo, loadDisplays, configureApiKey } from './core/api.js';
import { t, initLocale, changeLocale } from './core/i18n.js';
// Layer 2: ui
import {
toggleHint, lockBody, unlockBody, closeLightbox,
showToast, showConfirm, closeConfirmModal,
openFullImageLightbox, showOverlaySpinner, hideOverlaySpinner,
} from './core/ui.js';
// Layer 3: displays, tutorials
import {
openDisplayPicker, closeDisplayPicker, selectDisplay, formatDisplayLabel,
} from './features/displays.js';
import {
startCalibrationTutorial, startDeviceTutorial,
closeTutorial, tutorialNext, tutorialPrev,
} from './features/tutorials.js';
// Layer 4: devices, dashboard, streams, kc-targets, pattern-templates, profiles
import {
showSettings, closeDeviceSettingsModal, forceCloseDeviceSettingsModal,
saveDeviceSettings, updateBrightnessLabel, saveCardBrightness,
saveDeviceStaticColor, clearDeviceStaticColor,
toggleDevicePower, removeDevice, loadDevices,
updateSettingsBaudFpsHint,
} from './features/devices.js';
import {
loadDashboard, stopUptimeTimer,
dashboardToggleProfile, dashboardStartTarget, dashboardStopTarget, dashboardStopAll,
toggleDashboardSection, changeDashboardPollInterval,
} from './features/dashboard.js';
import { startEventsWS, stopEventsWS } from './core/events-ws.js';
import {
startPerfPolling, stopPerfPolling,
} from './features/perf-charts.js';
import {
loadPictureSources, switchStreamTab,
showAddTemplateModal, editTemplate, closeTemplateModal, saveTemplate, deleteTemplate,
showTestTemplateModal, closeTestTemplateModal, onEngineChange, runTemplateTest,
showAddStreamModal, editStream, closeStreamModal, saveStream, deleteStream,
onStreamTypeChange, onStreamDisplaySelected, onTestDisplaySelected,
showTestStreamModal, closeTestStreamModal, updateStreamTestDuration, runStreamTest,
showTestPPTemplateModal, closeTestPPTemplateModal, updatePPTestDuration, runPPTemplateTest,
showAddPPTemplateModal, editPPTemplate, closePPTemplateModal, savePPTemplate, deletePPTemplate,
addFilterFromSelect, toggleFilterExpand, removeFilter, moveFilter, updateFilterOption,
renderModalFilterList, updateCaptureDuration,
} from './features/streams.js';
import {
createKCTargetCard, testKCTarget, toggleKCTestAutoRefresh,
showKCEditor, closeKCEditorModal, forceCloseKCEditorModal, saveKCEditor,
deleteKCTarget, disconnectAllKCWebSockets,
updateKCBrightnessLabel, saveKCBrightness,
} from './features/kc-targets.js';
import {
createPatternTemplateCard,
showPatternTemplateEditor, closePatternTemplateModal, forceClosePatternTemplateModal,
savePatternTemplate, deletePatternTemplate,
renderPatternRectList, selectPatternRect, updatePatternRect,
addPatternRect, deleteSelectedPatternRect, removePatternRect,
capturePatternBackground,
} from './features/pattern-templates.js';
import {
loadProfiles, openProfileEditor, closeProfileEditorModal,
saveProfileEditor, addProfileCondition,
toggleProfileEnabled, toggleProfileTargets, deleteProfile,
} from './features/profiles.js';
// Layer 5: device-discovery, targets
import {
onDeviceTypeChanged, updateBaudFpsHint, onSerialPortFocus,
showAddDevice, closeAddDeviceModal, scanForDevices, handleAddDevice,
} from './features/device-discovery.js';
import {
loadTargetsTab, loadTargets, switchTargetSubTab,
showTargetEditor, closeTargetEditorModal, forceCloseTargetEditorModal, saveTargetEditor,
startTargetProcessing, stopTargetProcessing,
startTargetOverlay, stopTargetOverlay, deleteTarget,
} from './features/targets.js';
// Layer 5: color-strip sources
import {
showCSSEditor, closeCSSEditorModal, forceCSSEditorClose, saveCSSEditor, deleteColorStrip,
onCSSTypeChange, colorCycleAddColor, colorCycleRemoveColor,
} from './features/color-strips.js';
// Layer 5: calibration
import {
showCalibration, closeCalibrationModal, forceCloseCalibrationModal, saveCalibration,
updateOffsetSkipLock, updateCalibrationPreview,
setStartPosition, toggleEdgeInputs, toggleDirection, toggleTestEdge,
showCSSCalibration,
} from './features/calibration.js';
// Layer 6: tabs
import { switchTab, initTabs, startAutoRefresh } from './features/tabs.js';
// ─── Register all HTML onclick / onchange / onfocus globals ───
Object.assign(window, {
// core / state (for inline script)
setApiKey,
// core / ui
toggleHint,
lockBody,
unlockBody,
closeLightbox,
showToast,
showConfirm,
closeConfirmModal,
openFullImageLightbox,
showOverlaySpinner,
hideOverlaySpinner,
// core / api + i18n
t,
configureApiKey,
loadServerInfo,
loadDisplays,
changeLocale,
// displays
openDisplayPicker,
closeDisplayPicker,
selectDisplay,
formatDisplayLabel,
// tutorials
startCalibrationTutorial,
startDeviceTutorial,
closeTutorial,
tutorialNext,
tutorialPrev,
// devices
showSettings,
closeDeviceSettingsModal,
forceCloseDeviceSettingsModal,
saveDeviceSettings,
updateBrightnessLabel,
saveCardBrightness,
saveDeviceStaticColor,
clearDeviceStaticColor,
toggleDevicePower,
removeDevice,
loadDevices,
updateSettingsBaudFpsHint,
// dashboard
loadDashboard,
dashboardToggleProfile,
dashboardStartTarget,
dashboardStopTarget,
dashboardStopAll,
toggleDashboardSection,
changeDashboardPollInterval,
stopUptimeTimer,
startPerfPolling,
stopPerfPolling,
// streams / capture templates / PP templates
loadPictureSources,
switchStreamTab,
showAddTemplateModal,
editTemplate,
closeTemplateModal,
saveTemplate,
deleteTemplate,
showTestTemplateModal,
closeTestTemplateModal,
onEngineChange,
runTemplateTest,
updateCaptureDuration,
showAddStreamModal,
editStream,
closeStreamModal,
saveStream,
deleteStream,
onStreamTypeChange,
onStreamDisplaySelected,
onTestDisplaySelected,
showTestStreamModal,
closeTestStreamModal,
updateStreamTestDuration,
runStreamTest,
showTestPPTemplateModal,
closeTestPPTemplateModal,
updatePPTestDuration,
runPPTemplateTest,
showAddPPTemplateModal,
editPPTemplate,
closePPTemplateModal,
savePPTemplate,
deletePPTemplate,
addFilterFromSelect,
toggleFilterExpand,
removeFilter,
moveFilter,
updateFilterOption,
renderModalFilterList,
// kc-targets
createKCTargetCard,
testKCTarget,
toggleKCTestAutoRefresh,
showKCEditor,
closeKCEditorModal,
forceCloseKCEditorModal,
saveKCEditor,
deleteKCTarget,
disconnectAllKCWebSockets,
updateKCBrightnessLabel,
saveKCBrightness,
// pattern-templates
createPatternTemplateCard,
showPatternTemplateEditor,
closePatternTemplateModal,
forceClosePatternTemplateModal,
savePatternTemplate,
deletePatternTemplate,
renderPatternRectList,
selectPatternRect,
updatePatternRect,
addPatternRect,
deleteSelectedPatternRect,
removePatternRect,
capturePatternBackground,
// profiles
loadProfiles,
openProfileEditor,
closeProfileEditorModal,
saveProfileEditor,
addProfileCondition,
toggleProfileEnabled,
toggleProfileTargets,
deleteProfile,
// device-discovery
onDeviceTypeChanged,
updateBaudFpsHint,
onSerialPortFocus,
showAddDevice,
closeAddDeviceModal,
scanForDevices,
handleAddDevice,
// targets
loadTargetsTab,
loadTargets,
switchTargetSubTab,
showTargetEditor,
closeTargetEditorModal,
forceCloseTargetEditorModal,
saveTargetEditor,
startTargetProcessing,
stopTargetProcessing,
startTargetOverlay,
stopTargetOverlay,
deleteTarget,
// color-strip sources
showCSSEditor,
closeCSSEditorModal,
forceCSSEditorClose,
saveCSSEditor,
deleteColorStrip,
onCSSTypeChange,
colorCycleAddColor,
colorCycleRemoveColor,
// calibration
showCalibration,
closeCalibrationModal,
forceCloseCalibrationModal,
saveCalibration,
updateOffsetSkipLock,
updateCalibrationPreview,
setStartPosition,
toggleEdgeInputs,
toggleDirection,
toggleTestEdge,
showCSSCalibration,
// tabs
switchTab,
startAutoRefresh,
});
// ─── Global Escape key handler ───
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
// Close in order: overlay lightboxes first, then modals via stack
if (document.getElementById('display-picker-lightbox').classList.contains('active')) {
closeDisplayPicker();
} else if (document.getElementById('image-lightbox').classList.contains('active')) {
closeLightbox();
} else {
Modal.closeTopmost();
}
}
});
// ─── Cleanup on page unload ───
window.addEventListener('beforeunload', () => {
if (refreshInterval) {
clearInterval(refreshInterval);
}
stopEventsWS();
disconnectAllKCWebSockets();
});
// ─── Initialization ───
document.addEventListener('DOMContentLoaded', async () => {
// Load API key from localStorage before anything that triggers API calls
setApiKey(localStorage.getItem('wled_api_key'));
// Initialize locale (dispatches languageChanged which may trigger API calls)
await initLocale();
// Restore active tab before showing content to avoid visible jump
initTabs();
// Show content now that translations are loaded and tabs are set
document.body.style.visibility = 'visible';
// Setup form handler
document.getElementById('add-device-form').addEventListener('submit', handleAddDevice);
// Show modal if no API key is stored
if (!apiKey) {
setTimeout(() => {
if (typeof window.showApiKeyModal === 'function') {
window.showApiKeyModal(null, true);
}
}, 100);
return;
}
// User is logged in, load data
loadServerInfo();
loadDisplays();
loadTargetsTab();
// Start global events WebSocket and auto-refresh
startEventsWS();
startAutoRefresh();
});