From 8030598fc3691f37c7f45b8b7843118b49de9838 Mon Sep 17 00:00:00 2001 From: Jury Giannelli Date: Sun, 25 Jan 2026 22:08:50 +0100 Subject: [PATCH 1/4] showcase atoms as modal store --- src/dashboard/Dashboard.js | 9 --------- src/dashboard/components/DashboardHeader.tsx | 7 ++++--- .../components/DashboardModalLayer.tsx | 16 ---------------- .../core/hooks/useDashboardUiState.ts | 10 ---------- src/dashboard/core/modalAtoms.ts | 5 +++++ src/dashboard/modals/CreateSetModal.tsx | 7 ++++--- src/dashboard/modals/SelectSetModal.tsx | 18 +++++++++++------- 7 files changed, 24 insertions(+), 48 deletions(-) create mode 100644 src/dashboard/core/modalAtoms.ts diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 1369d93..be76afb 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -57,12 +57,8 @@ const Dashboard = () => { setWorkspaceModalPath, isCreateTrackOpen, setIsCreateTrackOpen, - isCreateSetOpen, - setIsCreateSetOpen, isSelectTrackModalOpen, setIsSelectTrackModalOpen, - isSelectSetModalOpen, - setIsSelectSetModalOpen, isSettingsModalOpen, setIsSettingsModalOpen, isInputMappingsModalOpen, @@ -294,7 +290,6 @@ const Dashboard = () => { return (
setIsSelectSetModalOpen(true)} onTracks={() => setIsSelectTrackModalOpen(true)} onModules={() => setIsManageModulesModalOpen(true)} onSettings={() => setIsSettingsModalOpen(true)} @@ -347,12 +342,8 @@ const Dashboard = () => { void) | null; onTracks?: (() => void) | null; onModules?: (() => void) | null; onSettings?: (() => void) | null; @@ -12,13 +13,13 @@ type DashboardHeaderProps = { }; export const DashboardHeader = ({ - onSets, onTracks, onModules, onSettings, onDebugOverlay, onReleases, }: DashboardHeaderProps) => { + const openSelectSet = useSetAtom(selectSetModalAtom) const update = useUpdateCheck(); const hasUpdate = update.status === "updateAvailable"; @@ -33,7 +34,7 @@ export const DashboardHeader = ({
-
- From 83670d20f68024e2b8d17beeeadee7164df77b48 Mon Sep 17 00:00:00 2001 From: Jury Giannelli Date: Fri, 30 Jan 2026 23:09:54 +0100 Subject: [PATCH 2/4] create modal and dialog atoms --- src/dashboard/core/modalAtoms.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/dashboard/core/modalAtoms.ts b/src/dashboard/core/modalAtoms.ts index f889a4c..c985ac7 100644 --- a/src/dashboard/core/modalAtoms.ts +++ b/src/dashboard/core/modalAtoms.ts @@ -1,5 +1,16 @@ import { atom } from "jotai" +import { Confirmation } from "../modals/ConfirmationModal" +export const confirmationModalAtom = atom() + +export const workspaceModalAtom = atom(false) export const selectSetModalAtom = atom(false) +export const selectTrackModalAtom = atom(false) export const createSetModalAtom = atom(false) -// ADD more modals here or one file per modal... \ No newline at end of file +export const createTrackModalAtom = atom(false) +export const settingsModalAtom = atom(false) +export const inputMappingsModalAtom = atom(false) +export const releaseNotesModalAtom = atom(false) +export const addModuleModalAtom = atom<"add-to-track" | "manage-modules" | false>(false) +export const moduleEditorModalAtom = atom(false) +export const debugOverlayModalAtom = atom(false) From 4092c3d8e884ee4ac0771d7e1f274cecfad92e05 Mon Sep 17 00:00:00 2001 From: Jury Giannelli Date: Sat, 31 Jan 2026 00:20:52 +0100 Subject: [PATCH 3/4] refactoring modals state to atoms --- src/dashboard/Dashboard.js | 68 +-------- src/dashboard/components/DashboardBody.tsx | 6 - src/dashboard/components/DashboardFooter.tsx | 10 +- src/dashboard/components/DashboardHeader.tsx | 48 +++---- .../components/DashboardModalLayer.tsx | 133 +----------------- .../components/ModuleEditorModal.tsx | 8 +- src/dashboard/components/NewModuleDialog.tsx | 8 +- .../components/WorkspaceGateModal.tsx | 5 +- src/dashboard/components/track/TrackItem.tsx | 24 +++- .../core/hooks/useDashboardBootstrap.ts | 5 +- .../core/hooks/useDashboardUiState.ts | 120 ++-------------- .../core/hooks/useWorkspaceModules.ts | 5 +- src/dashboard/core/modalAtoms.ts | 12 ++ src/dashboard/core/state.ts | 4 +- src/dashboard/modals/AddModuleModal.tsx | 18 +-- src/dashboard/modals/ConfirmationModal.tsx | 19 ++- src/dashboard/modals/CreateTrackModal.tsx | 7 +- src/dashboard/modals/DebugOverlayModal.tsx | 8 +- src/dashboard/modals/EditChannelModal.tsx | 12 +- src/dashboard/modals/EditSetModal.tsx | 14 +- src/dashboard/modals/EditTrackModal.tsx | 13 +- src/dashboard/modals/InputMappingsModal.tsx | 10 +- .../modals/MethodConfiguratorModal.tsx | 24 ++-- src/dashboard/modals/ReleaseNotesModal.tsx | 11 +- src/dashboard/modals/SelectSetModal.tsx | 74 +++++----- src/dashboard/modals/SelectTrackModal.tsx | 44 +++--- src/dashboard/modals/SettingsModal.tsx | 20 ++- src/dashboard/modals/TrackDataModal.tsx | 1 - 28 files changed, 230 insertions(+), 501 deletions(-) diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index be76afb..f3fa489 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -9,7 +9,6 @@ import { recordingDataAtom, activeTrackIdAtom, activeSetIdAtom, - selectedChannelAtom, flashingConstructorsAtom, recordingStateAtom, useFlashingChannels, @@ -39,7 +38,6 @@ const Dashboard = () => { const [activeTrackId, setActiveTrackId] = useAtom(activeTrackIdAtom); const [activeSetId, setActiveSetId] = useAtom(activeSetIdAtom); const [predefinedModules, setPredefinedModules] = useState([]); - const [selectedChannel, setSelectedChannel] = useAtom(selectedChannelAtom); const [, flashChannel] = useFlashingChannels(); const [, setFlashingConstructors] = useAtom(flashingConstructorsAtom); @@ -49,31 +47,12 @@ const Dashboard = () => { const { workspacePath, setWorkspacePath, - isWorkspaceModalOpen, - setIsWorkspaceModalOpen, workspaceModalMode, setWorkspaceModalMode, workspaceModalPath, setWorkspaceModalPath, - isCreateTrackOpen, - setIsCreateTrackOpen, - isSelectTrackModalOpen, - setIsSelectTrackModalOpen, - isSettingsModalOpen, - setIsSettingsModalOpen, - isInputMappingsModalOpen, - setIsInputMappingsModalOpen, - isReleaseNotesOpen, - setIsReleaseNotesOpen, - isAddModuleModalOpen, - setIsAddModuleModalOpen, - isManageModulesModalOpen, - setIsManageModulesModalOpen, - isDebugOverlayOpen, - setIsDebugOverlayOpen, selectedTrackForModuleMenu, setSelectedTrackForModuleMenu, - openAddModuleModal, handleCreateNewModule, handleCreateModule, handleEditModule, @@ -83,10 +62,7 @@ const Dashboard = () => { editingTemplateType, isNewModuleDialogOpen, setIsNewModuleDialogOpen, - confirmationModal, - setConfirmationModal, openAlertModal, - openConfirmationModal, debugLogs, setDebugLogs, isSequencerMuted, @@ -95,11 +71,8 @@ const Dashboard = () => { setIsProjectorReady, perfStats, setPerfStats, - editChannelModalState, - setEditChannelModalState, - handleEditChannel, handleDeleteChannel, - } = useDashboardUiState({ selectedChannel, setUserData, activeSetId }); + } = useDashboardUiState({ setUserData, activeSetId }); const userDataRef = useLatestRef(userData); const recordingDataRef = useLatestRef(recordingData); @@ -163,7 +136,6 @@ const Dashboard = () => { setInputStatus, setDebugLogs, sendToProjector, - isDebugOverlayOpen, setIsProjectorReady, }); @@ -196,7 +168,6 @@ const Dashboard = () => { useWorkspaceModules({ workspacePath, - isWorkspaceModalOpen, sendToProjector, userData, setUserData, @@ -232,7 +203,6 @@ const Dashboard = () => { setWorkspacePath, setWorkspaceModalMode, setWorkspaceModalPath, - setIsWorkspaceModalOpen, }); const handleSelectWorkspace = useCallback(async () => { @@ -289,13 +259,7 @@ const Dashboard = () => { return (
- setIsSelectTrackModalOpen(true)} - onModules={() => setIsManageModulesModalOpen(true)} - onSettings={() => setIsSettingsModalOpen(true)} - onDebugOverlay={() => setIsDebugOverlayOpen(true)} - onReleases={() => setIsReleaseNotesOpen(true)} - /> +
@@ -304,8 +268,6 @@ const Dashboard = () => { activeSetId={activeSetId} activeTrackId={activeTrackId} predefinedModules={predefinedModules} - openAddModuleModal={openAddModuleModal} - openConfirmationModal={openConfirmationModal} setActiveTrackId={setActiveTrackId} inputConfig={inputConfig} config={userData.config} @@ -333,29 +295,12 @@ const Dashboard = () => { inputStatus={inputStatus} inputConfig={inputConfig} config={userData.config} - onSettingsClick={() => setIsSettingsModalOpen(true)} isMuted={isSequencerMuted} onMuteChange={setIsSequencerMuted} isProjectorReady={isProjectorReady} /> { onCreateModule={handleCreateModule} debugLogs={debugLogs} perfStats={perfStats} - selectedChannel={selectedChannel} - setSelectedChannel={setSelectedChannel} - onEditChannel={handleEditChannel} onDeleteChannel={handleDeleteChannel} workspaceModuleFiles={workspaceModuleFiles} workspaceModuleLoadFailures={workspaceModuleLoadFailures} workspaceModuleSkipped={workspaceModuleSkipped} - editChannelModalState={editChannelModalState} - setEditChannelModalState={setEditChannelModalState} - confirmationModal={confirmationModal} - setConfirmationModal={setConfirmationModal} openAlertModal={openAlertModal} - openConfirmationModal={openConfirmationModal} /> void; - openConfirmationModal: (message: string, onConfirm: () => void) => void; setActiveTrackId: (id: string | number | null) => void; inputConfig: unknown; config: Record | null; @@ -24,8 +22,6 @@ export const DashboardBody = ({ activeSetId, activeTrackId, predefinedModules, - openAddModuleModal, - openConfirmationModal, setActiveTrackId, inputConfig, config, @@ -55,8 +51,6 @@ export const DashboardBody = ({ track={track} trackIndex={trackIndex} predefinedModules={predefinedModules} - openRightMenu={openAddModuleModal} - onConfirmDelete={openConfirmationModal} setActiveTrackId={setActiveTrackId} inputConfig={inputConfig} config={config} diff --git a/src/dashboard/components/DashboardFooter.tsx b/src/dashboard/components/DashboardFooter.tsx index 0107c31..22c0880 100644 --- a/src/dashboard/components/DashboardFooter.tsx +++ b/src/dashboard/components/DashboardFooter.tsx @@ -1,8 +1,9 @@ -import { useAtom } from "jotai"; +import { useAtom, useSetAtom } from "jotai"; import { FaPlay, FaStop } from "react-icons/fa"; import { recordingDataAtom } from "../core/state"; import { Checkbox } from "./FormInputs"; import { Button } from "./Button"; +import { settingsModalAtom } from "../core/modalAtoms"; type InputConfig = { type?: string; @@ -25,7 +26,6 @@ type DashboardFooterProps = { onStop: () => void; inputStatus: InputStatus; inputConfig: InputConfig | null; - onSettingsClick: () => void; config: DashboardConfig | null; isMuted: boolean; onMuteChange: (next: boolean) => void; @@ -39,13 +39,13 @@ export const DashboardFooter = ({ onStop, inputStatus, inputConfig, - onSettingsClick, config, isMuted, onMuteChange, isProjectorReady, }: DashboardFooterProps) => { const [_recordingData] = useAtom(recordingDataAtom); + const setSettingsModalIsOpen = useSetAtom(settingsModalAtom) const getStatusColor = () => { switch (inputStatus.status) { @@ -103,7 +103,7 @@ export const DashboardFooter = ({
No track selected
{!config?.sequencerMode && ( - - - -
@@ -55,7 +47,7 @@ export const DashboardHeader = ({
nw_wrld
- - {editingTrackIndex !== null && ( - setEditingTrackIndex(null)} - trackIndex={editingTrackIndex} - inputConfig={userData.config?.input || {}} - /> - )} + ); }; diff --git a/src/dashboard/modals/SettingsModal.tsx b/src/dashboard/modals/SettingsModal.tsx index 3eff911..e341738 100644 --- a/src/dashboard/modals/SettingsModal.tsx +++ b/src/dashboard/modals/SettingsModal.tsx @@ -11,6 +11,8 @@ import { } from "../components/FormInputs"; import { HelpIcon } from "../components/HelpIcon"; import { HELP_TEXT } from "../../shared/helpText"; +import { useAtom } from "jotai"; +import { inputMappingsModalAtom, settingsModalAtom } from "../core/modalAtoms"; const isValidHexColor = (value: string): boolean => /^#([0-9A-F]{3}){1,2}$/i.test(value); @@ -301,8 +303,6 @@ type Config = { }; type SettingsModalProps = { - isOpen: boolean; - onClose: () => void; aspectRatio: string; setAspectRatio: (ratio: string) => void; bgColor: string; @@ -314,7 +314,6 @@ type SettingsModalProps = { inputConfig: InputConfig; setInputConfig: (config: InputConfig) => void; availableMidiDevices: MidiDevice[]; - onOpenMappings: () => void; config: Config; updateConfig: (updates: Partial) => void; workspacePath: string | null; @@ -322,8 +321,6 @@ type SettingsModalProps = { }; export const SettingsModal = ({ - isOpen, - onClose, aspectRatio, setAspectRatio, bgColor, @@ -332,12 +329,16 @@ export const SettingsModal = ({ inputConfig, setInputConfig, availableMidiDevices, - onOpenMappings, config, updateConfig, workspacePath, onSelectWorkspace, }: SettingsModalProps) => { + const [isOpen, setIsOpen] = useAtom(settingsModalAtom) + const onClose = () => setIsOpen(false) + + const [_, setIsInputMappingsModalOpen] = useAtom(inputMappingsModalAtom) + const normalizedInputType = inputConfig?.type === "osc" ? "osc" : "midi"; const signalSourceValue = config.sequencerMode ? "sequencer" @@ -345,6 +346,11 @@ export const SettingsModal = ({ ? "external-osc" : "external-midi"; + const handleOpenMappings = () => { + onClose() + setIsInputMappingsModalOpen(true); + } + return ( @@ -568,7 +574,7 @@ export const SettingsModal = ({
Global Input Mappings:
-
diff --git a/src/dashboard/modals/TrackDataModal.tsx b/src/dashboard/modals/TrackDataModal.tsx index 3d96694..22d3d90 100644 --- a/src/dashboard/modals/TrackDataModal.tsx +++ b/src/dashboard/modals/TrackDataModal.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { Modal } from "../shared/Modal"; import { ModalHeader } from "../components/ModalHeader"; From 7522443e2ac269ca0a69f0794167262a6a935b5b Mon Sep 17 00:00:00 2001 From: Jury Giannelli Date: Thu, 2 Jul 2026 09:31:54 +0200 Subject: [PATCH 4/4] WIP --- src/main/InputManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/InputManager.ts b/src/main/InputManager.ts index 599d4c3..d4f96eb 100644 --- a/src/main/InputManager.ts +++ b/src/main/InputManager.ts @@ -499,7 +499,7 @@ class InputManager { })); resolve(devices); }; - webMidi.enable({ callback }); + webMidi.enable({ callback, requestMIDIAccessFunction: () => true }); }); } }