From f9e03929320210f648dc06083757dea485a0688e Mon Sep 17 00:00:00 2001 From: luckmer Date: Mon, 8 Sep 2025 20:02:23 +0200 Subject: [PATCH 01/48] modals --- src/containers/Modals/SelectPortModal.tsx | 89 +++++++++++++++++++++ src/containers/Modals/SelectboardModal.tsx | 76 ++++++++++++++++++ src/containers/Modals/index.tsx | 33 ++------ src/pages/Modals/SelectBoard.tsx | 88 +++++++++++++++++++++ src/pages/Modals/SelectPort.tsx | 91 ++++++++++++++++++++++ 5 files changed, 350 insertions(+), 27 deletions(-) create mode 100644 src/containers/Modals/SelectPortModal.tsx create mode 100644 src/containers/Modals/SelectboardModal.tsx create mode 100644 src/pages/Modals/SelectBoard.tsx create mode 100644 src/pages/Modals/SelectPort.tsx diff --git a/src/containers/Modals/SelectPortModal.tsx b/src/containers/Modals/SelectPortModal.tsx new file mode 100644 index 00000000..2cfe4f3f --- /dev/null +++ b/src/containers/Modals/SelectPortModal.tsx @@ -0,0 +1,89 @@ +import { ENotificationType, MODAL_TYPE, TITLEBAR_ACTION } from '@interfaces/enums' +import { IDropdownList } from '@interfaces/interfaces' +import SelectPort from '@pages/Modals/SelectPort' +import { espApi, UsbSerialPortInfo } from '@src/esp/api' +import { DEFAULT_PORT_NAME } from '@src/static' +import { useAppAPIContext } from '@store/context/api' +import { useAppNotificationsContext } from '@store/context/notifications' +import { useAppUIContext } from '@store/context/ui' +import { appWindow } from '@tauri-apps/api/window' +import { createEffect, onCleanup } from 'solid-js' +const SelectPortModal = () => { + const { setActivePortName, activePort, ports, setPorts } = useAppAPIContext() + const { addNotification } = useAppNotificationsContext() + const { modal, setOpenModal } = useAppUIContext() + + const loadPorts = (availablePorts: UsbSerialPortInfo[]) => { + if (ports().length === availablePorts.length) return + + if (!availablePorts.length) { + setActivePortName('', false) + setPorts([]) + return + } + + const portList: IDropdownList[] = availablePorts.map((port) => ({ + label: port.portName, + description: + port?.product && port?.manufacturer + ? `(${port.manufacturer}) ${port.product}` + : `${port.vid}:${port.pid}`, + })) + + if (activePort().autoSelect) { + setActivePortName(portList[0]?.label ?? DEFAULT_PORT_NAME, true) + } + + setPorts(portList) + } + + createEffect(() => { + const interval = setInterval(() => { + espApi + .availablePorts() + .then(loadPorts) + .catch(() => { + addNotification({ + title: 'Failed to load ports', + message: 'Failed to load ports', + type: ENotificationType.ERROR, + }) + }) + }, 250) + + onCleanup(() => clearInterval(interval)) + }) + + return ( + { + switch (action) { + case TITLEBAR_ACTION.MINIMIZE: + appWindow.minimize() + break + case TITLEBAR_ACTION.MAXIMIZE: + appWindow.toggleMaximize() + break + case TITLEBAR_ACTION.CLOSE: + appWindow.close() + break + default: + return + } + }} + onClickClose={() => { + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }} + onClickConfirmBoard={(port) => { + setActivePortName(port, false) + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }} + /> + ) +} + +export default SelectPortModal diff --git a/src/containers/Modals/SelectboardModal.tsx b/src/containers/Modals/SelectboardModal.tsx new file mode 100644 index 00000000..297d6e72 --- /dev/null +++ b/src/containers/Modals/SelectboardModal.tsx @@ -0,0 +1,76 @@ +import { MODAL_TYPE, TITLEBAR_ACTION } from '@interfaces/enums' +import { IDropdownList } from '@interfaces/interfaces' +import SelectBoard from '@pages/Modals/SelectBoard' +import { BoardDescription, supportedBoards } from '@src/static' +import { useAppAPIContext } from '@store/context/api' +import { useAppUIContext } from '@store/context/ui' +import { appWindow } from '@tauri-apps/api/window' +import { Accessor, createMemo } from 'solid-js' +import { trace } from 'tauri-plugin-log-api' +const SelectBoardModal = () => { + const { confirmFirmwareSelection, getFirmwareAssets, activeBoard } = useAppAPIContext() + const { modal, setOpenModal } = useAppUIContext() + + const boards: Accessor = createMemo(() => { + return getFirmwareAssets() + .map((item) => { + trace(`${item.name}`) + return { + label: item.name, + description: BoardDescription[item.name.replace('_release', '')] ?? '--', + } + }) + .sort((boardA, boardB) => { + const boardALabel = boardA.label.replace('_release', '') + const boardBLabel = boardB.label.replace('_release', '') + const isBoardARelease = boardA.label.includes('_release') + const isBoardBRelease = boardB.label.includes('_release') + + const boardAIsSupported = supportedBoards.includes(boardALabel) + const boardBIsSupported = supportedBoards.includes(boardBLabel) + + if (boardAIsSupported && boardBIsSupported) { + if (isBoardARelease && !isBoardBRelease) return 1 + if (!isBoardARelease && isBoardBRelease) return -1 + } + + if (boardAIsSupported && !boardBIsSupported) return -1 + if (!boardAIsSupported && boardBIsSupported) return 1 + + return 0 + }) + }) + + return ( + { + switch (action) { + case TITLEBAR_ACTION.MINIMIZE: + appWindow.minimize() + break + case TITLEBAR_ACTION.MAXIMIZE: + appWindow.toggleMaximize() + break + case TITLEBAR_ACTION.CLOSE: + appWindow.close() + break + default: + return + } + }} + onClickClose={() => { + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }} + onClickConfirmBoard={(board) => { + confirmFirmwareSelection(board) + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }} + /> + ) +} + +export default SelectBoardModal diff --git a/src/containers/Modals/index.tsx b/src/containers/Modals/index.tsx index 2c98b79a..68930e19 100644 --- a/src/containers/Modals/index.tsx +++ b/src/containers/Modals/index.tsx @@ -1,33 +1,12 @@ -import { MODAL_TYPE } from '@interfaces/enums' -import { useAppUIContext } from '@store/context/ui' -import { Match, Show, Switch } from 'solid-js' -import ApModeContainer from './ApModeModalContainer' -import BeforeFlashingModal from './BeforeFlashingContainer' -import BeforeSelectBoardModal from './BeforeSelectBoardContainer' -import WifiModal from './WifiModalcontainer' +import SelectBoardModal from './SelectboardModal' +import SelectPortModal from './SelectPortModal' export const ModalRoot = () => { - const { modal } = useAppUIContext() - return ( - -
- - - - - - - - - - - - - - -
-
+ <> + + + ) } diff --git a/src/pages/Modals/SelectBoard.tsx b/src/pages/Modals/SelectBoard.tsx new file mode 100644 index 00000000..1c0c4a4b --- /dev/null +++ b/src/pages/Modals/SelectBoard.tsx @@ -0,0 +1,88 @@ +import DefaultBoard from '@components/Board/DefaultBoard' +import Input from '@components/Inputs/Input' +import { Modal } from '@components/Modal' +import ModalHeader from '@components/ModalHeader' +import Typography from '@components/Typography' +import { TITLEBAR_ACTION } from '@interfaces/enums' +import { IDropdownList } from '@interfaces/interfaces' +import { beforeSelectBoardModalID } from '@src/static' +import { BsSearch } from 'solid-icons/bs' +import { Component, createMemo, createSignal, For, Show } from 'solid-js' + +export interface IProps { + onClickHeader: (action: TITLEBAR_ACTION) => void + onClickConfirmBoard: (board: string) => void + onClickClose: () => void + isActive: boolean + version: string + boards: IDropdownList[] + activeBoard: string +} + +const SelectBoard: Component = (props) => { + const [search, setSearch] = createSignal('') + + const filteredData = createMemo(() => { + return props.boards.filter((el) => el.label.toLowerCase().includes(search().toLowerCase())) + }) + + return ( + { + props.onClickClose() + setSearch('') + }} + onClickHeader={props.onClickHeader}> +
+ { + props.onClickClose() + setSearch('') + }} + /> +
+ + Look for a board + + setSearch(e)} + /> +
+
+ 0} + fallback={ +
+ +
+ }> + + {(data) => ( + { + const el = document.getElementById(beforeSelectBoardModalID) + if (el instanceof HTMLDialogElement) { + el.close() + } + props.onClickConfirmBoard(data.label) + }} + /> + )} + +
+
+
+
+ ) +} + +export default SelectBoard diff --git a/src/pages/Modals/SelectPort.tsx b/src/pages/Modals/SelectPort.tsx new file mode 100644 index 00000000..3c24dc49 --- /dev/null +++ b/src/pages/Modals/SelectPort.tsx @@ -0,0 +1,91 @@ +import DefaultBoard from '@components/Board/DefaultBoard' +import Input from '@components/Inputs/Input' +import { Modal } from '@components/Modal' +import ModalHeader from '@components/ModalHeader' +import Typography from '@components/Typography' +import { TITLEBAR_ACTION } from '@interfaces/enums' +import { IDropdownList } from '@interfaces/interfaces' +import { beforeSelectBoardModalID, SELECT_PORT_MODAL_ID } from '@src/static' +import { BsSearch } from 'solid-icons/bs' +import { Component, createMemo, createSignal, For, Show } from 'solid-js' + +export interface IProps { + onClickHeader: (action: TITLEBAR_ACTION) => void + onClickConfirmBoard: (board: string) => void + onClickClose: () => void + isActive: boolean + version: string + ports: IDropdownList[] + activeBoard: string +} + +const SelectPort: Component = (props) => { + const [search, setSearch] = createSignal('') + + const filteredData = createMemo(() => { + return props.ports.filter((el) => el.label.toLowerCase().includes(search().toLowerCase())) + }) + + return ( + { + props.onClickClose() + setSearch('') + }} + onClickHeader={props.onClickHeader}> +
+ { + props.onClickClose() + setSearch('') + }} + /> +
+ + Search for a port… + + setSearch(e)} + /> +
+
+ 0} + fallback={ +
+ + + Searching for data + +
+ }> + + {(data) => ( + { + const el = document.getElementById(SELECT_PORT_MODAL_ID) + if (el instanceof HTMLDialogElement) { + el.close() + } + props.onClickConfirmBoard(data.label) + }} + /> + )} + +
+
+
+
+ ) +} + +export default SelectPort From ca35fa73aa09e914c2c9b93aa06873fdfc7f6e94 Mon Sep 17 00:00:00 2001 From: luckmer Date: Mon, 8 Sep 2025 20:03:40 +0200 Subject: [PATCH 02/48] remove progressbar --- src/components/Header/index.tsx | 41 ++++---------------- src/components/ProgressBar/index.tsx | 42 -------------------- src/components/ProgressBar/styles.css | 16 -------- src/containers/Header/index.tsx | 55 +-------------------------- src/routes/index.tsx | 3 +- src/static/index.ts | 29 +------------- src/static/types/enums.ts | 14 +------ src/store/context/api.tsx | 2 +- 8 files changed, 16 insertions(+), 186 deletions(-) delete mode 100644 src/components/ProgressBar/index.tsx delete mode 100644 src/components/ProgressBar/styles.css diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index b4e70a29..d87e98dd 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,5 +1,4 @@ -import HeaderButton from '@components/Buttons/HeaderButton' -import { ProgressBar } from '@components/ProgressBar' +import DefaultButton from '@components/Buttons/DefaultButton' import Typography from '@components/Typography' import { TITLEBAR_ACTION } from '@interfaces/enums' import { classNames } from '@src/utils' @@ -8,9 +7,7 @@ import { Component, Show } from 'solid-js' interface IProps { onClickHome?: () => void onClick: (action: TITLEBAR_ACTION) => void - step?: { step: string; description: string; dashoffset: string; index: string } appVersion?: string - currentStep?: string docs?: boolean } @@ -25,9 +22,7 @@ const Header: Component = (props) => { data-tauri-drag-region>
-
props.onClickHome?.()}> +
= (props) => {
- = (props) => { - - + = (props) => { - - + = (props) => { d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z" /> - +
- -
- -
- - {props?.step?.step ?? '0'} - - - {props?.step?.description ?? '--'} - -
-
-
) diff --git a/src/components/ProgressBar/index.tsx b/src/components/ProgressBar/index.tsx deleted file mode 100644 index a3f1f2bb..00000000 --- a/src/components/ProgressBar/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import Typography from '@components/Typography' -import { radius } from '@src/static' -import { Component } from 'solid-js' -import './styles.css' - -export interface IProps { - currentStep: string - dashoffset: string -} - -export const ProgressBar: Component = (props) => { - return ( -
-
- - {props.currentStep} - -
- - - - -
- ) -} diff --git a/src/components/ProgressBar/styles.css b/src/components/ProgressBar/styles.css deleted file mode 100644 index 2093b1cb..00000000 --- a/src/components/ProgressBar/styles.css +++ /dev/null @@ -1,16 +0,0 @@ -#svg circle { - transition: stroke-dashoffset 1s linear; - stroke: #192736; -} - -#svg #bar { - stroke: #9092FF; -} - - -.step { -position: absolute; -left: 50%; -top: 50%; -transform: translate(-50%,-50%); -} \ No newline at end of file diff --git a/src/containers/Header/index.tsx b/src/containers/Header/index.tsx index c5aab5e8..cd138adf 100644 --- a/src/containers/Header/index.tsx +++ b/src/containers/Header/index.tsx @@ -1,51 +1,11 @@ import Header from '@components/Header' -import { useLocation, useNavigate } from '@solidjs/router' -import { stepStatus, usb } from '@src/static' -import { DIRECTION, ENotificationType, TITLEBAR_ACTION } from '@src/static/types/enums' -import { useAppAPIContext } from '@store/context/api' -import { useAppNotificationsContext } from '@store/context/notifications' -import { isActiveProcess } from '@store/terminal/selectors' -import { setAbortController } from '@store/terminal/terminal' +import { TITLEBAR_ACTION } from '@src/static/types/enums' import { appWindow } from '@tauri-apps/api/window' -import { createMemo } from 'solid-js' export const HeaderRoot = () => { - const { addNotification } = useAppNotificationsContext() - const { activeBoard } = useAppAPIContext() - - const location = useLocation() - const navigate = useNavigate() - - const isUSBBoardActive = createMemo(() => { - return activeBoard().includes(usb) ? 1 : 0 - }) - - const shouldHideStepIndicator = createMemo(() => { - return typeof stepStatus[DIRECTION[location.pathname]] === 'undefined' - }) - - const computedStepIndex = createMemo(() => { - if (!shouldHideStepIndicator()) { - const index = stepStatus[DIRECTION[location.pathname]]?.index - isUSBBoardActive() - return index <= 0 ? 1 : index - } - return 1 - }) - - const formattedCurrentStep = createMemo(() => { - if (shouldHideStepIndicator()) return undefined - return `${computedStepIndex()}/${Object.values(stepStatus).length - isUSBBoardActive()}` - }) - - const stepDetails = createMemo(() => ({ - ...stepStatus[DIRECTION[location.pathname]], - step: `Step ${computedStepIndex()}`, - })) - return (
{ switch (action) { case TITLEBAR_ACTION.MINIMIZE: @@ -61,19 +21,6 @@ export const HeaderRoot = () => { return } }} - onClickHome={() => { - if (isActiveProcess()) { - addNotification({ - title: 'There is an active installation. Please wait.', - message: 'There is an active installation. Please wait.', - type: ENotificationType.INFO, - }) - return true - } - setAbortController() - navigate('/') - }} - currentStep={formattedCurrentStep()} /> ) } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 678d0622..a975301b 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -5,10 +5,11 @@ const NetworkConfigurator = lazy(() => import('@containers/ManageNetwork')) const BoardConfigurator = lazy(() => import('@containers/ManageBoard')) const FlashFirmware = lazy(() => import('@containers/FlashFirmware')) const page404 = lazy(() => import('@containers/404/[...404]')) +const FlashWizard = lazy(() => import('@containers/FlashWizard')) export const routes: RouteDefinition[] = [ { path: '/flashFirmware', component: FlashFirmware }, { path: '/network', component: NetworkConfigurator }, - { path: '/', component: BoardConfigurator }, + { path: '/', component: FlashWizard }, { path: '**', component: page404 }, ] diff --git a/src/static/index.ts b/src/static/index.ts index ad16e710..c1c8bc81 100644 --- a/src/static/index.ts +++ b/src/static/index.ts @@ -1,5 +1,5 @@ -import { BOARD_TYPE, CHANNEL_TYPE, STEP_STATUS_ENUM } from './types/enums' import { type IChannelOptions } from '@interfaces/interfaces' +import { BOARD_TYPE, CHANNEL_TYPE } from './types/enums' export const supportedBoards: string[] = [BOARD_TYPE.XIAOSENSES_3, BOARD_TYPE.XIAOSENSES_3_USB] export const debugModes: string[] = ['off', 'error', 'warn', 'info', 'debug', 'trace'] @@ -14,6 +14,7 @@ export const logsModalID = 'logs' export const wifiModalID = 'wifiMode' export const beforeFlashingModalID = 'beforeFlashingMode' export const beforeSelectBoardModalID = 'BeforeSelectBoardMode' +export const SELECT_PORT_MODAL_ID = 'SELECT_PORT_MODAL_ID' export const debugModalId = 'debugModal' export const staticMdns = 'openiristracker' export const DEVICE_LOST = 'The device has been lost.' @@ -22,32 +23,6 @@ export const SSID_MISSING = 'ssid missing' export const AP_IP_ADDRESS = 'AP IP address:' export const DEFAULT_PORT_NAME = 'auto' -const circleSize = Math.PI * (radius * 2) - -export const stepStatus: { - [key in STEP_STATUS_ENUM]: { - description: string - dashoffset: string - index: string - } -} = { - [STEP_STATUS_ENUM.SELECT_BOARD]: { - index: '1', - description: 'Select board', - dashoffset: ((105 / 100) * circleSize).toString(), - }, - [STEP_STATUS_ENUM.CONFIGURE_WIFI]: { - index: '2', - description: 'Configure wifi network', - dashoffset: (((105 - 50) / 100) * circleSize).toString(), - }, - [STEP_STATUS_ENUM.FLASH_FIRMWARE]: { - index: '3', - description: 'Flash firmware assets', - dashoffset: (((100 - 100) / 100) * circleSize).toString(), - }, -} - export const BoardDescription: { [key in BOARD_TYPE]: string } = { diff --git a/src/static/types/enums.ts b/src/static/types/enums.ts index 762332ad..dee57252 100644 --- a/src/static/types/enums.ts +++ b/src/static/types/enums.ts @@ -84,18 +84,6 @@ export enum ESPEndpoints { OTA = '/update', } -export enum STEP_STATUS_ENUM { - CONFIGURE_WIFI = 'CONFIGURE_WIFI', - SELECT_BOARD = 'SELECT_BOARD', - FLASH_FIRMWARE = 'FLASH_FIRMWARE', -} - -export enum DIRECTION { - '/' = STEP_STATUS_ENUM.SELECT_BOARD, - '/network' = STEP_STATUS_ENUM.CONFIGURE_WIFI, - '/flashFirmware' = STEP_STATUS_ENUM.FLASH_FIRMWARE, -} - export enum BOARD_TYPE { BABBLE_WROOMS_S3 = 'Babble_wrooms_s3', BABBLE_WROOMS_S3_RELEASE = 'Babble_wrooms_s3_release', @@ -143,6 +131,8 @@ export const enum FLASH_STATUS { } export enum MODAL_TYPE { + SELECT_BOARD = 'SELECT_BOARD', + SELECT_PORT = 'SELECT_PORT', BEFORE_SELECT_BOARD = 'BEFORE_SELECT_BOARD', UPDATE_NETWORK = 'UPDATE_NETWORK', BEFORE_FLASHING = 'BEFORE_FLASHING', diff --git a/src/store/context/api.tsx b/src/store/context/api.tsx index 769a7386..d7a1ebfe 100644 --- a/src/store/context/api.tsx +++ b/src/store/context/api.tsx @@ -117,7 +117,7 @@ export const AppAPIProvider: Component = (props) => { mdns: '', manifestPath: '', activePort: { - activePortName: DEFAULT_PORT_NAME, + activePortName: '', autoSelect: true, }, ports: [], From a9e3e810aa21e3953a64c83245045a9ec08babf9 Mon Sep 17 00:00:00 2001 From: luckmer Date: Mon, 8 Sep 2025 22:08:01 +0200 Subject: [PATCH 03/48] store --- src/Animation/index.tsx | 32 +++++++ .../Modals/BeforeFlashingContainer.tsx | 84 ------------------- ...reFlashingModal.tsx => BeforeFlashing.tsx} | 24 ++++-- src/static/types/enums.ts | 14 ++++ src/store/animation/animation.ts | 53 ++++++++++++ src/store/animation/selectors.ts | 4 + src/store/terminal/selectors.ts | 20 +---- src/store/utils/index.ts | 18 ++++ 8 files changed, 140 insertions(+), 109 deletions(-) create mode 100644 src/Animation/index.tsx delete mode 100644 src/containers/Modals/BeforeFlashingContainer.tsx rename src/pages/Modals/{BeforeFlashingModal.tsx => BeforeFlashing.tsx} (79%) create mode 100644 src/store/animation/animation.ts create mode 100644 src/store/animation/selectors.ts create mode 100644 src/store/utils/index.ts diff --git a/src/Animation/index.tsx b/src/Animation/index.tsx new file mode 100644 index 00000000..bbfe67a1 --- /dev/null +++ b/src/Animation/index.tsx @@ -0,0 +1,32 @@ +import { ACTION } from '@interfaces/enums' +import { setActiveStep, setShowComponent } from '@store/animation/animation' +import { action, activeStep, showComponent, step } from '@store/animation/selectors' +import { createMemo, ParentComponent } from 'solid-js' + +const SwipeAnimation: ParentComponent = (props) => { + const animationClass = createMemo(() => { + if (step() !== activeStep()) { + return action() === ACTION.NEXT ? 'animate-slide-left-exit' : 'animate-slide-right-exit' + } + return action() === ACTION.NEXT ? 'animate-slide-right-enter' : 'animate-slide-left-enter' + }) + + const handleAnimationEnd = () => { + if (step() !== activeStep()) { + setActiveStep(step()) + setShowComponent(true) + } + } + + return ( +
setShowComponent(false)} + style={!showComponent() ? { opacity: '0' } : { opacity: '1' }}> + {props.children} +
+ ) +} + +export default SwipeAnimation diff --git a/src/containers/Modals/BeforeFlashingContainer.tsx b/src/containers/Modals/BeforeFlashingContainer.tsx deleted file mode 100644 index 23f5c413..00000000 --- a/src/containers/Modals/BeforeFlashingContainer.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { ENotificationType, MODAL_TYPE, TITLEBAR_ACTION } from '@interfaces/enums' -import BeforeFlashingModal from '@pages/Modals/BeforeFlashingModal' -import { usb } from '@src/static' -import { useAppAPIContext } from '@store/context/api' -import { useAppNotificationsContext } from '@store/context/notifications' -import { useAppUIContext } from '@store/context/ui' -import { installOpenIris } from '@store/terminal/actions' -import { isActiveProcess } from '@store/terminal/selectors' -import { - restartFirmwareState, - setAbortController, - setProcessStatus, -} from '@store/terminal/terminal' -import { appWindow } from '@tauri-apps/api/window' -import { createMemo } from 'solid-js' - -const BeforeFlashingContainer = () => { - const { downloadAsset, getFirmwareType, activeBoard, activePort } = useAppAPIContext() - const { modal, setOpenModal, hideModal, setHideModal } = useAppUIContext() - const { addNotification } = useAppNotificationsContext() - - const isUSBBoard = createMemo(() => { - return activeBoard().includes(usb) - }) - - const activePortName = createMemo(() => { - return activePort().activePortName - }) - - return ( - { - switch (action) { - case TITLEBAR_ACTION.MINIMIZE: - appWindow.minimize() - break - case TITLEBAR_ACTION.MAXIMIZE: - appWindow.toggleMaximize() - break - case TITLEBAR_ACTION.CLOSE: - appWindow.close() - break - default: - return - } - }} - onClickClose={() => { - setOpenModal({ open: false, type: MODAL_TYPE.NONE }) - }} - onClickCheckbox={() => { - setHideModal() - }} - onClickInstallOpeniris={() => { - setOpenModal({ open: false, type: MODAL_TYPE.NONE }) - if (isActiveProcess()) { - addNotification({ - title: 'There is an active installation. Please wait.', - message: 'There is an active installation. Please wait.', - type: ENotificationType.INFO, - }) - return true - } - setAbortController('openiris') - setProcessStatus(true) - restartFirmwareState() - installOpenIris( - isUSBBoard(), - activePortName(), - async () => { - await downloadAsset(getFirmwareType()) - }, - () => { - setOpenModal({ open: true, type: MODAL_TYPE.UPDATE_NETWORK }) - }, - ).catch(() => ({})) - }} - /> - ) -} - -export default BeforeFlashingContainer diff --git a/src/pages/Modals/BeforeFlashingModal.tsx b/src/pages/Modals/BeforeFlashing.tsx similarity index 79% rename from src/pages/Modals/BeforeFlashingModal.tsx rename to src/pages/Modals/BeforeFlashing.tsx index 8198b82e..24895c2d 100644 --- a/src/pages/Modals/BeforeFlashingModal.tsx +++ b/src/pages/Modals/BeforeFlashing.tsx @@ -17,7 +17,7 @@ export interface IProps { version: string } -const BeforeFlashingModal: Component = (props) => { +const BeforeFlashing: Component = (props) => { return ( = (props) => { checked={props.checked} label="Don’t show this again" /> - + ) +} + +export default PrimaryButton diff --git a/src/components/Buttons/SelectButton/index.tsx b/src/components/Buttons/SelectButton/index.tsx index 41735c3f..e870efc0 100644 --- a/src/components/Buttons/SelectButton/index.tsx +++ b/src/components/Buttons/SelectButton/index.tsx @@ -1,24 +1,26 @@ import Typography from '@components/Typography' -import { Component } from 'solid-js' +import { Component, Show } from 'solid-js' export interface IProps { type?: 'submit' | 'reset' | 'button' | undefined label: string onClick?: () => void tabIndex?: number - header: string + header?: string } export const SelectButton: Component = (props) => { return (
- - {props.header} - + + + {props.header} + +
+ + ) +} + +export default Card diff --git a/src/components/Dropdown/PortDropdown/index.tsx b/src/components/Dropdown/PortDropdown/index.tsx index cf9ed86a..de989ded 100644 --- a/src/components/Dropdown/PortDropdown/index.tsx +++ b/src/components/Dropdown/PortDropdown/index.tsx @@ -16,7 +16,7 @@ export interface IProps { const PortDropdown: Component = (props) => { return ( - + { + const { downloadAsset, getFirmwareType, activeBoard, activePort } = useAppAPIContext() + const { modal, setOpenModal, hideModal, setHideModal } = useAppUIContext() + const { addNotification } = useAppNotificationsContext() + + const isUSBBoard = createMemo(() => { + return activeBoard().includes(usb) + }) + + const activePortName = createMemo(() => { + return activePort().activePortName + }) + + return ( + { + switch (action) { + case TITLEBAR_ACTION.MINIMIZE: + appWindow.minimize() + break + case TITLEBAR_ACTION.MAXIMIZE: + appWindow.toggleMaximize() + break + case TITLEBAR_ACTION.CLOSE: + appWindow.close() + break + default: + return + } + }} + onClickClose={() => { + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }} + onClickCheckbox={() => { + setHideModal() + }} + onClickInstallOpeniris={() => { + batch(() => { + setAction(ACTION.NEXT) + setStep(FLASH_WIZARD_STEPS.FLASH_PROCESS) + setOpenModal({ open: false, type: MODAL_TYPE.NONE }) + }) + if (isActiveProcess()) { + addNotification({ + title: 'There is an active installation. Please wait.', + message: 'There is an active installation. Please wait.', + type: ENotificationType.INFO, + }) + return true + } + setAbortController('openiris') + setProcessStatus(true) + restartFirmwareState() + installOpenIris( + isUSBBoard(), + activePortName(), + async () => { + await downloadAsset(getFirmwareType()) + }, + () => { + setOpenModal({ open: true, type: MODAL_TYPE.UPDATE_NETWORK }) + }, + ).catch(() => ({})) + }} + /> + ) +} + +export default BeforeFlashingModal diff --git a/src/containers/Modals/index.tsx b/src/containers/Modals/index.tsx index 68930e19..26084c96 100644 --- a/src/containers/Modals/index.tsx +++ b/src/containers/Modals/index.tsx @@ -1,3 +1,4 @@ +import BeforeFlashingModal from './BeforeFlashingModal' import SelectBoardModal from './SelectboardModal' import SelectPortModal from './SelectPortModal' @@ -6,6 +7,7 @@ export const ModalRoot = () => { <> + ) } diff --git a/src/pages/Modals/SelectBoard.tsx b/src/pages/Modals/SelectBoard.tsx index 1c0c4a4b..b93eef38 100644 --- a/src/pages/Modals/SelectBoard.tsx +++ b/src/pages/Modals/SelectBoard.tsx @@ -55,7 +55,7 @@ const SelectBoard: Component = (props) => { onChange={(e) => setSearch(e)} /> -
+
0} fallback={ From 25f104a4346807cfaa5a02871196322c9b16c1d0 Mon Sep 17 00:00:00 2001 From: luckmer Date: Tue, 9 Sep 2025 20:07:52 +0200 Subject: [PATCH 05/48] update modals workflow --- src/components/DevTools/index.tsx | 129 ------------------ src/components/Modal/index.tsx | 16 ++- .../Modals/ApModeModalContainer.tsx | 4 +- src/containers/Modals/BeforeFlashingModal.tsx | 28 ++-- .../Modals/BeforeSelectBoardContainer.tsx | 4 +- src/containers/Modals/DevtoolsModal.tsx | 52 +++++++ src/containers/Modals/SelectPortModal.tsx | 9 +- src/containers/Modals/SelectboardModal.tsx | 63 +++++---- src/containers/Modals/index.tsx | 2 + ...reFlashing.tsx => BeforeFlashingModal.tsx} | 4 +- ...ctBoard.tsx => BeforeSelectBoardModal.tsx} | 4 +- src/pages/Modals/DevtoolsModal.tsx | 77 +++++++++++ .../{SelectBoard.tsx => SelectBoardModal.tsx} | 4 +- .../{SelectPort.tsx => SelectPortModal.tsx} | 6 +- src/static/index.ts | 1 + src/static/types/enums.ts | 5 + 16 files changed, 211 insertions(+), 197 deletions(-) delete mode 100644 src/components/DevTools/index.tsx create mode 100644 src/containers/Modals/DevtoolsModal.tsx rename src/pages/Modals/{BeforeFlashing.tsx => BeforeFlashingModal.tsx} (97%) rename src/pages/Modals/{BeforeSelectBoard.tsx => BeforeSelectBoardModal.tsx} (95%) create mode 100644 src/pages/Modals/DevtoolsModal.tsx rename src/pages/Modals/{SelectBoard.tsx => SelectBoardModal.tsx} (97%) rename src/pages/Modals/{SelectPort.tsx => SelectPortModal.tsx} (95%) diff --git a/src/components/DevTools/index.tsx b/src/components/DevTools/index.tsx deleted file mode 100644 index b918feb5..00000000 --- a/src/components/DevTools/index.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { SelectButton } from '@components/Buttons/SelectButton' -import Dropdown from '@components/Dropdown/Dropdown' -import DropdownList from '@components/Dropdown/DropdownList' -import Header from '@components/Header' -import ModalHeader from '@components/ModalHeader' -import { type CHANNEL_TYPE, type TITLEBAR_ACTION } from '@interfaces/enums' -import { IDropdownList } from '@interfaces/interfaces' -import { IEventType } from '@interfaces/types' -import theme from '@src/common/theme' -import { debugModalId } from '@src/static' -import { FaSolidGear } from 'solid-icons/fa' -import { type Component, onMount } from 'solid-js' - -export interface IProps { - onClickHeader: (action: TITLEBAR_ACTION) => void - onClickSetChannelMode: (data: string) => void - setDebugMode: (debugMode: string) => void - onClickOpenModal: (id: string) => void - channelOptions: IDropdownList[] - debugModes: IDropdownList[] - channelMode: CHANNEL_TYPE - debugMode: string - version: string -} - -export const Devtools: Component = (props) => { - let debugModeTab: HTMLDivElement | undefined = undefined - let versionTab: HTMLDivElement | undefined = undefined - - onMount(() => { - if (debugModeTab) debugModeTab.style.opacity = '0' - if (versionTab) versionTab.style.opacity = '0' - }) - - return ( -
- - -
-
-
- -
-
- ) -} diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 2db8b3b6..ebd45c66 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -1,6 +1,7 @@ import Header from '@components/Header' import { type TITLEBAR_ACTION } from '@src/static/types/enums' -import { Component, createEffect, JSX } from 'solid-js' +import { classNames } from '@src/utils' +import { Component, createEffect, createMemo, JSX } from 'solid-js' export interface IProps { onClickHeader: (action: TITLEBAR_ACTION) => void @@ -10,6 +11,7 @@ export interface IProps { children: JSX.Element isSending?: boolean version: string + width?: string } export const Modal: Component = (props) => { @@ -22,13 +24,21 @@ export const Modal: Component = (props) => { } }) + const width = createMemo(() => { + return props.width ?? 'w-[500px]' + }) + return (
-