├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ └── config.yml ├── funding.yml └── workflows │ ├── cd.yml │ └── ci.yml ├── .gitignore ├── .vscode ├── extensions.json ├── freeter.code-snippets └── settings.json ├── COPYING ├── README.md ├── backers.json ├── electron-builder.config.js ├── eslint.config.mjs ├── jest.config.js ├── package.json ├── resources ├── darwin │ ├── dmgBg.png │ ├── dmgBg@2x.png │ └── freeter.icns ├── linux │ └── freeter-icons │ │ ├── 1024x1024.png │ │ ├── 128x128.png │ │ ├── 16x16.png │ │ ├── 256x256.png │ │ ├── 32x32.png │ │ ├── 48x48.png │ │ ├── 512x512.png │ │ └── 64x64.png └── win32 │ └── freeter.ico ├── src ├── assets │ └── app-icons │ │ ├── 16.png │ │ └── 256.png ├── common │ ├── application │ │ └── interfaces │ │ │ ├── dataStorage.ts │ │ │ └── store.ts │ ├── base │ │ ├── dialog.ts │ │ ├── menu.ts │ │ ├── objectManager.ts │ │ ├── process.ts │ │ ├── userAgent.ts │ │ └── versionedObject.ts │ ├── data │ │ ├── stateStorage.ts │ │ └── store.ts │ ├── helpers │ │ ├── debounce.ts │ │ ├── deepFreeze.ts │ │ └── sanitizeUrl.ts │ ├── infra │ │ ├── dataStorage │ │ │ ├── inMemoryDataStorage.ts │ │ │ ├── setTextOnlyIfChanged.ts │ │ │ └── withJson.ts │ │ └── network.ts │ ├── ipc │ │ ├── channels.ts │ │ └── ipc.ts │ └── tsconfig.json ├── main │ ├── application │ │ ├── interfaces │ │ │ ├── appMenuProvider.ts │ │ │ ├── appsProvider.ts │ │ │ ├── browserWindow.ts │ │ │ ├── childProcessProvider.ts │ │ │ ├── clipboardProvider.ts │ │ │ ├── contextMenuProvider.ts │ │ │ ├── dialogProvider.ts │ │ │ ├── globalShortcutProvider.ts │ │ │ ├── processProvider.ts │ │ │ ├── shellProvider.ts │ │ │ ├── store.ts │ │ │ ├── trayProvider.ts │ │ │ └── webContents.ts │ │ └── useCases │ │ │ ├── appDataStorage │ │ │ ├── deleteInAppDataStorage.ts │ │ │ ├── getTextFromAppDataStorage.ts │ │ │ └── setTextInAppDataStorage.ts │ │ │ ├── appMenu │ │ │ ├── setAppMenu.ts │ │ │ └── setAppMenuAutoHide.ts │ │ │ ├── browserWindow │ │ │ ├── getWindowState.ts │ │ │ ├── setWindowState.ts │ │ │ └── showBrowserWindow.ts │ │ │ ├── clipboard │ │ │ ├── writeBookmarkIntoClipboard.ts │ │ │ └── writeTextIntoClipboard.ts │ │ │ ├── contextMenu │ │ │ └── popupContextMenu.ts │ │ │ ├── dialog │ │ │ ├── showMessageBox.ts │ │ │ ├── showOpenDirDialog.ts │ │ │ ├── showOpenFileDialog.ts │ │ │ └── showSaveFileDialog.ts │ │ │ ├── globalShortcut │ │ │ └── setMainShortcut.ts │ │ │ ├── process │ │ │ └── getProcessInfo.ts │ │ │ ├── shell │ │ │ ├── openApp.ts │ │ │ ├── openExternalUrl.ts │ │ │ └── openPath.ts │ │ │ ├── terminal │ │ │ └── execCmdLinesInTerminal.ts │ │ │ ├── tray │ │ │ ├── initTray.ts │ │ │ ├── setTrayMenu.ts │ │ │ └── showAppAction.ts │ │ │ └── widgetDataStorage │ │ │ ├── clearWidgetDataStorage.ts │ │ │ ├── copyWidgetDataStorage.ts │ │ │ ├── deleteInWidgetDataStorage.ts │ │ │ ├── getKeysFromWidgetDataStorage.ts │ │ │ ├── getTextFromWidgetDataStorage.ts │ │ │ └── setTextInWidgetDataStorage.ts │ ├── base │ │ ├── apps │ │ │ └── terminal.ts │ │ └── state │ │ │ └── window.ts │ ├── controllers │ │ ├── appDataStorage.ts │ │ ├── appMenu.ts │ │ ├── browserWindow.ts │ │ ├── clipboard.ts │ │ ├── contextMenu.ts │ │ ├── controller.ts │ │ ├── dialog.ts │ │ ├── globalShortcut.ts │ │ ├── interfaces │ │ │ └── ipcMain.ts │ │ ├── process.ts │ │ ├── shell.ts │ │ ├── terminal.ts │ │ ├── trayMenu.ts │ │ └── widgetDataStorage.ts │ ├── data │ │ ├── windowStateStorage.ts │ │ └── windowStore.ts │ ├── eslint.config.mjs │ ├── index.ts │ ├── infra │ │ ├── appMenuProvider │ │ │ └── appMenuProvider.ts │ │ ├── appsProvider │ │ │ ├── appsProvider.ts │ │ │ └── detectDefaultTerminal.ts │ │ ├── browserWindow │ │ │ └── browserWindow.ts │ │ ├── childProcessProvider │ │ │ └── childProcessProvider.ts │ │ ├── clipboardProvider │ │ │ └── clipboardProvider.ts │ │ ├── contextMenuProvider │ │ │ └── contextMenuProvider.ts │ │ ├── dataStorage │ │ │ └── fileDataStorage.ts │ │ ├── dialogProvider │ │ │ └── dialogProvider.ts │ │ ├── globalShortcut │ │ │ └── globalShortcutProvider.ts │ │ ├── ipcMain │ │ │ ├── ipcMain.ts │ │ │ └── ipcMainEventValidator.ts │ │ ├── processProvider │ │ │ └── processProvider.ts │ │ ├── protocolHandler │ │ │ ├── protocolHandler.ts │ │ │ └── registerAppFileProtocol.ts │ │ ├── shellProvider │ │ │ └── shellProvider.ts │ │ ├── trayProvider │ │ │ └── trayProvider.ts │ │ └── utils │ │ │ └── menu.ts │ └── tsconfig.json └── renderer │ ├── application │ ├── interfaces │ │ ├── appMenuProvider.ts │ │ ├── browserWindowProvider.ts │ │ ├── clipboardProvider.ts │ │ ├── contextMenuProvider.ts │ │ ├── dataStorage.ts │ │ ├── dialogProvider.ts │ │ ├── globalShortcutProvider.ts │ │ ├── idGenerator.ts │ │ ├── processProvider.ts │ │ ├── productInfoProvider.ts │ │ ├── registry.ts │ │ ├── shellProvider.ts │ │ ├── store.ts │ │ ├── terminalProvider.ts │ │ └── trayMenuProvider.ts │ └── useCases │ │ ├── about │ │ ├── closeAbout.ts │ │ ├── getAboutInfo.ts │ │ ├── openAbout.ts │ │ └── openSponsorshipUrl.ts │ │ ├── actionBar │ │ └── clickActionBarItem.ts │ │ ├── appManager │ │ ├── addAppInAppManager.ts │ │ ├── closeAppManager.ts │ │ ├── duplicateAppInAppManager.ts │ │ ├── openAppManager.ts │ │ ├── saveChangesInAppManager.ts │ │ ├── switchAppInAppManager.ts │ │ ├── toggleDeletionInAppManager.ts │ │ ├── updateAppSettingsInAppManager.ts │ │ └── updateAppsOrderInAppManager.ts │ │ ├── appMenu │ │ ├── clickAppMenuItem.ts │ │ └── initAppMenu.ts │ │ ├── applicationSettings │ │ ├── closeApplicationSettings.ts │ │ ├── getMainHotkeyOptions.ts │ │ ├── openApplicationSettings.ts │ │ ├── saveApplicationSettings.ts │ │ └── updateApplicationSettings.ts │ │ ├── browserWindow │ │ └── showBrowserWindow.ts │ │ ├── contextMenu │ │ ├── clickContextMenuItem.ts │ │ └── showContextMenu.ts │ │ ├── dialog │ │ └── showOpenFileDialog.ts │ │ ├── dragDrop │ │ ├── dragEnd.ts │ │ ├── dragLeaveTarget.ts │ │ ├── dragOverTopBarList.ts │ │ ├── dragOverWorkflowSwitcher.ts │ │ ├── dragOverWorktableLayout.ts │ │ ├── dragWidgetFromPalette.ts │ │ ├── dragWidgetFromTopBarList.ts │ │ ├── dragWidgetFromWorktableLayout.ts │ │ ├── dragWorkflowFromWorkflowSwitcher.ts │ │ ├── dropOnTopBarList.ts │ │ ├── dropOnWorkflowSwitcher.ts │ │ └── dropOnWorktableLayout.ts │ │ ├── globalShortcut │ │ └── initMainShortcut.ts │ │ ├── memSaver │ │ ├── deactivateWorkflow.ts │ │ ├── initMemSaver.ts │ │ └── subs │ │ │ ├── activateProjectWorkflows.ts │ │ │ ├── activateWorkflow.ts │ │ │ ├── deactivateWorkflow.ts │ │ │ ├── resetDelayedWorkflowDeactivation.ts │ │ │ ├── scheduleProjectWorkflowsDeactivation.ts │ │ │ ├── scheduleWorkflowDeactivation.ts │ │ │ └── startDelayedWorkflowDeactivation.ts │ │ ├── project │ │ └── subs │ │ │ ├── deleteProjects.ts │ │ │ └── setCurrentWorkflow.ts │ │ ├── projectManager │ │ ├── addProjectInProjectManager.ts │ │ ├── closeProjectManager.ts │ │ ├── duplicateProjectInProjectManager.ts │ │ ├── openProjectManager.ts │ │ ├── saveChangesInProjectManager.ts │ │ ├── switchProjectInProjectManager.ts │ │ ├── toggleDeletionInProjectManager.ts │ │ ├── updateProjectSettingsInProjectManager.ts │ │ └── updateProjectsOrderInProjectManager.ts │ │ ├── projectSwitcher │ │ ├── subs │ │ │ └── setCurrentProject.ts │ │ └── switchProject.ts │ │ ├── shelf │ │ ├── addWidgetToShelf.ts │ │ ├── pasteWidgetToShelf.ts │ │ └── subs │ │ │ ├── addItemToWidgetList.ts │ │ │ ├── cloneWidgetToWidgetList.ts │ │ │ └── deleteWidgetsFromWidgetList.ts │ │ ├── toggleEditMode.ts │ │ ├── toggleMenuBar.ts │ │ ├── trayMenu │ │ ├── clickTrayMenuItem.ts │ │ └── initTrayMenu.ts │ │ ├── widget │ │ ├── copyWidget.ts │ │ ├── deleteWidget.ts │ │ ├── getWidgetApi.ts │ │ ├── showWidgetContextMenu.ts │ │ └── subs │ │ │ ├── cloneWidget.ts │ │ │ └── createWidget.ts │ │ ├── widgetSettings │ │ ├── closeWidgetSettings.ts │ │ ├── getWidgetSettingsApi.ts │ │ ├── openWidgetSettings.ts │ │ ├── saveWidgetSettings.ts │ │ └── updateWidgetCoreSettings.ts │ │ ├── workflow │ │ ├── addWidgetToWorkflow.ts │ │ ├── copyWorkflow.ts │ │ ├── pasteWidgetToWorkflow.ts │ │ └── subs │ │ │ ├── addItemToWidgetLayout.ts │ │ │ ├── cloneWidgetLayoutItem.ts │ │ │ ├── cloneWidgetToWidgetLayout.ts │ │ │ ├── cloneWorkflow.ts │ │ │ ├── createWorkflow.ts │ │ │ ├── deleteWidgetsFromWidgetLayout.ts │ │ │ └── deleteWorkflows.ts │ │ ├── workflowSettings │ │ ├── closeWorkflowSettings.ts │ │ ├── openWorkflowSettings.ts │ │ ├── saveWorkflowSettings.ts │ │ └── updateWorkflowSettings.ts │ │ ├── workflowSwitcher │ │ ├── addWorkflow.ts │ │ ├── deleteWorkflow.ts │ │ ├── pasteWorkflow.ts │ │ ├── renameWorkflow.ts │ │ └── switchWorkflow.ts │ │ └── worktable │ │ └── resizeLayoutItem │ │ ├── calc.ts │ │ ├── index.ts │ │ ├── resizeLayoutItem.ts │ │ ├── resizeLayoutItemEnd.ts │ │ └── resizeLayoutItemStart.ts │ ├── assets.d.ts │ ├── base │ ├── actionBar.ts │ ├── app.ts │ ├── appConfig.ts │ ├── contextMenu.ts │ ├── convTypes.ts │ ├── entity.ts │ ├── entityCollection.ts │ ├── entityList.ts │ ├── list.ts │ ├── memSaver.ts │ ├── productInfo.ts │ ├── project.ts │ ├── state │ │ ├── actions │ │ │ ├── dragDrop.ts │ │ │ ├── entity.ts │ │ │ ├── index.ts │ │ │ ├── modalScreens.ts │ │ │ └── usedNames.ts │ │ ├── app.ts │ │ ├── entities.ts │ │ ├── shared.ts │ │ └── ui.ts │ ├── uiTheme.ts │ ├── utils.ts │ ├── widget.ts │ ├── widgetApi.ts │ ├── widgetLayout.ts │ ├── widgetList.ts │ ├── widgetType.ts │ └── workflow.ts │ ├── data │ ├── appStateStorage.ts │ └── appStore.ts │ ├── eslint.config.mjs │ ├── helpers │ ├── event.ts │ └── index.ts │ ├── index.ejs │ ├── index.tsx │ ├── infra │ ├── appMenuProvider │ │ └── appMenuProvider.ts │ ├── browserWindowProvider │ │ └── browserWindowProvider.ts │ ├── clipboardProvider │ │ └── clipboardProvider.ts │ ├── contextMenuProvider │ │ └── osContextMenuProvider.ts │ ├── dataStorage │ │ ├── appDataStorage.ts │ │ └── widgetDataStorage.ts │ ├── dialogProvider │ │ └── osDialogProvider.ts │ ├── globalShortcut │ │ └── globalShortcutProvider.ts │ ├── globals.ts │ ├── idGenerator │ │ └── uuidv4IdGenerator.ts │ ├── interfaces │ │ ├── globals.ts │ │ └── mainApi.ts │ ├── ipc │ │ └── prepareMenuItemsForIpc.ts │ ├── mainApi │ │ ├── __mocks__ │ │ │ └── mainApi.ts │ │ └── mainApi.ts │ ├── processProvider │ │ └── processProvider.ts │ ├── productInfoProvider │ │ └── productInfoProvider.ts │ ├── shellProvider │ │ └── shellProvider.ts │ ├── terminalProvider │ │ └── terminalProvider.ts │ └── trayMenuProvider │ │ └── trayMenuProvider.ts │ ├── init.ts │ ├── preload │ ├── index.ts │ └── tsconfig.json │ ├── registry │ └── registry.ts │ ├── styles.d.ts │ ├── tsconfig.json │ ├── ui │ ├── assets │ │ ├── fonts │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2 │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2 │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2 │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2 │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2 │ │ │ ├── roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100italic.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500italic.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900italic.woff2 │ │ │ ├── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2 │ │ │ └── roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2 │ │ └── images │ │ │ └── appIcons │ │ │ ├── add-14.svg │ │ │ ├── arr-down-14.svg │ │ │ ├── browse-14.svg │ │ │ ├── circle-question-16.svg │ │ │ ├── delete-14.svg │ │ │ ├── duplicate-14.svg │ │ │ ├── edit-mode-24.svg │ │ │ ├── index.ts │ │ │ ├── logo-150.svg │ │ │ ├── manage-14.svg │ │ │ ├── manage-24.svg │ │ │ ├── maximize-14.svg │ │ │ ├── more-14.svg │ │ │ ├── settings-14.svg │ │ │ └── unmaximize-14.svg │ ├── components │ │ ├── about │ │ │ ├── about.module.scss │ │ │ ├── about.tsx │ │ │ ├── aboutViewModel.ts │ │ │ └── index.ts │ │ ├── app │ │ │ ├── _fonts.scss │ │ │ ├── app.module.scss │ │ │ ├── app.tsx │ │ │ ├── appViewModel.ts │ │ │ ├── globals.scss │ │ │ ├── index.ts │ │ │ └── uiTheme │ │ │ │ ├── themes │ │ │ │ ├── dark.ts │ │ │ │ ├── index.ts │ │ │ │ └── light.ts │ │ │ │ └── uiTheme.tsx │ │ ├── appManager │ │ │ ├── appManager.module.scss │ │ │ ├── appManager.tsx │ │ │ ├── appManagerList │ │ │ │ ├── appManagerList.module.scss │ │ │ │ ├── appManagerList.tsx │ │ │ │ ├── appManagerListItem.module.scss │ │ │ │ ├── appManagerListItem.tsx │ │ │ │ ├── appManagerListItemViewModel.ts │ │ │ │ ├── appManagerListViewModel.ts │ │ │ │ └── index.ts │ │ │ ├── appManagerSettings │ │ │ │ ├── appManagerSettings.tsx │ │ │ │ ├── appManagerSettingsViewModel.ts │ │ │ │ └── index.ts │ │ │ ├── appManagerViewModel.ts │ │ │ └── index.ts │ │ ├── applicationSettings │ │ │ ├── applicationSettings.module.scss │ │ │ ├── applicationSettings.tsx │ │ │ ├── applicationSettingsViewModel.ts │ │ │ └── index.ts │ │ ├── basic │ │ │ ├── actionBar │ │ │ │ ├── actionBar.module.scss │ │ │ │ ├── actionBar.tsx │ │ │ │ ├── actionBarViewModel.ts │ │ │ │ └── index.ts │ │ │ ├── button │ │ │ │ ├── button.module.scss │ │ │ │ ├── button.tsx │ │ │ │ └── index.ts │ │ │ ├── inAppNote │ │ │ │ ├── inAppNote.module.scss │ │ │ │ ├── inAppNote.tsx │ │ │ │ └── index.ts │ │ │ ├── modalScreen │ │ │ │ ├── index.ts │ │ │ │ ├── modalScreen.module.scss │ │ │ │ └── modalScreen.tsx │ │ │ ├── moreInfo │ │ │ │ ├── index.ts │ │ │ │ ├── moreInfo.module.scss │ │ │ │ └── moreInfo.tsx │ │ │ ├── settingsScreen │ │ │ │ ├── index.ts │ │ │ │ ├── setting │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── settingActions.tsx │ │ │ │ │ ├── settingBlock.tsx │ │ │ │ │ └── settingRow.tsx │ │ │ │ ├── settingsScreen.module.scss │ │ │ │ └── settingsScreen.tsx │ │ │ └── svgIcon │ │ │ │ ├── index.ts │ │ │ │ └── svgIcon.tsx │ │ ├── projectManager │ │ │ ├── index.ts │ │ │ ├── projectManager.module.scss │ │ │ ├── projectManager.tsx │ │ │ ├── projectManagerList │ │ │ │ ├── index.ts │ │ │ │ ├── projectManagerList.module.scss │ │ │ │ ├── projectManagerList.tsx │ │ │ │ ├── projectManagerListItem.module.scss │ │ │ │ ├── projectManagerListItem.tsx │ │ │ │ ├── projectManagerListItemViewModel.ts │ │ │ │ └── projectManagerListViewModel.ts │ │ │ ├── projectManagerSettings │ │ │ │ ├── index.ts │ │ │ │ ├── projectManagerSettings.tsx │ │ │ │ └── projectManagerSettingsViewModel.ts │ │ │ └── projectManagerViewModel.ts │ │ ├── topBar │ │ │ ├── editModeToggle │ │ │ │ ├── editModeToggle.tsx │ │ │ │ ├── editModeToggleViewModel.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── manageProjectsButton │ │ │ │ ├── index.ts │ │ │ │ ├── manageProjectsButton.tsx │ │ │ │ └── manageProjectsButtonViewModel.ts │ │ │ ├── palette │ │ │ │ ├── index.ts │ │ │ │ ├── palette.module.scss │ │ │ │ ├── palette.tsx │ │ │ │ ├── paletteItem.tsx │ │ │ │ └── paletteViewModel.ts │ │ │ ├── projectSwitcher │ │ │ │ ├── index.ts │ │ │ │ ├── projectSwitcher.module.scss │ │ │ │ ├── projectSwitcher.tsx │ │ │ │ └── projectSwitcherViewModel.ts │ │ │ ├── shelf │ │ │ │ ├── index.ts │ │ │ │ ├── shelf.module.scss │ │ │ │ ├── shelf.tsx │ │ │ │ ├── shelfItem.tsx │ │ │ │ ├── shelfItemViewModel.ts │ │ │ │ └── shelfViewModel.ts │ │ │ ├── topBar.module.scss │ │ │ ├── topBar.tsx │ │ │ └── topBarViewModel.ts │ │ ├── widget │ │ │ ├── index.ts │ │ │ ├── widget.module.scss │ │ │ ├── widget.tsx │ │ │ ├── widgetById.tsx │ │ │ ├── widgetByIdViewModel.ts │ │ │ └── widgetViewModel.ts │ │ ├── widgetSettings │ │ │ ├── coreSettings │ │ │ │ ├── coreSettings.tsx │ │ │ │ ├── coreSettingsViewModel.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── widgetSettings.module.scss │ │ │ ├── widgetSettings.tsx │ │ │ └── widgetSettingsViewModel.ts │ │ ├── workflowSettings │ │ │ ├── index.ts │ │ │ ├── workflowSettings.module.scss │ │ │ ├── workflowSettings.tsx │ │ │ └── workflowSettingsViewModel.ts │ │ ├── workflowSwitcher │ │ │ ├── index.ts │ │ │ ├── workflowSwitcher.module.scss │ │ │ ├── workflowSwitcher.tsx │ │ │ ├── workflowSwitcherItem.tsx │ │ │ ├── workflowSwitcherItemViewModel.ts │ │ │ └── workflowSwitcherViewModel.ts │ │ └── worktable │ │ │ ├── index.ts │ │ │ ├── widgetLayout │ │ │ ├── calcs.ts │ │ │ ├── index.ts │ │ │ ├── resizeHandles.ts │ │ │ ├── widgetLayout.module.scss │ │ │ ├── widgetLayout.tsx │ │ │ ├── widgetLayoutItem.tsx │ │ │ ├── widgetLayoutItemGhost.module.scss │ │ │ ├── widgetLayoutItemGhost.tsx │ │ │ ├── widgetLayoutItemViewModel.ts │ │ │ └── widgetLayoutViewModel.ts │ │ │ ├── worktable.module.scss │ │ │ ├── worktable.tsx │ │ │ └── worktableViewModel.ts │ ├── hooks │ │ ├── appState.ts │ │ ├── index.ts │ │ ├── useComponentMounted.ts │ │ ├── useElementRect.ts │ │ ├── useWidgetTypeComp.tsx │ │ └── useWindowSize.ts │ └── types │ │ ├── dimensions.ts │ │ ├── events.ts │ │ └── widgetType.ts │ └── widgets │ ├── _template │ ├── icons │ │ ├── index.ts │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ └── widget.tsx │ ├── appModules.ts │ ├── commander │ ├── icons │ │ ├── exec-command.svg │ │ ├── index.ts │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── widget.module.scss │ └── widget.tsx │ ├── file-opener │ ├── icons │ │ ├── index.ts │ │ ├── open-file.svg │ │ ├── open-folder.svg │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── settingsType.ts │ ├── widget.module.scss │ └── widget.tsx │ ├── helpers.ts │ ├── index.ts │ ├── link-opener │ ├── icons │ │ ├── index.ts │ │ ├── open-link.svg │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── widget.module.scss │ └── widget.tsx │ ├── note │ ├── actionBar.ts │ ├── actions.ts │ ├── contextMenu.ts │ ├── icons │ │ ├── copy-full-text.svg │ │ ├── index.ts │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── widget.module.scss │ └── widget.tsx │ ├── timer │ ├── audio │ │ └── timer-end │ │ │ ├── 8-bit-arpeggio.mp3 │ │ │ ├── air-horn.mp3 │ │ │ ├── angry-boat.mp3 │ │ │ ├── bike-s-bell-ring.mp3 │ │ │ ├── bouncing-down.mp3 │ │ │ ├── cuckoo-clock.mp3 │ │ │ ├── drum-and-bass-hardcore.mp3 │ │ │ ├── drum-and-bass.mp3 │ │ │ ├── dubstep-wobbles.mp3 │ │ │ ├── glass-ding.mp3 │ │ │ ├── glockenspiel-arpeggio.mp3 │ │ │ ├── guitar-arpeggio.mp3 │ │ │ ├── guitar-chimes.mp3 │ │ │ ├── guitar-chord.mp3 │ │ │ ├── guitar-dub.mp3 │ │ │ ├── guitar-groove.mp3 │ │ │ ├── guitar-harmonics.mp3 │ │ │ ├── guitar-slide.mp3 │ │ │ ├── hardstyle-kick.mp3 │ │ │ ├── hover-scooter.mp3 │ │ │ ├── index.ts │ │ │ ├── metal-ding.mp3 │ │ │ ├── movie-swell.mp3 │ │ │ ├── piano-attack.mp3 │ │ │ ├── piano-plinks.mp3 │ │ │ ├── piano-reel.mp3 │ │ │ ├── plucked-synth.mp3 │ │ │ ├── reversed-door-bell.mp3 │ │ │ ├── reversed-transform.mp3 │ │ │ ├── satellite-flyby.mp3 │ │ │ ├── science-bells.mp3 │ │ │ ├── synth-bell.mp3 │ │ │ ├── synth-tune.mp3 │ │ │ ├── time-travel.mp3 │ │ │ ├── transformer.mp3 │ │ │ ├── uplifting-synth.mp3 │ │ │ └── xylophone-tones.mp3 │ ├── icons │ │ ├── index.ts │ │ ├── play.svg │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── useAudioFile.ts │ ├── widget.module.scss │ └── widget.tsx │ ├── to-do-list │ ├── actionBar.ts │ ├── actions.ts │ ├── contextMenu.ts │ ├── dom.ts │ ├── icons │ │ ├── add-task.svg │ │ ├── index.ts │ │ ├── uncheck-all.svg │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── state.ts │ ├── widget.module.scss │ └── widget.tsx │ ├── web-query │ ├── icons │ │ ├── index.ts │ │ ├── query.svg │ │ └── widget.svg │ ├── index.ts │ ├── settings.tsx │ ├── widget.module.scss │ └── widget.tsx │ └── webpage │ ├── actionBar.ts │ ├── actions.ts │ ├── contextMenu.ts │ ├── icons │ ├── back.svg │ ├── forward.svg │ ├── home.svg │ ├── index.ts │ ├── open-in-browser.svg │ ├── reload-start.svg │ ├── reload-stop.svg │ ├── reload.svg │ └── widget.svg │ ├── index.ts │ ├── partition.ts │ ├── settings.tsx │ ├── widget.module.scss │ └── widget.tsx ├── tests ├── __mocks__ │ ├── fileMock.js │ └── identity-obj-proxy.js ├── common │ ├── base │ │ ├── fixtures │ │ │ ├── menu.ts │ │ │ └── process.ts │ │ ├── objectManager.spec.ts │ │ ├── userAgent.spec.ts │ │ └── versionedObject.spec.ts │ ├── data │ │ ├── fixtures │ │ │ ├── stateStorage.ts │ │ │ └── store.ts │ │ ├── stateStorage.spec.ts │ │ └── store.spec.ts │ ├── eslint.config.mjs │ ├── helpers │ │ ├── debounce.spec.ts │ │ ├── deepFreeze.spec.ts │ │ └── sanitizeUrl.spec.ts │ ├── infra │ │ └── dataStorage │ │ │ ├── inMemoryDataStorage.spec.ts │ │ │ ├── setTextOnlyIfChanged.spec.ts │ │ │ └── withJson.spec.ts │ ├── ipc │ │ └── ipc.spec.ts │ └── tsconfig.json ├── main │ ├── application │ │ └── useCases │ │ │ ├── appDataStorage │ │ │ ├── deleteInAppDataStorage.spec.ts │ │ │ ├── getTextFromAppDataStorage.spec.ts │ │ │ └── setTextInAppDataStorage.spec.ts │ │ │ ├── appMenu │ │ │ ├── setAppMenu.spec.ts │ │ │ └── setAppMenuAutoHide.spec.ts │ │ │ ├── browserWindow │ │ │ ├── getWindowState.spec.ts │ │ │ └── setWindowState.spec.ts │ │ │ ├── clipboard │ │ │ ├── writeBookmarkIntoClipboard.spec.ts │ │ │ └── writeTextIntoClipboard.spec.ts │ │ │ ├── contextMenu │ │ │ └── popupContextMenu.spec.ts │ │ │ ├── dialog │ │ │ ├── showMessageBox.spec.ts │ │ │ ├── showOpenDirDialog.spec.ts │ │ │ ├── showOpenFileDialog.spec.ts │ │ │ └── showSaveFileDialog.spec.ts │ │ │ ├── globalShortcut │ │ │ └── setMainShortcut.spec.ts │ │ │ ├── process │ │ │ └── getProcessInfo.spec.ts │ │ │ ├── shell │ │ │ ├── openApp.spec.ts │ │ │ ├── openExternalUrl.spec.ts │ │ │ └── openPath.spec.ts │ │ │ ├── terminal │ │ │ └── execCmdLinesInTerminal.spec.ts │ │ │ ├── tray │ │ │ └── setTrayMenu.spec.ts │ │ │ └── widgetDataStorage │ │ │ ├── clearWidgetDataStorage.spec.ts │ │ │ ├── deleteInWidgetDataStorage.spec.ts │ │ │ ├── getKeysFromWidgetDataStorage.spec.ts │ │ │ ├── getTextFromWidgetDataStorage.spec.ts │ │ │ └── setTextInWidgetDataStorage.spec.ts │ ├── base │ │ ├── apps │ │ │ └── terminal.spec.ts │ │ └── state │ │ │ ├── fixtures │ │ │ └── windowState.ts │ │ │ └── window.spec.ts │ ├── controllers │ │ ├── appDataStorage.spec.ts │ │ ├── appMenu.spec.ts │ │ ├── browserWindow.spec.ts │ │ ├── clipboard.spec.ts │ │ ├── contextMenu.spec.ts │ │ ├── controller.spec.ts │ │ ├── dialog.spec.ts │ │ ├── globalShortcut.spec.ts │ │ ├── process.spec.ts │ │ ├── shell.spec.ts │ │ ├── terminal.spec.ts │ │ ├── trayMenu.spec.ts │ │ └── widgetDataStorage.spec.ts │ ├── data │ │ ├── fixtures │ │ │ └── windowStore.ts │ │ ├── windowStateStorage.spec.ts │ │ └── windowStore.spec.ts │ ├── eslint.config.mjs │ ├── infra │ │ ├── ipcMain │ │ │ ├── ipcMain.spec.ts │ │ │ └── ipcMainEventValidator.spec.ts │ │ └── mocks │ │ │ ├── childProcessProvider.ts │ │ │ ├── ipcMain.ts │ │ │ ├── processProvider.ts │ │ │ └── shellProvider.ts │ └── tsconfig.json ├── renderer │ ├── application │ │ └── useCases │ │ │ ├── about │ │ │ ├── closeAbout.spec.ts │ │ │ ├── getAboutInfo.spec.ts │ │ │ └── openAbout.spec.ts │ │ │ ├── actionBar │ │ │ └── clickActionBarItem.spec.ts │ │ │ ├── appManager │ │ │ ├── addAppInAppManager.spec.ts │ │ │ ├── closeAppManager.spec.ts │ │ │ ├── duplicateAppInAppManager.spec.ts │ │ │ ├── openAppManager.spec.ts │ │ │ ├── saveChangesInAppManager.spec.ts │ │ │ ├── switchAppInAppManager.spec.ts │ │ │ ├── toggleDeletionInAppManager.spec.ts │ │ │ ├── updateAppSettingsInAppManager.spec.ts │ │ │ └── updateAppsOrderInAppManager.spec.ts │ │ │ ├── appMenu │ │ │ ├── clickAppMenuItem.spec.ts │ │ │ └── initAppMenu.spec.ts │ │ │ ├── applicationSettings │ │ │ ├── closeApplicationSettings.spec.ts │ │ │ ├── openApplicationSettings.spec.ts │ │ │ ├── saveApplicationSettings.spec.ts │ │ │ └── updateApplicationSettings.spec.ts │ │ │ ├── browserWindow │ │ │ └── showBrowserWindow.spec.ts │ │ │ ├── contextMenu │ │ │ ├── clickContextMenuItem.spec.ts │ │ │ └── showContextMenu.spec.ts │ │ │ ├── dragDrop │ │ │ ├── dragEnd.spec.ts │ │ │ ├── dragLeaveTarget.spec.ts │ │ │ ├── dragOverTopBarList.spec.ts │ │ │ ├── dragOverWorkflowSwitcher.spec.ts │ │ │ ├── dragOverWorktableLayout.spec.ts │ │ │ ├── dragWidgetFromPalette.spec.ts │ │ │ ├── dragWidgetFromTopBarList.spec.ts │ │ │ ├── dragWidgetFromWorktableLayout.spec.ts │ │ │ ├── dragWorkflowFromWorkflowSwitcher.spec.ts │ │ │ ├── dropOnTopBarList.spec.ts │ │ │ ├── dropOnWorkflowSwitcher.spec.ts │ │ │ └── dropOnWorktableLayout.spec.ts │ │ │ ├── globalShortcut │ │ │ └── initMainShortcut.spec.ts │ │ │ ├── memSaver │ │ │ ├── deactivateWorkflow.spec.ts │ │ │ ├── initMemSaver.spec.ts │ │ │ └── subs │ │ │ │ ├── activateProjectWorkflows.spec.ts │ │ │ │ ├── activateWorkflow.spec.ts │ │ │ │ ├── deactivateWorkflow.spec.ts │ │ │ │ ├── resetDelayedWorkflowDeactivation.spec.ts │ │ │ │ ├── scheduleProjectWorkflowsDeactivation.spec.ts │ │ │ │ ├── scheduleWorkflowDeactivation.spec.ts │ │ │ │ └── startDelayedWorkflowDeactivation.spec.ts │ │ │ ├── project │ │ │ └── subs │ │ │ │ └── deleteProjects.spec.ts │ │ │ ├── projectManager │ │ │ ├── addProjectInProjectManager.spec.ts │ │ │ ├── closeProjectManager.spec.ts │ │ │ ├── duplicateProjectInProjectManager.spec.ts │ │ │ ├── openProjectManager.spec.ts │ │ │ ├── saveChangesInProjectManager.spec.ts │ │ │ ├── switchProjectInProjectManager.spec.ts │ │ │ ├── toggleDeletionInProjectManager.spec.ts │ │ │ ├── updateProjectSettingsInProjectManager.spec.ts │ │ │ └── updateProjectsOrderInProjectManager.spec.ts │ │ │ ├── projectSwitcher │ │ │ └── switchProject.spec.ts │ │ │ ├── shelf │ │ │ ├── addWidgetToShelf.spec.ts │ │ │ ├── pasteWidgetToShelf.spec.ts │ │ │ └── subs │ │ │ │ ├── addItemToWidgetList.spec.ts │ │ │ │ ├── cloneWidgetToWidgetList.spec.ts │ │ │ │ └── deleteWidgetsFromWidgetList.spec.ts │ │ │ ├── toggleEditMode.spec.ts │ │ │ ├── toggleMenuBar.spec.ts │ │ │ ├── trayMenu │ │ │ ├── clickTrayMenuItem.spec.ts │ │ │ └── initTrayMenu.spec.ts │ │ │ ├── widget │ │ │ ├── copyWidget.spec.ts │ │ │ ├── deleteWidget.spec.ts │ │ │ ├── getWidgetApi.spec.ts │ │ │ ├── showWidgetContextMenu.spec.ts │ │ │ └── subs │ │ │ │ └── cloneWidget.spec.ts │ │ │ ├── widgetSettings │ │ │ ├── closeWidgetSettings.spec.ts │ │ │ ├── getWidgetSettingsApi.spec.ts │ │ │ ├── openWidgetSettings.spec.ts │ │ │ ├── saveWidgetSettings.spec.ts │ │ │ └── updateWidgetCoreSettings.spec.ts │ │ │ ├── workflow │ │ │ ├── addWidgetToWorkflow.spec.ts │ │ │ ├── copyWorkflow.spec.ts │ │ │ ├── pasteWidgetToWorkflow.spec.ts │ │ │ └── subs │ │ │ │ ├── addItemToWidgetLayout.spec.ts │ │ │ │ ├── cloneWidgetLayoutItem.spec.ts │ │ │ │ ├── cloneWidgetToWidgetLayout.spec.ts │ │ │ │ ├── cloneWorkflow.spec.ts │ │ │ │ ├── deleteWidgetsFromWidgetList.spec.ts │ │ │ │ └── deleteWorkflows.spec.ts │ │ │ ├── workflowSettings │ │ │ ├── closeWorkflowSettings.spec.ts │ │ │ ├── openWorkflowSettings.spec.ts │ │ │ ├── saveWorkflowSettings.spec.ts │ │ │ └── updateWorkflowSettings.spec.ts │ │ │ ├── workflowSwitcher │ │ │ ├── addWorkflow.spec.ts │ │ │ ├── deleteWorkflow.spec.ts │ │ │ ├── pasteWorkflow.spec.ts │ │ │ ├── renameWorkflow.spec.ts │ │ │ └── switchWorkflow.spec.ts │ │ │ └── worktable │ │ │ └── resizeLayoutItem │ │ │ ├── calc.spec.ts │ │ │ ├── resizeLayoutItem.spec.ts │ │ │ ├── resizeLayoutItemEnd.spec.ts │ │ │ └── resizeLayoutItemStart.spec.ts │ ├── base │ │ ├── app.spec.ts │ │ ├── convTypes.spec.ts │ │ ├── entityCollection.spec.ts │ │ ├── entityList.spec.ts │ │ ├── fixtures │ │ │ ├── actionBar.ts │ │ │ ├── app.ts │ │ │ ├── appConfig.ts │ │ │ ├── entity.ts │ │ │ ├── memSaver.ts │ │ │ ├── menu.ts │ │ │ ├── productInfo.ts │ │ │ ├── project.ts │ │ │ ├── widget.ts │ │ │ ├── widgetLayout.ts │ │ │ ├── widgetList.ts │ │ │ ├── widgetType.tsx │ │ │ └── workflow.ts │ │ ├── list.spec.ts │ │ ├── project.spec.ts │ │ ├── state │ │ │ ├── actions │ │ │ │ ├── dragDrop.spec.ts │ │ │ │ ├── entity.spec.ts │ │ │ │ └── modalScreens.spec.ts │ │ │ ├── app.spec.ts │ │ │ ├── fixtures │ │ │ │ ├── appManager.ts │ │ │ │ ├── appState.ts │ │ │ │ ├── applicationSettings.ts │ │ │ │ ├── apps.ts │ │ │ │ ├── copy.ts │ │ │ │ ├── dragDropState.ts │ │ │ │ ├── entitiesState.ts │ │ │ │ ├── memSaver.ts │ │ │ │ ├── modalScreens.ts │ │ │ │ ├── palette.ts │ │ │ │ ├── projectManager.ts │ │ │ │ ├── projectSwitcher.ts │ │ │ │ ├── shelf.ts │ │ │ │ ├── widgetSettings.ts │ │ │ │ ├── workflowSettings.ts │ │ │ │ └── worktable.ts │ │ │ └── shared.spec.ts │ │ ├── utils.spec.ts │ │ ├── widget.spec.ts │ │ ├── widgetApi.spec.ts │ │ ├── widgetLayout.spec.ts │ │ ├── widgetList.spec.ts │ │ └── workflow.spec.ts │ ├── data │ │ ├── appStateStorage.spec.ts │ │ ├── appStore.spec.ts │ │ └── fixtures │ │ │ └── appStore.ts │ ├── eslint.config.mjs │ ├── global.d.ts │ ├── helpers │ │ └── event.spec.ts │ ├── infra │ │ ├── appMenuProvider │ │ │ └── appMenuProvider.spec.ts │ │ ├── browserWindowProvider │ │ │ └── appMenuProvider.spec.ts │ │ ├── clipboardProvider │ │ │ └── clipboardProvider.spec.ts │ │ ├── contextMenuProvider │ │ │ └── osContextMenuProvider.spec.ts │ │ ├── dataStorage │ │ │ ├── appDataStorage.spec.ts │ │ │ └── widgetDataStorage.spec.ts │ │ ├── dialogProvider │ │ │ └── osDialogProvider.spec.ts │ │ ├── globalShortcut │ │ │ └── globalShortcutProvider.spec.ts │ │ ├── idGenerator │ │ │ └── uuidv4IdGenerator.spec.ts │ │ ├── ipc │ │ │ └── prepareMenuItemsForIpc.spec.ts │ │ ├── mocks │ │ │ ├── dialogProvider.ts │ │ │ └── shellProvider.ts │ │ ├── processProvider │ │ │ └── processProvider.spec.ts │ │ ├── shellProvider │ │ │ └── shellProvider.spec.ts │ │ ├── terminalProvider │ │ │ └── terminalProvider.spec.ts │ │ └── trayMenuProvider │ │ │ └── trayMenuProvider.spec.ts │ ├── registry │ │ └── registry.spec.ts │ ├── setupTests.ts │ ├── tsconfig.json │ ├── ui │ │ └── components │ │ │ ├── about.spec.tsx │ │ │ ├── app.spec.tsx │ │ │ ├── appManager.spec.tsx │ │ │ ├── applicationSettings.spec.tsx │ │ │ ├── basic │ │ │ └── actionBar.spec.tsx │ │ │ ├── projectManager.spec.tsx │ │ │ ├── topBar │ │ │ ├── editModeToggle.spec.tsx │ │ │ ├── manageProjects.spec.tsx │ │ │ ├── palette.spec.tsx │ │ │ ├── projectSwitcher.spec.tsx │ │ │ ├── shelf.spec.tsx │ │ │ └── topBar.spec.tsx │ │ │ ├── widget │ │ │ ├── widget.spec.tsx │ │ │ └── widgetById.spec.tsx │ │ │ ├── widgetSettings.spec.tsx │ │ │ ├── workflowSettings.spec.tsx │ │ │ ├── workflowSwitcher.spec.tsx │ │ │ └── worktable │ │ │ ├── widgetLayout.spec.tsx │ │ │ └── worktable.spec.tsx │ └── widgets │ │ ├── _template │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── commander │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── file-opener │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── link-opener │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── note │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── setupSut.tsx │ │ ├── timer │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── to-do-list │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ ├── web-query │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts │ │ └── webpage │ │ ├── fixtures.ts │ │ ├── settings.spec.ts │ │ └── widget.spec.ts └── utils │ ├── makeFixture │ ├── index.ts │ ├── makeFixture.spec.ts │ └── makeFixture.ts │ └── tsconfig.json ├── tsconfig.json ├── webpack.main.config.js ├── webpack.preload.config.js ├── webpack.renderer.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Using Freeter 4 | url: https://community.freeter.io/category/8/using-freeter 5 | about: Looking for help with Freeter? Please ask and answer questions here. 6 | - name: Bug reports 7 | url: https://community.freeter.io/category/7/bug-reports 8 | about: Found a bug? Report it here. 9 | - name: Feature requests 10 | url: https://community.freeter.io/category/6/feature-requests 11 | about: Is there some feature you'd love to see added to Freeter? Post it here. 12 | -------------------------------------------------------------------------------- /.github/funding.yml: -------------------------------------------------------------------------------- 1 | patreon: alexkaul 2 | custom: https://freeter.io/sponsor/ 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | workflow_dispatch: 11 | 12 | jobs: 13 | main: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | 22 | - name: Install Deps 23 | run: yarn install 24 | 25 | - name: Run Tests 26 | run: yarn run test 27 | 28 | - name: Compile 29 | run: yarn run prod 30 | 31 | - name: Run Linter 32 | run: yarn run lint 33 | 34 | - name: Run Type-checking for Tests 35 | run: yarn run test:typecheck 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | Thumbs.db 4 | yarn-error.log 5 | build/ 6 | coverage/ 7 | dist/ 8 | node_modules/ 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "EditorConfig.EditorConfig" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.trimTrailingWhitespace": true, 3 | "search.exclude": { 4 | "node_modules/**": true, 5 | "build/**": true 6 | }, 7 | "npm.packageManager": "yarn", 8 | "emmet.excludeLanguages": [], 9 | "typescript.preferences.importModuleSpecifier": "non-relative", 10 | "typescript.preferences.quoteStyle": "single", 11 | "files.insertFinalNewline": true, 12 | "[plaintext]": { 13 | "files.insertFinalNewline": false 14 | }, 15 | "[typescript]": { 16 | "editor.defaultFormatter": "vscode.typescript-language-features", 17 | "editor.formatOnSave": true 18 | }, 19 | "[javascript]": { 20 | "editor.defaultFormatter": "vscode.typescript-language-features", 21 | "editor.formatOnSave": true 22 | }, 23 | "typescript.tsc.autoDetect": "off", 24 | "typescript.tsdk": "node_modules/typescript/lib", 25 | "eslint.useFlatConfig": true 26 | } 27 | -------------------------------------------------------------------------------- /backers.json: -------------------------------------------------------------------------------- 1 | { 2 | "bronzeSponsors": [ 3 | ["Nick Hitch"] 4 | ], 5 | "backersPlus": [ 6 | ["Nick Hitch"], 7 | ["Ryann Hoffman"], 8 | ["Ernesto"] 9 | ], 10 | "backers": [ 11 | ["Greg Lehmkuhl"], 12 | ["Rv3nDr3mr"], 13 | ["Mark Creamer"], 14 | ["Valor"] 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /resources/darwin/dmgBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/darwin/dmgBg.png -------------------------------------------------------------------------------- /resources/darwin/dmgBg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/darwin/dmgBg@2x.png -------------------------------------------------------------------------------- /resources/darwin/freeter.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/darwin/freeter.icns -------------------------------------------------------------------------------- /resources/linux/freeter-icons/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/1024x1024.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/128x128.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/16x16.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/256x256.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/32x32.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/48x48.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/512x512.png -------------------------------------------------------------------------------- /resources/linux/freeter-icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/linux/freeter-icons/64x64.png -------------------------------------------------------------------------------- /resources/win32/freeter.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/resources/win32/freeter.ico -------------------------------------------------------------------------------- /src/assets/app-icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/assets/app-icons/16.png -------------------------------------------------------------------------------- /src/assets/app-icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/assets/app-icons/256.png -------------------------------------------------------------------------------- /src/common/application/interfaces/dataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ObjectManager } from '@common/base/objectManager'; 7 | 8 | export interface DataStorage { 9 | getText(key: string): Promise; 10 | setText(key: string, text: string): Promise; 11 | deleteItem(key: string): Promise; 12 | clear(): Promise; 13 | getKeys(): Promise; 14 | } 15 | 16 | export type DataStorageManager = ObjectManager; 17 | 18 | export interface DataStorageJson { 19 | getJson(key: string): Promise; 20 | setJson(key: string, json: unknown): Promise; 21 | } 22 | -------------------------------------------------------------------------------- /src/common/base/objectManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ObjectManager { 7 | getObject(id: string): Promise; 8 | copyObjectData(fromId: string, toId: string): Promise; 9 | } 10 | 11 | export function createObjectManager( 12 | objectFactory: (id: string) => Promise, 13 | objectDataCopier: (fromId: string, toId: string) => Promise 14 | ): ObjectManager { 15 | const items: Record> = {}; 16 | 17 | return { 18 | getObject: async (id) => { 19 | if (!items[id]) { 20 | items[id] = objectFactory(id); 21 | } 22 | return items[id]; 23 | }, 24 | copyObjectData: objectDataCopier 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/common/base/process.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ProcessInfoBrowser { 7 | name: 'Chrome'; 8 | ver: string; 9 | } 10 | 11 | export type ProcessInfoOsName = 'darwin' | 'linux' | 'win32'; 12 | 13 | export interface ProcessInfoOs { 14 | name: ProcessInfoOsName; 15 | ver: string; 16 | } 17 | 18 | export interface ProcessInfo { 19 | browser: ProcessInfoBrowser; 20 | os: ProcessInfoOs; 21 | isWin: boolean; 22 | isMac: boolean; 23 | isLinux: boolean; 24 | isDevMode: boolean; 25 | } 26 | -------------------------------------------------------------------------------- /src/common/helpers/debounce.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export type DebouncedFunc = ( 7 | (...args: TArgs) => void 8 | ) & { 9 | cancel: () => void; 10 | } 11 | 12 | export function debounce( 13 | func: (...args: TArgs) => void, 14 | msec: number 15 | ) { 16 | let timer: ReturnType; 17 | const debouncedFunc: DebouncedFunc = (...args) => { 18 | clearTimeout(timer); 19 | timer = setTimeout(() => { 20 | func(...args); 21 | }, msec); 22 | }; 23 | 24 | debouncedFunc.cancel = () => clearTimeout(timer); 25 | 26 | return debouncedFunc; 27 | } 28 | -------------------------------------------------------------------------------- /src/common/helpers/deepFreeze.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export function deepFreeze | object>(item: T): T { 7 | // Skip if already frozen and primitives for which isFrozen is always true 8 | if (Object.isFrozen(item)) { 9 | return item; 10 | } 11 | 12 | if (!Array.isArray(item) && item.constructor === Object && Object.getPrototypeOf(item) !== Object.prototype) { 13 | throw new Error('Cannot freeze a class-based object'); 14 | } 15 | 16 | Object.freeze(item); 17 | 18 | Object.keys(item).forEach(i => deepFreeze((item as Record)[i] as Record)); 19 | 20 | return item; 21 | } 22 | -------------------------------------------------------------------------------- /src/common/helpers/sanitizeUrl.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export function sanitizeUrl(url: string, defPrefix: string = 'https://'): string { 7 | url = url.trim(); 8 | try { 9 | new URL(url); 10 | return url; 11 | } catch (e) { 12 | try { 13 | const prefixedUrl = defPrefix + url; 14 | new URL(prefixedUrl); 15 | return prefixedUrl; 16 | } catch (e) { 17 | return ''; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/common/infra/dataStorage/inMemoryDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage } from '@common/application/interfaces/dataStorage'; 7 | 8 | export function createInMemoryDataStorage(initData?: Record): DataStorage { 9 | let storage = { ...initData }; 10 | return { 11 | getText: async (key) => storage[key] as string ?? undefined, 12 | setText: async (key, item) => { storage[key] = item }, 13 | deleteItem: async (key) => { delete storage[key] }, 14 | clear: async () => { storage = {} }, 15 | getKeys: async () => Object.keys(storage) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/common/infra/dataStorage/withJson.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage as DataStorageCommon, DataStorageJson } from '@common/application/interfaces/dataStorage'; 7 | 8 | export function withJson(dataStorage: T): T & DataStorageJson { 9 | return { 10 | ...dataStorage, 11 | getJson: async (key) => { 12 | const stringItem = await dataStorage.getText(key); 13 | if (stringItem !== undefined) { 14 | try { 15 | return JSON.parse(stringItem) 16 | } catch { 17 | return undefined; 18 | } 19 | } 20 | return undefined; 21 | }, 22 | setJson: async (key, val) => dataStorage.setText(key, JSON.stringify(val)) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/common/infra/network.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export const schemeFreeterFile = 'freeter-file'; 7 | 8 | export const hostFreeterApp = 'freeter-app'; 9 | -------------------------------------------------------------------------------- /src/common/ipc/ipc.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export const channelPrefix = 'freeter:'; 7 | 8 | export const makeIpcChannelName = (name: string) => channelPrefix + name; 9 | -------------------------------------------------------------------------------- /src/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["es2021"], 5 | "baseUrl": "../", 6 | "paths": { 7 | "@common/*": ["common/*"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/application/interfaces/appMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItemsIpc } from '@common/base/menu'; 7 | import { WebContents } from '@/application/interfaces/webContents'; 8 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 9 | 10 | export interface AppMenuProvider { 11 | setMenu: (items: MenuItemsIpc, actionsTarget: WebContents) => void 12 | setAutoHide: (autoHide: boolean, windowTarget: BrowserWindow) => void 13 | } 14 | -------------------------------------------------------------------------------- /src/main/application/interfaces/appsProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface AppsProvider { 7 | getDefaultTerminal: () => string; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/application/interfaces/browserWindow.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface BrowserWindow { 7 | isMinimized: () => boolean; 8 | restore: () => void; 9 | focus: () => void; 10 | hide: () => void; 11 | show: () => void; 12 | isVisible: () => boolean; 13 | isFocused: () => boolean; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/application/interfaces/childProcessProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ChildProcessProvider { 7 | spawnDetached: (cmd: string, args: string[], opts?: { 8 | cwd?: string; 9 | env?: Record; 10 | shell?: boolean; 11 | }) => void; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/application/interfaces/clipboardProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ClipboardProvider { 7 | writeBookmark: (title: string, url: string) => void; 8 | writeText: (text: string) => void; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/application/interfaces/contextMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItemsIpc } from '@common/base/menu'; 7 | 8 | export interface ContextMenuProvider { 9 | popup: (items: MenuItemsIpc) => Promise; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/application/interfaces/globalShortcutProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 7 | 8 | export interface GlobalShortcutProvider { 9 | setMainShortcut: (accelerator: string, windowTarget: BrowserWindow) => Promise; 10 | destroy: () => void; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/application/interfaces/processProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProcessInfo } from '@common/base/process'; 7 | 8 | export interface ProcessProvider { 9 | getProcessInfo: () => ProcessInfo; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/application/interfaces/shellProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ShellProvider { 7 | openExternal: (url: string) => Promise; 8 | openPath: (path: string) => Promise; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/application/interfaces/store.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Store } from '@common/application/interfaces/store'; 7 | import { WindowState } from '@/base/state/window'; 8 | 9 | export type WindowStore = Store; 10 | -------------------------------------------------------------------------------- /src/main/application/interfaces/trayProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WebContents } from '@/application/interfaces/webContents'; 7 | import { MenuItem, MenuItemIpc } from '@common/base/menu'; 8 | 9 | export interface TrayProvider { 10 | setMenu: (items: ReadonlyArray, actionsTarget?: WebContents) => void; 11 | setMainAction: (action: (() => Promise) | null) => void; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/application/interfaces/webContents.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface WebContents { 7 | send(channel: string, ...args: unknown[]): void; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/application/useCases/appDataStorage/deleteInAppDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | appDataStorage: DataStorage 10 | } 11 | 12 | export function createDeleteInAppDataStorageUseCase({ appDataStorage }: Deps) { 13 | return async function deleteInAppDataStorageUseCase(key: string): Promise { 14 | return appDataStorage.deleteItem(key); 15 | } 16 | } 17 | 18 | export type DeleteInAppDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/appDataStorage/getTextFromAppDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | appDataStorage: DataStorage 10 | } 11 | 12 | export function createGetTextFromAppDataStorageUseCase({ appDataStorage }: Deps) { 13 | return async function getTextFromAppDataStorageUseCase(key: string): Promise { 14 | return appDataStorage.getText(key); 15 | } 16 | } 17 | 18 | export type GetTextFromAppDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/appDataStorage/setTextInAppDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | appDataStorage: DataStorage 10 | } 11 | 12 | export function createSetTextInAppDataStorageUseCase({ appDataStorage }: Deps) { 13 | return async function setTextInAppDataStorageUseCase(key: string, text: string): Promise { 14 | return appDataStorage.setText(key, text); 15 | } 16 | } 17 | 18 | export type SetTextInAppDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/appMenu/setAppMenu.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppMenuProvider } from '@/application/interfaces/appMenuProvider'; 7 | import { MenuItemsIpc } from '@common/base/menu'; 8 | import { WebContents } from '@/application/interfaces/webContents'; 9 | 10 | interface Deps { 11 | appMenuProvider: AppMenuProvider; 12 | } 13 | 14 | export function createSetAppMenuUseCase(deps: Deps) { 15 | const { appMenuProvider } = deps; 16 | return async function setAppMenuUseCase(items: MenuItemsIpc, actionsTarget: WebContents): Promise { 17 | appMenuProvider.setMenu(items, actionsTarget); 18 | } 19 | } 20 | 21 | export type SetAppMenuUseCase = ReturnType; 22 | -------------------------------------------------------------------------------- /src/main/application/useCases/appMenu/setAppMenuAutoHide.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppMenuProvider } from '@/application/interfaces/appMenuProvider'; 7 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 8 | 9 | interface Deps { 10 | appMenuProvider: AppMenuProvider; 11 | } 12 | 13 | export function createSetAppMenuAutoHideUseCase(deps: Deps) { 14 | const { appMenuProvider } = deps; 15 | return async function setAppMenuAutoHideUseCase(autoHide: boolean, windowTarget: BrowserWindow): Promise { 16 | appMenuProvider.setAutoHide(autoHide, windowTarget); 17 | } 18 | } 19 | 20 | export type SetAppMenuAutoHideUseCase = ReturnType; 21 | -------------------------------------------------------------------------------- /src/main/application/useCases/browserWindow/getWindowState.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WindowStore } from '@/application/interfaces/store'; 7 | 8 | interface Deps { 9 | windowStore: WindowStore; 10 | } 11 | 12 | export function createGetWindowStateUseCase(deps: Deps) { 13 | const { windowStore } = deps; 14 | return function getWindowStateUseCase() { 15 | return windowStore.get(); 16 | } 17 | } 18 | 19 | export type GetWindowStateUseCase = ReturnType; 20 | -------------------------------------------------------------------------------- /src/main/application/useCases/browserWindow/setWindowState.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WindowStore } from '@/application/interfaces/store'; 7 | import { WindowState } from '@/base/state/window'; 8 | 9 | interface Deps { 10 | windowStore: WindowStore; 11 | } 12 | 13 | export function createSetWindowStateUseCase(deps: Deps) { 14 | const { windowStore } = deps; 15 | return function setWindowStateUseCase(newWindowState: WindowState) { 16 | windowStore.set(newWindowState); 17 | } 18 | } 19 | 20 | export type SetWindowStateUseCase = ReturnType; 21 | -------------------------------------------------------------------------------- /src/main/application/useCases/browserWindow/showBrowserWindow.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 7 | 8 | export function createShowBrowserWindowUseCase() { 9 | return function showBrowserWindowUseCase(browserWindow: BrowserWindow) { 10 | return browserWindow.show(); 11 | } 12 | } 13 | 14 | export type ShowBrowserWindowUseCase = ReturnType; 15 | -------------------------------------------------------------------------------- /src/main/application/useCases/clipboard/writeBookmarkIntoClipboard.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ClipboardProvider } from '@/application/interfaces/clipboardProvider'; 7 | 8 | interface Deps { 9 | clipboardProvider: ClipboardProvider; 10 | } 11 | 12 | export function createWriteBookmarkIntoClipboardUseCase({ clipboardProvider }: Deps) { 13 | return async function writeBookmarkIntoClipboardUseCase(title: string, url: string) { 14 | clipboardProvider.writeBookmark(title, url); 15 | } 16 | } 17 | 18 | export type WriteBookmarkIntoClipboardUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/clipboard/writeTextIntoClipboard.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ClipboardProvider } from '@/application/interfaces/clipboardProvider'; 7 | 8 | interface Deps { 9 | clipboardProvider: ClipboardProvider; 10 | } 11 | 12 | export function createWriteTextIntoClipboardUseCase({ clipboardProvider }: Deps) { 13 | return async function writeTextIntoClipboardUseCase(text: string) { 14 | clipboardProvider.writeText(text); 15 | } 16 | } 17 | 18 | export type WriteTextIntoClipboardUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/contextMenu/popupContextMenu.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ContextMenuProvider } from '@/application/interfaces/contextMenuProvider'; 7 | import { MenuItemsIpc } from '@common/base/menu'; 8 | 9 | interface Deps { 10 | contextMenuProvider: ContextMenuProvider; 11 | } 12 | 13 | export function createPopupContextMenuUseCase(deps: Deps) { 14 | const { contextMenuProvider } = deps; 15 | return async function popupContextMenuUseCase(items: MenuItemsIpc): Promise { 16 | return contextMenuProvider.popup(items); 17 | } 18 | } 19 | 20 | export type PopupContextMenuUseCase = ReturnType; 21 | -------------------------------------------------------------------------------- /src/main/application/useCases/globalShortcut/setMainShortcut.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 7 | import { GlobalShortcutProvider } from '@/application/interfaces/globalShortcutProvider'; 8 | 9 | interface Deps { 10 | globalShortcutProvider: GlobalShortcutProvider; 11 | } 12 | 13 | export function createSetMainShortcutUseCase(deps: Deps) { 14 | const { globalShortcutProvider } = deps; 15 | return async function setMainShortcutUseCase(accelerator: string, windowTarget: BrowserWindow) { 16 | return globalShortcutProvider.setMainShortcut(accelerator, windowTarget); 17 | } 18 | } 19 | 20 | export type SetMainShortcutUseCase = ReturnType; 21 | -------------------------------------------------------------------------------- /src/main/application/useCases/process/getProcessInfo.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProcessProvider } from '@/application/interfaces/processProvider'; 7 | import { ProcessInfo } from '@common/base/process'; 8 | 9 | interface Deps { 10 | processProvider: ProcessProvider; 11 | } 12 | 13 | export function createGetProcessInfoUseCase({ processProvider }: Deps) { 14 | return async function getProcessInfoUseCase(): Promise { 15 | return processProvider.getProcessInfo(); 16 | } 17 | } 18 | 19 | export type GetProcessInfoUseCase = ReturnType; 20 | -------------------------------------------------------------------------------- /src/main/application/useCases/shell/openExternalUrl.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { sanitizeUrl } from '@common/helpers/sanitizeUrl'; 7 | import { ShellProvider } from '../../interfaces/shellProvider'; 8 | 9 | interface Deps { 10 | shellProvider: ShellProvider; 11 | } 12 | 13 | export function createOpenExternalUrlUseCase({ shellProvider }: Deps) { 14 | return async function openExternalUrlUseCase(url: string): Promise { 15 | const sanitUrl = sanitizeUrl(url); 16 | if (sanitUrl) { 17 | return shellProvider.openExternal(sanitUrl); 18 | } 19 | return undefined; 20 | } 21 | } 22 | 23 | export type OpenExternalUrlUseCase = ReturnType; 24 | -------------------------------------------------------------------------------- /src/main/application/useCases/shell/openPath.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ShellProvider } from '../../interfaces/shellProvider'; 7 | 8 | interface Deps { 9 | shellProvider: ShellProvider; 10 | } 11 | 12 | export function createOpenPathUseCase({ shellProvider }: Deps) { 13 | return async function openPathUseCase(path: string): Promise { 14 | return shellProvider.openPath(path); 15 | } 16 | } 17 | 18 | export type OpenPathUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/tray/showAppAction.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { BrowserWindow } from '@/application/interfaces/browserWindow'; 7 | 8 | export const createShowAppAction = (appWindow: BrowserWindow) => async () => appWindow.show(); 9 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/clearWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createClearWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function clearWidgetDataStorageUseCase(widgetId: string): Promise { 14 | return (await widgetDataStorageManager.getObject(widgetId)).clear(); 15 | } 16 | } 17 | 18 | export type ClearWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/copyWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createCopyWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function copyWidgetDataStorageUseCase(srcWidgetId: string, destWidgetId: string): Promise { 14 | return widgetDataStorageManager.copyObjectData(srcWidgetId, destWidgetId); 15 | } 16 | } 17 | 18 | export type CopyWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/deleteInWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createDeleteInWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function deleteInWidgetDataStorageUseCase(widgetId: string, key: string): Promise { 14 | return (await widgetDataStorageManager.getObject(widgetId)).deleteItem(key); 15 | } 16 | } 17 | 18 | export type DeleteInWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/getKeysFromWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createGetKeysFromWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function getKeysFromWidgetDataStorageUseCase(widgetId: string): Promise { 14 | return (await widgetDataStorageManager.getObject(widgetId)).getKeys(); 15 | } 16 | } 17 | 18 | export type GetKeysFromWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/getTextFromWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createGetTextFromWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function getTextFromWidgetDataStorageUseCase(widgetId: string, key: string): Promise { 14 | return (await widgetDataStorageManager.getObject(widgetId)).getText(key); 15 | } 16 | } 17 | 18 | export type GetTextFromWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/application/useCases/widgetDataStorage/setTextInWidgetDataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorageManager } from '@common/application/interfaces/dataStorage'; 7 | 8 | interface Deps { 9 | widgetDataStorageManager: DataStorageManager 10 | } 11 | 12 | export function createSetTextInWidgetDataStorageUseCase({ widgetDataStorageManager }: Deps) { 13 | return async function setTextInWidgetDataStorageUseCase(widgetId: string, key: string, text: string): Promise { 14 | return (await widgetDataStorageManager.getObject(widgetId)).setText(key, text); 15 | } 16 | } 17 | 18 | export type SetTextInWidgetDataStorageUseCase = ReturnType; 19 | -------------------------------------------------------------------------------- /src/main/controllers/contextMenu.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Controller } from '@/controllers/controller'; 7 | import { IpcPopupOsContextMenuArgs, ipcPopupOsContextMenuChannel, IpcPopupOsContextMenuRes } from '@common/ipc/channels'; 8 | import { PopupContextMenuUseCase } from '@/application/useCases/contextMenu/popupContextMenu'; 9 | 10 | type Deps = { 11 | popupContextMenuUseCase: PopupContextMenuUseCase; 12 | } 13 | 14 | export function createContextMenuControllers({ 15 | popupContextMenuUseCase, 16 | }: Deps): [ 17 | Controller, 18 | ] { 19 | return [{ 20 | channel: ipcPopupOsContextMenuChannel, 21 | handle: async (_event, menuItemsIpc) => popupContextMenuUseCase(menuItemsIpc) 22 | }] 23 | } 24 | -------------------------------------------------------------------------------- /src/main/controllers/controller.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IpcMain, IpcMainEvent } from '@/controllers/interfaces/ipcMain'; 7 | 8 | export interface Controller { 9 | channel: string; 10 | handle(event: IpcMainEvent, ...args: TArgs): Promise; 11 | } 12 | 13 | export function registerControllers(ipcMain: IpcMain, controllers: Controller[]) { 14 | for (const { channel, handle } of controllers) { 15 | ipcMain.handle(channel, handle); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/controllers/process.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Controller } from '@/controllers/controller'; 7 | import { IpcGetProcessInfoArgs, ipcGetProcessInfoChannel, IpcGetProcessInfoRes } from '@common/ipc/channels'; 8 | import { GetProcessInfoUseCase } from '@/application/useCases/process/getProcessInfo'; 9 | 10 | type Deps = { 11 | getProcessInfoUseCase: GetProcessInfoUseCase; 12 | } 13 | 14 | export function createProcessControllers({ 15 | getProcessInfoUseCase, 16 | }: Deps): [ 17 | Controller, 18 | ] { 19 | return [{ 20 | channel: ipcGetProcessInfoChannel, 21 | handle: async (_event) => getProcessInfoUseCase() 22 | }] 23 | } 24 | -------------------------------------------------------------------------------- /src/main/data/windowStateStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { StateStorage, createStateStorage, windowStateDataStoragKey } from '@common/data/stateStorage'; 7 | import { DataStorageJson } from '@common/application/interfaces/dataStorage'; 8 | import { WindowState, createPersistentWindowState, currentWindowStateVersion, migrateWindowState, PersistentWindowState } from '@/base/state/window'; 9 | 10 | export type WindowStateStorage = StateStorage 11 | export function createWindowStateStorage( 12 | dataStorage: DataStorageJson, 13 | ): WindowStateStorage { 14 | return createStateStorage(dataStorage, windowStateDataStoragKey, currentWindowStateVersion, 5000, migrateWindowState, createPersistentWindowState); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/data/windowStore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WindowState, PersistentWindowState, prepareWindowState, mergeWindowStateWithPersistentWindowState } from '@/base/state/window'; 7 | import { StateStorage } from '@common/data/stateStorage'; 8 | import { createStore } from '@common/data/store'; 9 | 10 | export function createWindowStore( 11 | deps: { 12 | stateStorage: StateStorage; 13 | }, 14 | initialState: WindowState, 15 | onStoreReady?: () => void 16 | ) { 17 | return createStore( 18 | deps, 19 | initialState, 20 | prepareWindowState, 21 | mergeWindowStateWithPersistentWindowState, 22 | onStoreReady 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /src/main/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import base from '../../eslint.config.mjs'; 2 | 3 | export default [ 4 | ...base, 5 | { 6 | languageOptions: { 7 | globals: { 8 | node: 'readonly' 9 | } 10 | } 11 | } 12 | ]; 13 | -------------------------------------------------------------------------------- /src/main/infra/appsProvider/appsProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppsProvider } from '@/application/interfaces/appsProvider'; 7 | import { detectDefaultTerminal } from '@/infra/appsProvider/detectDefaultTerminal'; 8 | 9 | export function createAppsProvider(): AppsProvider { 10 | const defaultTerminal = detectDefaultTerminal(); 11 | return { 12 | getDefaultTerminal: () => defaultTerminal 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/infra/childProcessProvider/childProcessProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { spawn } from 'node:child_process'; 7 | import { ChildProcessProvider } from '@/application/interfaces/childProcessProvider'; 8 | 9 | export function createChildProcessProvider(): ChildProcessProvider { 10 | return { 11 | spawnDetached: (cmd, args, opts = {}) => { 12 | const proc = spawn(cmd, args, { 13 | ...opts, 14 | detached: true, 15 | stdio: 'ignore', 16 | windowsHide: true 17 | }); 18 | proc.unref(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/infra/clipboardProvider/clipboardProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import Electron from 'electron'; 7 | import { ClipboardProvider } from '@/application/interfaces/clipboardProvider'; 8 | 9 | export function createClipboardProvider(): ClipboardProvider { 10 | return { 11 | writeBookmark: (title, url) => (process.platform === 'darwin' || process.platform === 'win32') ? Electron.clipboard.writeBookmark(title, url) : Electron.clipboard.writeText(url), 12 | writeText: (text) => Electron.clipboard.writeText(text) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/infra/contextMenuProvider/contextMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ContextMenuProvider } from '@/application/interfaces/contextMenuProvider'; 7 | import { createElectronMenuFromMenuItemsIpc } from '@/infra/utils/menu'; 8 | 9 | export function createContextMenuProvider(): ContextMenuProvider { 10 | return { 11 | popup: async (items) => new Promise((resolve) => { 12 | const menu = createElectronMenuFromMenuItemsIpc(items, (actionId) => resolve(actionId)); 13 | menu.popup({ callback: () => resolve(undefined) }); 14 | }) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/infra/protocolHandler/protocolHandler.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { app, protocol } from 'electron'; 7 | 8 | /** 9 | * Should be called **before `app` is ready** 10 | */ 11 | export function registerProtocol( 12 | scheme: string, 13 | handler: (request: Request) => (Response) | (Promise) 14 | ): void { 15 | protocol.registerSchemesAsPrivileged([{ 16 | scheme, 17 | privileges: { 18 | standard: true, 19 | secure: true, 20 | supportFetchAPI: true, 21 | stream: true 22 | } 23 | }]) 24 | app.whenReady().then(() => { 25 | protocol.handle(scheme, handler) 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/infra/shellProvider/shellProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import Electron from 'electron'; 7 | import { ShellProvider } from '@/application/interfaces/shellProvider'; 8 | 9 | export function createShellProvider(): ShellProvider { 10 | return { 11 | openExternal: (url) => Electron.shell.openExternal(url), 12 | openPath: (path) => Electron.shell.openPath(path) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["es2021"], 5 | "module": "CommonJS", 6 | "target": "es2021", 7 | "baseUrl": "../", 8 | "paths": { 9 | "@/*": ["main/*"], 10 | "@common/*": ["common/*"] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/appMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItems } from '@common/base/menu'; 7 | 8 | export interface AppMenuProvider { 9 | setMenu: (items: MenuItems) => Promise; 10 | setAutoHide: (autoHide: boolean) => Promise; 11 | } 12 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/browserWindowProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface BrowserWindowProvider { 7 | show: () => Promise; 8 | } 9 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/clipboardProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ClipboardProvider { 7 | writeBookmark: (title: string, url: string) => Promise; 8 | writeText: (text: string) => Promise; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/contextMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItems } from '@common/base/menu'; 7 | 8 | export interface ContextMenuProvider { 9 | show: (items: MenuItems) => Promise; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/dataStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DataStorage, DataStorageJson } from '@common/application/interfaces/dataStorage'; 7 | import { ObjectManager } from '@common/base/objectManager'; 8 | 9 | export interface DataStorageRenderer extends DataStorage, DataStorageJson { } 10 | 11 | export type DataStorageManagerRenderer = ObjectManager; 12 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/dialogProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MessageBoxConfig, MessageBoxResult, OpenDialogResult, OpenDirDialogConfig, OpenFileDialogConfig, SaveDialogResult, SaveFileDialogConfig } from '@common/base/dialog'; 7 | export interface DialogProvider { 8 | showMessageBox: (config: MessageBoxConfig) => Promise; 9 | showOpenFileDialog: (config: OpenFileDialogConfig) => Promise; 10 | showSaveFileDialog: (config: SaveFileDialogConfig) => Promise; 11 | showOpenDirDialog: (config: OpenDirDialogConfig) => Promise; 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/globalShortcutProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface GlobalShortcutProvider { 7 | setMainShortcut: (accelerator: string) => Promise; 8 | } 9 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/idGenerator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface IdGenerator { 7 | (): string; 8 | } 9 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/processProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProcessInfo } from '@common/base/process'; 7 | 8 | export interface ProcessProvider { 9 | getProcessInfo: () => ProcessInfo; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/productInfoProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProductInfo } from '@/base/productInfo'; 7 | 8 | export interface ProductInfoProvider { 9 | getProductInfo(): ProductInfo; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/registry.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/base/widgetType'; 7 | 8 | export interface Registry { 9 | getWidgetTypes: () => WidgetType[]; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/shellProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface ShellProvider { 7 | openApp: (appPath: string, args?: string[]) => Promise; 8 | openExternal: (url: string) => Promise; 9 | openPath: (path: string) => Promise; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/store.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Store } from '@common/application/interfaces/store'; 7 | import { AppState } from '@/base/state/app'; 8 | 9 | export type AppStore = Store; 10 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/terminalProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface TerminalProvider { 7 | execCmdLines: (cmdLines: ReadonlyArray, cwd?: string) => Promise; 8 | } 9 | -------------------------------------------------------------------------------- /src/renderer/application/interfaces/trayMenuProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItems } from '@common/base/menu'; 7 | 8 | export interface TrayMenuProvider { 9 | setMenu: (items: MenuItems) => Promise; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/about/closeAbout.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseAboutUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'about'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseAboutUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/about/openAbout.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createOpenAboutUseCase({ 14 | appStore, 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.openModalScreen(state, 'about', undefined); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type OpenAboutUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/about/openSponsorshipUrl.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ShellProvider } from '@/application/interfaces/shellProvider'; 7 | 8 | type Deps = { 9 | shellProvider: ShellProvider; 10 | } 11 | 12 | const sponsorshipUrl = 'https://freeter.io/v2/sponsor/' 13 | 14 | export function createOpenSponsorshipUrlUseCase({ 15 | shellProvider, 16 | }: Deps) { 17 | const useCase = () => { 18 | shellProvider.openExternal(sponsorshipUrl); 19 | } 20 | 21 | return useCase; 22 | } 23 | 24 | export type OpenSponsorshipUrlUseCase = ReturnType; 25 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/actionBar/clickActionBarItem.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | // import { AppStore } from '@/application/interfaces/store'; 7 | import { EntityId } from '@/base/entity'; 8 | import { findEntityOnList } from '@/base/entityList'; 9 | import { ActionBarItems } from '@/base/actionBar'; 10 | 11 | export function clickActionBarItemUseCase(actionBarItems: ActionBarItems, actionBarItemId: EntityId) { 12 | const actionBarItem = findEntityOnList(actionBarItems, actionBarItemId); 13 | if (actionBarItem) { 14 | actionBarItem.doAction(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/appManager/closeAppManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseAppManagerUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'appManager'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseAppManagerUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/appManager/switchAppInAppManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { EntityId } from '@/base/entity'; 8 | import { modalScreensStateActions } from '@/base/state/actions'; 9 | 10 | type Deps = { 11 | appStore: AppStore; 12 | } 13 | export function createSwitchAppInAppManagerUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = (appId: EntityId) => { 17 | const state = appStore.get(); 18 | appStore.set(modalScreensStateActions.updateModalScreen(state, 'appManager', { 19 | currentAppId: appId 20 | })); 21 | } 22 | 23 | return useCase; 24 | } 25 | 26 | export type SwitchAppInAppManagerUseCase = ReturnType; 27 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/appMenu/clickAppMenuItem.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItem } from '@common/base/menu'; 7 | 8 | export function createClickAppMenuItemUseCase() { 9 | return function clickAppMenuItemUseCase(item: MenuItem): void { 10 | if (item.doAction) { 11 | item.doAction(); 12 | } 13 | } 14 | } 15 | 16 | export type ClickAppMenuItemUseCase = ReturnType; 17 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/applicationSettings/closeApplicationSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseApplicationSettingsUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'applicationSettings'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseApplicationSettingsUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/applicationSettings/openApplicationSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createOpenApplicationSettingsUseCase({ 14 | appStore, 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.openModalScreen(state, 'applicationSettings', { 19 | appConfig: state.ui.appConfig 20 | }); 21 | appStore.set(state); 22 | } 23 | 24 | return useCase; 25 | } 26 | 27 | export type OpenApplicationSettingsUseCase = ReturnType; 28 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/browserWindow/showBrowserWindow.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { BrowserWindowProvider } from '@/application/interfaces/browserWindowProvider'; 7 | 8 | type Deps = { 9 | browserWindow: BrowserWindowProvider; 10 | } 11 | 12 | export function createShowBrowserWindowUseCase({ 13 | browserWindow 14 | }: Deps) { 15 | const showBrowserWindowUseCase = () => { 16 | browserWindow.show(); 17 | } 18 | 19 | return showBrowserWindowUseCase; 20 | } 21 | 22 | export type ShowBrowserWindowUseCase = ReturnType; 23 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/contextMenu/clickContextMenuItem.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItem } from '@common/base/menu'; 7 | 8 | export function createClickContextMenuItemUseCase() { 9 | return function clickContextMenuItemUseCase(item: MenuItem): void { 10 | if (item.doAction) { 11 | item.doAction(); 12 | } 13 | } 14 | } 15 | 16 | export type ClickContextMenuItemUseCase = ReturnType; 17 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/contextMenu/showContextMenu.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ContextMenuProvider } from '@/application/interfaces/contextMenuProvider'; 7 | import { MenuItems } from '@common/base/menu'; 8 | 9 | type Deps = { 10 | contextMenu: ContextMenuProvider; 11 | } 12 | 13 | export function createShowContextMenuUseCase({ 14 | contextMenu 15 | }: Deps) { 16 | const showContextMenu = (menuItems: MenuItems) => contextMenu.show(menuItems); 17 | 18 | return showContextMenu; 19 | } 20 | 21 | export type ShowContextMenuUseCase = ReturnType; 22 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/dialog/showOpenFileDialog.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DialogProvider } from '@/application/interfaces/dialogProvider'; 7 | import { OpenFileDialogConfig } from '@common/base/dialog'; 8 | 9 | type Deps = { 10 | dialog: DialogProvider; 11 | } 12 | 13 | export function createShowOpenFileDialogUseCase({ 14 | dialog 15 | }: Deps) { 16 | const showOpenFileDialog = (cfg: OpenFileDialogConfig) => dialog.showOpenFileDialog(cfg); 17 | 18 | return showOpenFileDialog; 19 | } 20 | 21 | export type ShowOpenFileDialogUseCase = ReturnType; 22 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/dragDrop/dragEnd.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { dragDropStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createDragEndUseCase({ 14 | appStore 15 | }: Deps) { 16 | const dragEndUseCase = () => { 17 | appStore.set(dragDropStateActions.resetAll(appStore.get())); 18 | } 19 | 20 | return dragEndUseCase; 21 | } 22 | 23 | export type DragEndUseCase = ReturnType; 24 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/dragDrop/dragLeaveTarget.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { dragDropStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createDragLeaveTargetUseCase({ 14 | appStore 15 | }: Deps) { 16 | const dragLeaveTargetUseCase = () => { 17 | appStore.set(dragDropStateActions.resetOver(appStore.get())) 18 | } 19 | 20 | return dragLeaveTargetUseCase; 21 | } 22 | 23 | export type DragLeaveTargetUseCase = ReturnType; 24 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/memSaver/subs/resetDelayedWorkflowDeactivation.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { EntityId } from '@/base/entity'; 7 | import { MemSaverState } from '@/base/state/ui'; 8 | 9 | export function resetDelayedWorkflowDeactivationSubCase( 10 | workflowId: EntityId, 11 | memSaverState: MemSaverState 12 | ): MemSaverState { 13 | const { workflowTimeouts } = memSaverState; 14 | if (workflowTimeouts[workflowId]) { 15 | clearTimeout(workflowTimeouts[workflowId]); 16 | const { [workflowId]: _, ...updWorkflowTimeouts } = workflowTimeouts; 17 | memSaverState = { 18 | ...memSaverState, 19 | workflowTimeouts: updWorkflowTimeouts 20 | } 21 | } 22 | 23 | return memSaverState; 24 | } 25 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/projectManager/closeProjectManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseProjectManagerUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'projectManager'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseProjectManagerUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/shelf/subs/deleteWidgetsFromWidgetList.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { EntityId } from '@/base/entity'; 7 | import { WidgetList } from '@/base/widgetList'; 8 | 9 | export function deleteWidgetsFromWidgetListSubCase( 10 | widgetIdsToDel: EntityId[], 11 | widgetList: WidgetList, 12 | ): [newList: WidgetList, deletedIds: EntityId[]] { 13 | const delWidgetIds: EntityId[] = []; 14 | const newList = widgetList.filter(item => { 15 | if (widgetIdsToDel.indexOf(item.widgetId) > -1) { 16 | delWidgetIds.push(item.widgetId); 17 | return false; 18 | } else { 19 | return true; 20 | } 21 | }) 22 | return [newList, delWidgetIds]; 23 | } 24 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/toggleEditMode.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | 8 | type Deps = { 9 | appStore: AppStore; 10 | } 11 | 12 | export function createToggleEditModeUseCase({ 13 | appStore 14 | }: Deps) { 15 | const useCase = () => { 16 | const state = appStore.get(); 17 | const { editMode } = state.ui; 18 | appStore.set({ 19 | ...state, 20 | ui: { 21 | ...state.ui, 22 | editMode: !editMode 23 | } 24 | }) 25 | } 26 | 27 | return useCase; 28 | } 29 | 30 | export type ToggleEditModeUseCase = ReturnType; 31 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/toggleMenuBar.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | 8 | type Deps = { 9 | appStore: AppStore; 10 | } 11 | 12 | export function createToggleMenuBarUseCase({ 13 | appStore 14 | }: Deps) { 15 | const useCase = () => { 16 | const state = appStore.get(); 17 | const { menuBar } = state.ui; 18 | appStore.set({ 19 | ...state, 20 | ui: { 21 | ...state.ui, 22 | menuBar: !menuBar 23 | } 24 | }) 25 | } 26 | 27 | return useCase; 28 | } 29 | 30 | export type ToggleMenuBarUseCase = ReturnType; 31 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/trayMenu/clickTrayMenuItem.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MenuItem } from '@common/base/menu'; 7 | 8 | export function createClickTrayMenuItemUseCase() { 9 | return function clickTrayMenuItemUseCase(item: MenuItem): void { 10 | if (item.doAction) { 11 | item.doAction(); 12 | } 13 | } 14 | } 15 | 16 | export type ClickTrayMenuItemUseCase = ReturnType; 17 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/widget/subs/createWidget.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IdGenerator } from '@/application/interfaces/idGenerator'; 7 | import { Widget, createWidget } from '@/base/widget'; 8 | import { WidgetType } from '@/base/widgetType'; 9 | 10 | type Deps = { 11 | idGenerator: IdGenerator; 12 | } 13 | export function createCreateWidgetSubCase({ 14 | idGenerator, 15 | }: Deps) { 16 | function subCase(type: WidgetType, name: string): Widget { 17 | return createWidget(type, idGenerator(), name); 18 | } 19 | 20 | return subCase; 21 | } 22 | 23 | export type CreateWidgetSubCase = ReturnType; 24 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/widgetSettings/closeWidgetSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseWidgetSettingsUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'widgetSettings'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseWidgetSettingsUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/workflow/subs/createWorkflow.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IdGenerator } from '@/application/interfaces/idGenerator'; 7 | import { Workflow, createWorkflow } from '@/base/workflow'; 8 | 9 | type Deps = { 10 | idGenerator: IdGenerator; 11 | } 12 | export function createCreateWorkflowSubCase({ 13 | idGenerator, 14 | }: Deps) { 15 | function subCase(name: string): Workflow { 16 | return createWorkflow(idGenerator(), name); 17 | } 18 | 19 | return subCase; 20 | } 21 | 22 | export type CreateWorkflowSubCase = ReturnType; 23 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/workflow/subs/deleteWidgetsFromWidgetLayout.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { EntityId } from '@/base/entity'; 7 | import { WidgetLayout } from '@/base/widgetLayout'; 8 | 9 | export function deleteWidgetsFromWidgetLayoutSubCase( 10 | widgetIds: EntityId[], 11 | layout: WidgetLayout, 12 | ): [newLayout: WidgetLayout, deletedIds: EntityId[]] { 13 | const delWidgetIds: EntityId[] = []; 14 | const newLayout = layout.filter(item => { 15 | if (widgetIds.indexOf(item.widgetId) > -1) { 16 | delWidgetIds.push(item.widgetId); 17 | return false; 18 | } else { 19 | return true; 20 | } 21 | }) 22 | return [newLayout, delWidgetIds]; 23 | } 24 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/workflowSettings/closeWorkflowSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppStore } from '@/application/interfaces/store'; 7 | import { modalScreensStateActions } from '@/base/state/actions'; 8 | 9 | type Deps = { 10 | appStore: AppStore; 11 | } 12 | 13 | export function createCloseWorkflowSettingsUseCase({ 14 | appStore 15 | }: Deps) { 16 | const useCase = () => { 17 | let state = appStore.get(); 18 | state = modalScreensStateActions.closeModalScreen(state, 'workflowSettings'); 19 | appStore.set(state); 20 | } 21 | 22 | return useCase; 23 | } 24 | 25 | export type CloseWorkflowSettingsUseCase = ReturnType; 26 | -------------------------------------------------------------------------------- /src/renderer/application/useCases/worktable/resizeLayoutItem/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './resizeLayoutItem'; 7 | export * from './resizeLayoutItemEnd'; 8 | export * from './resizeLayoutItemStart'; 9 | -------------------------------------------------------------------------------- /src/renderer/assets.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | declare module '*.png' { export default '' as string } 7 | declare module '*.svg' { 8 | export const id: string; 9 | export const url: string; 10 | export const viewBox: string; 11 | export default url; 12 | } 13 | declare module '*.jpeg' { export default '' as string } 14 | declare module '*.jpg' { export default '' as string } 15 | declare module '*.mp3' { export default '' as string } 16 | -------------------------------------------------------------------------------- /src/renderer/base/actionBar.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Entity } from '@/base/entity'; 7 | import { EntityList } from '@/base/entityList'; 8 | 9 | export interface ActionBarItem extends Entity { 10 | readonly title: string; 11 | readonly icon: string; 12 | readonly enabled?: boolean; 13 | readonly pressed?: boolean; 14 | readonly doAction: () => Promise; 15 | } 16 | 17 | export type ActionBarItems = EntityList; 18 | -------------------------------------------------------------------------------- /src/renderer/base/appConfig.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MemSaverConfigApp } from '@/base/memSaver'; 7 | 8 | export interface AppConfig { 9 | mainHotkey: string; 10 | memSaver: MemSaverConfigApp; 11 | uiTheme: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/base/contextMenu.ts: -------------------------------------------------------------------------------- 1 | import { MenuItems } from '@common/base/menu'; 2 | 3 | export const contextMenuForTextInput: MenuItems = [ 4 | { role: 'undo', label: 'Undo' }, 5 | { role: 'redo', label: 'Redo' }, 6 | { type: 'separator' }, 7 | { role: 'cut', label: 'Cut' }, 8 | { role: 'copy', label: 'Copy' }, 9 | { role: 'paste', label: 'Paste' }, 10 | { type: 'separator' }, 11 | { role: 'selectAll', label: 'Select All' }, 12 | ] 13 | -------------------------------------------------------------------------------- /src/renderer/base/entity.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export type EntityId = string; 7 | 8 | export interface Entity { 9 | readonly id: EntityId; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/base/productInfo.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export type ProductInfoBacker = [name: string]; 7 | export interface ProductInfoBackers { 8 | bronzeSponsors: Array; 9 | backersPlus: Array; 10 | backers: Array; 11 | } 12 | export interface ProductInfo { 13 | version: string; 14 | builtAt: string; 15 | commitHash: string; 16 | backers: ProductInfoBackers; 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/base/state/actions/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './dragDrop'; 7 | export * from './entity'; 8 | export * from './modalScreens'; 9 | -------------------------------------------------------------------------------- /src/renderer/base/utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export function generateUniqueName(baseName: string, usedNames: string[]): string { 7 | let res = ''; 8 | for (let i = 1; i <= 1000; i++) { 9 | res = `${baseName} ${i}`; 10 | if (usedNames.indexOf(res) < 0) { 11 | return res; 12 | } 13 | } 14 | return res; 15 | } 16 | 17 | export function generateCopyName(itemName: string, usedNames: string[]): string { 18 | return generateUniqueName(itemName + ' Copy', usedNames); 19 | } 20 | -------------------------------------------------------------------------------- /src/renderer/data/appStateStorage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { StateStorage, createStateStorage, appStateDataStoragKey } from '@common/data/stateStorage'; 7 | import { DataStorageJson } from '@common/application/interfaces/dataStorage'; 8 | import { AppState, createPersistentAppState, currentAppStateVersion, migrateAppState, PersistentAppState } from '@/base/state/app'; 9 | 10 | export type AppStateStorage = StateStorage 11 | export function createAppStateStorage( 12 | dataStorage: DataStorageJson, 13 | ): AppStateStorage { 14 | return createStateStorage(dataStorage, appStateDataStoragKey, currentAppStateVersion, 5000, migrateAppState, createPersistentAppState); 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import base from '../../eslint.config.mjs'; 2 | import reactPlugin from 'eslint-plugin-react'; 3 | import reactHooks from 'eslint-plugin-react-hooks'; 4 | 5 | export default [ 6 | ...base, 7 | reactPlugin.configs.flat.recommended, 8 | reactPlugin.configs.flat['jsx-runtime'], 9 | reactHooks.configs['recommended-latest'], 10 | { 11 | languageOptions: { 12 | globals: { 13 | browser: 'readonly' 14 | } 15 | }, 16 | settings: { 17 | react: { 18 | createClass: 'createReactClass', 19 | pragma: 'React', 20 | version: 'detect' 21 | }, 22 | linkComponents: [ 23 | 'Hyperlink', 24 | { 'name': 'Link', 'linkAttribute': 'to' } 25 | ] 26 | } 27 | } 28 | ]; 29 | -------------------------------------------------------------------------------- /src/renderer/helpers/event.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export class Event { 7 | private listeners: ((...args: T) => void)[]; 8 | constructor() { 9 | this.listeners = []; 10 | } 11 | 12 | hasListener(callback: (...args: T) => void) { 13 | return (this.listeners.indexOf(callback) > -1); 14 | } 15 | 16 | addListener(callback: (...args: T) => void) { 17 | this.listeners.push(callback); 18 | } 19 | 20 | removeListener(callback: (...args: T) => void) { 21 | const idx = this.listeners.indexOf(callback); 22 | if (idx > -1) { 23 | this.listeners.splice(idx, 1); 24 | } 25 | } 26 | 27 | emit(...args: T) { 28 | this.listeners.forEach(listener => listener(...args)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/renderer/helpers/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './event'; 7 | -------------------------------------------------------------------------------- /src/renderer/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | <% if (htmlWebpackPlugin.options.env_REACT_DEVTOOLS === 'enabled') { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/renderer/index.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import {createRoot} from 'react-dom/client'; 7 | import { init } from './init'; 8 | 9 | async function main() { 10 | const { App } = await init(); 11 | 12 | const root = createRoot(document.getElementById('app') as HTMLElement); 13 | 14 | root.render(); 15 | } 16 | 17 | main(); 18 | -------------------------------------------------------------------------------- /src/renderer/infra/browserWindowProvider/browserWindowProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IpcShowBrowserWindowArgs, IpcShowBrowserWindowRes, ipcShowBrowserWindowChannel } from '@common/ipc/channels'; 7 | import { BrowserWindowProvider } from '@/application/interfaces/browserWindowProvider'; 8 | import { electronIpcRenderer } from '@/infra/mainApi/mainApi'; 9 | 10 | export function createBrowserWindowProvider(): BrowserWindowProvider { 11 | return { 12 | show: async () => { 13 | electronIpcRenderer.invoke( 14 | ipcShowBrowserWindowChannel 15 | ) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/infra/globalShortcut/globalShortcutProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IpcSetMainShortcutArgs, IpcSetMainShortcutRes, ipcSetMainShortcutChannel } from '@common/ipc/channels'; 7 | import { GlobalShortcutProvider } from '@/application/interfaces/globalShortcutProvider'; 8 | import { electronIpcRenderer } from '@/infra/mainApi/mainApi'; 9 | 10 | export function createGlobalShortcutProvider(): GlobalShortcutProvider { 11 | return { 12 | setMainShortcut: async (accelerator) => electronIpcRenderer.invoke( 13 | ipcSetMainShortcutChannel, 14 | accelerator 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/infra/globals.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProductInfoBackers } from '@/base/productInfo'; 7 | 8 | declare global { 9 | const VERSION: string; 10 | const BUILT_AT: string; 11 | const COMMIT_HASH: string; 12 | const BACKERS: ProductInfoBackers; 13 | } 14 | -------------------------------------------------------------------------------- /src/renderer/infra/idGenerator/uuidv4IdGenerator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { v4 as uuidv4 } from 'uuid'; 7 | import { IdGenerator } from '@/application/interfaces/idGenerator'; 8 | 9 | export const uuidv4IdGenerator: IdGenerator = (): string => uuidv4(); 10 | -------------------------------------------------------------------------------- /src/renderer/infra/interfaces/globals.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MainApi } from '@/infra/interfaces/mainApi'; 7 | 8 | export type RendererGlobals = { 9 | getMainApiOnce(): MainApi | undefined; 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/infra/interfaces/mainApi.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | /** 7 | * Taken from electron.d.ts and updated with generic types 8 | */ 9 | interface ElectronIpcRenderer { 10 | invoke(channel: string, ...args: TArgs): Promise; 11 | on(channel: string, listener: (...args: TArgs) => void): this; 12 | once(channel: string, listener: (...args: TArgs) => void): this; 13 | removeListener(channel: string, listener: (...args: TArgs) => void): this; 14 | send(channel: string, ...args: TArgs): void; 15 | } 16 | 17 | export interface MainApi { 18 | electronIpcRenderer: ElectronIpcRenderer; 19 | } 20 | -------------------------------------------------------------------------------- /src/renderer/infra/mainApi/__mocks__/mainApi.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MainApi } from '@/infra/interfaces/mainApi'; 7 | 8 | const mainApi: MainApi = { 9 | electronIpcRenderer: { 10 | invoke: jest.fn(), 11 | on: jest.fn(), 12 | once: jest.fn(), 13 | removeListener: jest.fn(), 14 | send: jest.fn() 15 | } 16 | } 17 | 18 | export const { electronIpcRenderer } = mainApi; 19 | -------------------------------------------------------------------------------- /src/renderer/infra/mainApi/mainApi.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { RendererGlobals } from '@/infra/interfaces/globals'; 7 | 8 | declare global { 9 | interface Window { 10 | freeter: RendererGlobals; 11 | } 12 | } 13 | 14 | const mainApi = window.freeter.getMainApiOnce(); 15 | if (!mainApi) { 16 | throw new Error('MainAPI unavailable'); 17 | } 18 | 19 | export const { electronIpcRenderer } = mainApi; 20 | -------------------------------------------------------------------------------- /src/renderer/infra/processProvider/processProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IpcGetProcessInfoArgs, ipcGetProcessInfoChannel, IpcGetProcessInfoRes } from '@common/ipc/channels'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | import { electronIpcRenderer } from '@/infra/mainApi/mainApi'; 9 | import { ProcessProvider } from '@/application/interfaces/processProvider'; 10 | 11 | export async function createProcessProvider(): Promise { 12 | const processInfo = deepFreeze(await electronIpcRenderer.invoke( 13 | ipcGetProcessInfoChannel 14 | )) 15 | return { 16 | getProcessInfo: () => processInfo 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/infra/productInfoProvider/productInfoProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { deepFreeze } from '@common/helpers/deepFreeze'; 7 | import { ProductInfoProvider } from '@/application/interfaces/productInfoProvider'; 8 | import { ProductInfo } from '@/base/productInfo'; 9 | 10 | export function createProductInfoProvider(): ProductInfoProvider { 11 | const productInfo = deepFreeze({ 12 | builtAt: BUILT_AT, 13 | commitHash: COMMIT_HASH, 14 | version: VERSION, 15 | backers: BACKERS 16 | }) 17 | return { 18 | getProductInfo: () => productInfo 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/renderer/infra/terminalProvider/terminalProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { IpcExecCmdLinesInTerminalArgs, IpcExecCmdLinesInTerminalRes, ipcExecCmdLinesInTerminalChannel } from '@common/ipc/channels'; 7 | import { electronIpcRenderer } from '@/infra/mainApi/mainApi'; 8 | import { TerminalProvider } from '@/application/interfaces/terminalProvider'; 9 | 10 | export function createTerminalProvider(): TerminalProvider { 11 | return { 12 | execCmdLines: async (cmdLines, cwd) => electronIpcRenderer.invoke( 13 | ipcExecCmdLinesInTerminalChannel, 14 | cmdLines, 15 | cwd 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/preload/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "ES6", 5 | "target": "es2021", 6 | "baseUrl": "../../", 7 | "paths": { 8 | "@/*": ["renderer/*"], 9 | "@common/*": ["common/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/registry/registry.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Registry } from '@/application/interfaces/registry'; 7 | import widgets from '@/widgets'; 8 | 9 | export const registry: Registry = { 10 | getWidgetTypes: () => widgets 11 | } 12 | -------------------------------------------------------------------------------- /src/renderer/styles.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | // For CSS 7 | declare module '*.module.css' { 8 | const classes: { [key: string]: string }; 9 | export = classes; 10 | } 11 | 12 | // For SCSS 13 | declare module '*.module.scss' { 14 | const classes: { [key: string]: string }; 15 | export = classes; 16 | } 17 | -------------------------------------------------------------------------------- /src/renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "module": "ES6", 6 | "target": "ES2021", 7 | "jsx": "react-jsx", 8 | "baseUrl": "../", 9 | "paths": { 10 | "@/*": ["renderer/*"], 11 | "@common/*": ["common/*"] 12 | }, 13 | "plugins": [{ 14 | "name": "typescript-plugin-css-modules" 15 | }] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-condensed-v25-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-100italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-300italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-500italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-700italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-900italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-italic.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/ui/assets/fonts/roboto-v30-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2 -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/add-14.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/arr-down-14.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/delete-14.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/duplicate-14.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/edit-mode-24.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/logo-150.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/ui/assets/images/appIcons/more-14.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/about/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './about'; 7 | export * from './aboutViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/app/app.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .no-projects { 7 | background-color: var(--freeter-inAppNoteNoProjectsBackground); 8 | position: fixed; 9 | top: 62px; 10 | left: 0; 11 | right: 0; 12 | bottom: 0; 13 | } 14 | 15 | .manage-icon { 16 | display: inline-block; 17 | width: 24px; 18 | height: 24px; 19 | margin: 0 6px; 20 | color: var(--freeter-inAppNoteIconColor); 21 | } 22 | -------------------------------------------------------------------------------- /src/renderer/ui/components/app/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './app'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/app/uiTheme/themes/index.ts: -------------------------------------------------------------------------------- 1 | import { UiThemeId } from '@/base/uiTheme'; 2 | import { darkTheme } from '@/ui/components/app/uiTheme/themes/dark'; 3 | import { lightTheme } from '@/ui/components/app/uiTheme/themes/light'; 4 | 5 | type UiTheme = typeof darkTheme; 6 | 7 | export const uiThemes: Record = { 8 | 'dark': darkTheme, 9 | 'light': lightTheme 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/ui/components/app/uiTheme/uiTheme.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { useEffect } from 'react'; 7 | import { UiThemeId } from '@/base/uiTheme'; 8 | import { uiThemes } from '@/ui/components/app/uiTheme/themes'; 9 | 10 | export interface UIThemeProps { 11 | themeId: UiThemeId; 12 | } 13 | 14 | export const UITheme = ({ 15 | themeId 16 | }: UIThemeProps) => { 17 | useEffect(() => { 18 | const theme = uiThemes[themeId]; 19 | Object.keys(theme).forEach((key) => { 20 | const value = theme[key as keyof typeof theme]; 21 | document.documentElement.style.setProperty(`--freeter-${key}`, value); 22 | }); 23 | }, [themeId]) 24 | return <>; 25 | } 26 | -------------------------------------------------------------------------------- /src/renderer/ui/components/appManager/appManager.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .app-list, .settings-editor { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | .app-list { 14 | left: 0; 15 | width: 30%; 16 | overflow: auto; 17 | background: var(--freeter-appManagerListBackground); 18 | &:not(:hover)::-webkit-scrollbar{ 19 | display: none; 20 | } 21 | } 22 | 23 | .settings-editor { 24 | border-left: 1px solid var(--freeter-modalScreenBorder); 25 | right:0; 26 | width: 70%; 27 | } 28 | -------------------------------------------------------------------------------- /src/renderer/ui/components/appManager/appManagerList/appManagerList.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .app-list-actions { 7 | margin: 12px 0 24px; 8 | text-align: center; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/appManager/appManagerList/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './appManagerList'; 7 | export * from './appManagerListViewModel'; 8 | export * from './appManagerListItem'; 9 | export * from './appManagerListItemViewModel'; 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/appManager/appManagerSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './appManagerSettings'; 7 | export * from './appManagerSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/appManager/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './appManager'; 7 | export * from './appManagerViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/applicationSettings/applicationSettings.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .settings-editor { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | left:0; 11 | right:0; 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/ui/components/applicationSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './applicationSettings'; 7 | export * from './applicationSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/actionBar/actionBar.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .action-bar { 7 | display: flex; 8 | align-items: center; 9 | overflow: hidden; 10 | margin: 0; 11 | padding: 0 6px; 12 | } 13 | 14 | .action-bar-item { 15 | display: inline-block; 16 | position: relative; 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/actionBar/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './actionBar'; 7 | export * from './actionBarViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/button/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './button'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/inAppNote/inAppNote.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .in-app-note { 7 | box-sizing: border-box; 8 | font-size: 36px; 9 | line-height: 48px; 10 | font-family: 'Roboto Condensed'; 11 | font-weight: 300; 12 | color: var(--freeter-inAppNoteColor); 13 | text-align: center; 14 | display: flex; 15 | align-items: center; 16 | padding: 24px 100px; 17 | justify-content: center; 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/inAppNote/inAppNote.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import * as styles from './inAppNote.module.scss'; 7 | import clsx from 'clsx'; 8 | 9 | export type InAppNoteProps = React.PropsWithChildren, HTMLDivElement>> 10 | 11 | export const InAppNote = ({ 12 | className, 13 | children, 14 | ...restProps 15 | }: InAppNoteProps) => ( 16 |
17 |
18 | {children} 19 |
20 |
21 | ) 22 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/inAppNote/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './inAppNote'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/modalScreen/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './modalScreen'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/moreInfo/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './moreInfo'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/moreInfo/moreInfo.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .more-info { 7 | width: 16px; 8 | height: 16px; 9 | line-height: 16px; 10 | display: inline-block; 11 | } 12 | 13 | .more-info-icon { 14 | width: 16px; 15 | height: 16px; 16 | display: inline-block; 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/moreInfo/moreInfo.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { SvgIcon } from '@/ui/components/basic/svgIcon'; 7 | import * as styles from './moreInfo.module.scss'; 8 | import clsx from 'clsx'; 9 | import { circleQuestion16Svg } from '@/ui/assets/images/appIcons'; 10 | 11 | export interface MoreInfoProps { 12 | info: string; 13 | className?: string; 14 | } 15 | 16 | export const MoreInfo = ({ 17 | info, 18 | className 19 | }: MoreInfoProps) => ( 20 | 21 | 22 | 23 | ) 24 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/settingsScreen/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './settingsScreen'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/settingsScreen/setting/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './settingActions'; 7 | export * from './settingBlock'; 8 | export * from './settingRow'; 9 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/settingsScreen/setting/settingActions.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ActionBarItems } from '@/base/actionBar'; 7 | import { ActionBar } from '@/ui/components/basic/actionBar'; 8 | 9 | export interface SettingActionsProps { 10 | className?: string; 11 | actions: ActionBarItems; 12 | } 13 | 14 | export const SettingActions = ({ 15 | className, 16 | actions 17 | }: SettingActionsProps) => ( 18 | 22 | ) 23 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/settingsScreen/setting/settingBlock.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MoreInfo } from '@/ui/components/basic/moreInfo'; 7 | import * as styles from '../settingsScreen.module.scss'; 8 | 9 | export interface SettingBlockProps extends React.PropsWithChildren { 10 | titleForId?: string; 11 | moreInfo?: string; 12 | title: string; 13 | } 14 | 15 | export const SettingBlock = ({ 16 | titleForId, 17 | title, 18 | children, 19 | moreInfo 20 | }: SettingBlockProps) => ( 21 |
22 | 28 |
29 | { children } 30 |
31 |
32 | ) 33 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/settingsScreen/setting/settingRow.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import clsx from 'clsx'; 7 | import * as styles from '../settingsScreen.module.scss'; 8 | 9 | export type SettingRowProps = React.PropsWithChildren>; 10 | 11 | export const SettingRow = ({ 12 | children, 13 | className, 14 | ...divProps 15 | }: SettingRowProps) => ( 16 |
17 | { children } 18 |
19 | ) 20 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/svgIcon/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './svgIcon'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/basic/svgIcon/svgIcon.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface SvgIconProps extends Pick, 'className' | 'style'> { 7 | svg: string; 8 | } 9 | 10 | export const SvgIcon = (props: SvgIconProps) => { 11 | const {svg, ...rest} = props; 12 | 13 | return ( 14 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/renderer/ui/components/projectManager/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './projectManager'; 7 | export * from './projectManagerViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/projectManager/projectManager.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .project-list, .settings-editor { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | .project-list { 14 | left: 0; 15 | width: 30%; 16 | overflow: auto; 17 | background: var(--freeter-projectManagerListBackground); 18 | &:not(:hover)::-webkit-scrollbar{ 19 | display: none; 20 | } 21 | } 22 | 23 | .settings-editor { 24 | border-left: 1px solid var(--freeter-modalScreenBorder); 25 | right:0; 26 | width: 70%; 27 | } 28 | -------------------------------------------------------------------------------- /src/renderer/ui/components/projectManager/projectManagerList/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './projectManagerList'; 7 | export * from './projectManagerListViewModel'; 8 | export * from './projectManagerListItem'; 9 | export * from './projectManagerListItemViewModel'; 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/projectManager/projectManagerList/projectManagerList.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .project-list-actions { 7 | margin: 12px 0 24px; 8 | text-align: center; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/projectManager/projectManagerSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './projectManagerSettings'; 7 | export * from './projectManagerSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/editModeToggle/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './editModeToggle'; 7 | export * from './editModeToggleViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './topBar'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/manageProjectsButton/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './manageProjectsButton'; 7 | export * from './manageProjectsButtonViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/palette/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './palette'; 7 | export * from './paletteItem'; 8 | export * from './paletteViewModel'; 9 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/projectSwitcher/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './projectSwitcher'; 7 | export * from './projectSwitcherViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/projectSwitcher/projectSwitcher.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .project-switcher { 7 | height: 36px; 8 | line-height: 24px; 9 | font-family: 'Roboto Condensed'; 10 | font-size: 16px; 11 | min-width: 140px; 12 | max-width: 280px; 13 | margin-right: 12px; 14 | option[disabled] { 15 | display: none; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/ui/components/topBar/shelf/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './shelf'; 7 | export * from './shelfViewModel'; 8 | export * from './shelfItem'; 9 | export * from './shelfItemViewModel'; 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/widget/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './widget'; 7 | export * from './widgetViewModel'; 8 | export * from './widgetById'; 9 | export * from './widgetByIdViewModel'; 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/widgetSettings/coreSettings/coreSettingsViewModel.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetCoreSettings } from '@/base/widget'; 7 | 8 | export interface CoreSettingsProps { 9 | updateCoreSettings: (coreSettings: WidgetCoreSettings) => void; 10 | coreSettings: WidgetCoreSettings; 11 | } 12 | 13 | export function useCoreSettingsViewModel(props: CoreSettingsProps) { 14 | return props; 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/ui/components/widgetSettings/coreSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './coreSettings'; 7 | export * from './coreSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/widgetSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './widgetSettings'; 7 | export * from './widgetSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/widgetSettings/widgetSettings.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .settings-preview, .settings-editor { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | } 11 | 12 | .settings-preview { 13 | left: 0; 14 | overflow: hidden; 15 | width: 40%; 16 | } 17 | 18 | .settings-editor { 19 | border-left: 1px solid var(--freeter-modalScreenBorder); 20 | right:0; 21 | width: 60%; 22 | } 23 | -------------------------------------------------------------------------------- /src/renderer/ui/components/workflowSettings/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './workflowSettings'; 7 | export * from './workflowSettingsViewModel'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/components/workflowSettings/workflowSettings.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .settings-editor { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | left:0; 11 | right:0; 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/ui/components/workflowSwitcher/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './workflowSwitcher'; 7 | export * from './workflowSwitcherItem'; 8 | export * from './workflowSwitcherItemViewModel'; 9 | export * from './workflowSwitcherViewModel'; 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/worktable/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './worktable'; 7 | -------------------------------------------------------------------------------- /src/renderer/ui/components/worktable/widgetLayout/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './widgetLayout'; 7 | export * from './widgetLayoutViewModel'; 8 | export * from './widgetLayoutItem'; 9 | export * from './widgetLayoutItemViewModel'; 10 | export * from './widgetLayoutItemGhost'; 11 | -------------------------------------------------------------------------------- /src/renderer/ui/components/worktable/widgetLayout/widgetLayoutItemGhost.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .layout-item-ghost { 7 | position: absolute; 8 | background-color: var(--freeter-widgetLayoutGhostBackground); 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/ui/components/worktable/worktable.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .no-workflows, .worktable { 7 | position: fixed; 8 | top: 99px; 9 | bottom: 0px; 10 | left: 0px; 11 | right: 0px; 12 | } 13 | 14 | .worktable { 15 | overflow: hidden; 16 | background: var(--freeter-worktableBackground); 17 | } 18 | 19 | .no-workflows { 20 | background-color: var(--freeter-inAppNoteNoWorkflowsBackground); 21 | } 22 | 23 | .edit-mode-icon, .add-icon { 24 | display: inline-block; 25 | vertical-align: middle; 26 | margin: 0 6px; 27 | color: var(--freeter-inAppNoteIconColor); 28 | } 29 | .edit-mode-icon { 30 | width: 24px; 31 | height: 24px; 32 | } 33 | .add-icon { 34 | width: 14px; 35 | height: 14px; 36 | } 37 | -------------------------------------------------------------------------------- /src/renderer/ui/hooks/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './useComponentMounted'; 7 | export * from './useElementRect'; 8 | -------------------------------------------------------------------------------- /src/renderer/ui/hooks/useComponentMounted.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { useEffect, useState } from 'react'; 7 | 8 | export function useComponentMounted() { 9 | const [componentMounted, setComponentMounted] = useState(false); 10 | 11 | useEffect(() => { 12 | setComponentMounted(true); 13 | return () => { 14 | setComponentMounted(false); 15 | } 16 | }, []); 17 | 18 | return componentMounted; 19 | } 20 | -------------------------------------------------------------------------------- /src/renderer/ui/types/dimensions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export interface WHPx { 7 | wPx: number; 8 | hPx: number; 9 | } 10 | 11 | export interface XYPx { 12 | xPx: number; 13 | yPx: number; 14 | } 15 | 16 | export interface RectPx extends WHPx, XYPx { } 17 | -------------------------------------------------------------------------------- /src/renderer/ui/types/events.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import react from 'react'; 7 | 8 | export type ContextMenuEvent = E & { 9 | contextData?: unknown; 10 | } 11 | 12 | export type ReactContextMenuEvent = react.MouseEvent>; 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/_template/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import widgetSvg from './widget.svg'; 7 | 8 | export { 9 | widgetSvg 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/widgets/_template/icons/widget.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/_template/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/widgets/appModules'; 7 | import { settingsEditorComp, Settings, createSettingsState } from './settings'; 8 | import { widgetComp } from './widget'; 9 | import { widgetSvg } from './icons'; 10 | 11 | const widgetType: WidgetType = { 12 | id: 'widget-id', 13 | icon: widgetSvg, 14 | name: 'Widget Name', 15 | minSize: { 16 | w: 1, 17 | h: 1 18 | }, 19 | description: 'Widget description', 20 | createSettingsState, 21 | settingsEditorComp, 22 | widgetComp, 23 | requiresApi: [] 24 | } 25 | 26 | export default widgetType; 27 | -------------------------------------------------------------------------------- /src/renderer/widgets/_template/widget.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ReactComponent, WidgetReactComponentProps } from '@/widgets/appModules'; 7 | import { Settings } from './settings'; 8 | 9 | function WidgetComp({settings}: WidgetReactComponentProps) { 10 | const {text} = settings; 11 | return ( 12 | <>{text} 13 | ) 14 | } 15 | 16 | export const widgetComp: ReactComponent> = { 17 | type: 'react', 18 | Comp: WidgetComp 19 | } 20 | -------------------------------------------------------------------------------- /src/renderer/widgets/commander/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import execCommandSvg from './exec-command.svg'; 7 | import widgetSvg from './widget.svg'; 8 | 9 | export { 10 | execCommandSvg, 11 | widgetSvg 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/commander/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/widgets/appModules'; 7 | import { settingsEditorComp, Settings, createSettingsState } from './settings'; 8 | import { widgetComp } from './widget'; 9 | import { widgetSvg } from './icons'; 10 | 11 | const widgetType: WidgetType = { 12 | id: 'commander', 13 | icon: widgetSvg, 14 | name: 'Commander', 15 | minSize: { 16 | w: 1, 17 | h: 1 18 | }, 19 | description: 'The Commander widget allows to set command-lines and run them in Terminal with a single click.', 20 | createSettingsState, 21 | settingsEditorComp, 22 | widgetComp, 23 | requiresApi: ['terminal'] 24 | } 25 | 26 | export default widgetType; 27 | -------------------------------------------------------------------------------- /src/renderer/widgets/commander/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .not-configured { 7 | display: block; 8 | padding: 6px; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/widgets/file-opener/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import openFileSvg from './open-file.svg'; 7 | import openFolderSvg from './open-folder.svg'; 8 | import widgetSvg from './widget.svg'; 9 | 10 | export { 11 | openFileSvg, 12 | openFolderSvg, 13 | widgetSvg 14 | } 15 | -------------------------------------------------------------------------------- /src/renderer/widgets/file-opener/icons/open-folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/file-opener/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .not-configured { 7 | display: block; 8 | padding: 6px; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/widgets/helpers.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export { debounce } from '@common/helpers/debounce' 7 | export type { DebouncedFunc } from '@common/helpers/debounce'; 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetSettings, WidgetType } from '@/widgets/appModules' 7 | import commander from './commander'; 8 | import fileOpener from './file-opener'; 9 | import linkOpener from './link-opener'; 10 | import note from './note'; 11 | import timer from './timer'; 12 | import toDoList from './to-do-list'; 13 | import webpage from './webpage'; 14 | import webQuery from './web-query'; 15 | 16 | const widgetTypes = [ 17 | commander, 18 | fileOpener, 19 | linkOpener, 20 | note, 21 | timer, 22 | toDoList, 23 | webpage, 24 | webQuery, 25 | ] as unknown as WidgetType[]; 26 | 27 | export default widgetTypes; 28 | -------------------------------------------------------------------------------- /src/renderer/widgets/link-opener/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import openLinkSvg from './open-link.svg'; 7 | import widgetSvg from './widget.svg'; 8 | 9 | export { 10 | openLinkSvg, 11 | widgetSvg 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/link-opener/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/widgets/appModules'; 7 | import { settingsEditorComp, Settings, createSettingsState } from './settings'; 8 | import { widgetComp } from './widget'; 9 | import { widgetSvg } from './icons'; 10 | 11 | const widgetType: WidgetType = { 12 | id: 'link-opener', 13 | icon: widgetSvg, 14 | name: 'Link Opener', 15 | minSize: { 16 | w: 1, 17 | h: 1 18 | }, 19 | description: 'The Link Opener widget allows you to set a link or a group of links and open them in Browser with a single click.', 20 | createSettingsState, 21 | settingsEditorComp, 22 | widgetComp, 23 | requiresApi: ['shell'] 24 | } 25 | 26 | export default widgetType; 27 | -------------------------------------------------------------------------------- /src/renderer/widgets/link-opener/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .not-configured { 7 | display: block; 8 | padding: 6px; 9 | } 10 | -------------------------------------------------------------------------------- /src/renderer/widgets/note/actionBar.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ActionBarItems } from '@/base/actionBar'; 7 | import { canCopyFullText, copyFullText, labelCopyFullText } from './actions'; 8 | import { WidgetApi } from '@/widgets/appModules'; 9 | import { copyFullTextSvg } from './icons'; 10 | 11 | export function createActionBarItems(elTextArea: HTMLTextAreaElement | null, widgetApi: WidgetApi): ActionBarItems { 12 | return (!elTextArea) ? [] : [ 13 | { 14 | enabled: canCopyFullText(), 15 | icon: copyFullTextSvg, 16 | id: 'COPY-FULL-TEXT', 17 | title: labelCopyFullText, 18 | doAction: async () => copyFullText(elTextArea, widgetApi) 19 | } 20 | ]; 21 | } 22 | -------------------------------------------------------------------------------- /src/renderer/widgets/note/actions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetApi } from '@/widgets/appModules'; 7 | 8 | export const labelCopyFullText = 'Copy Full Text'; 9 | export const labelUndo = 'Undo'; 10 | export const labelRedo = 'Redo'; 11 | export const labelCut = 'Cut'; 12 | export const labelCopy = 'Copy'; 13 | export const labelPaste = 'Paste'; 14 | export const labelSelectAll = 'Select All'; 15 | 16 | export function canCopyFullText() { 17 | return true; 18 | } 19 | 20 | export function copyFullText(elTextArea: HTMLTextAreaElement, widgetApi: WidgetApi) { 21 | widgetApi.clipboard.writeText(elTextArea.value); 22 | } 23 | -------------------------------------------------------------------------------- /src/renderer/widgets/note/icons/copy-full-text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/note/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import copyFullTextSvg from './copy-full-text.svg'; 7 | import widgetSvg from './widget.svg'; 8 | 9 | export { 10 | copyFullTextSvg, 11 | widgetSvg 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/note/icons/widget.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/8-bit-arpeggio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/8-bit-arpeggio.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/air-horn.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/air-horn.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/angry-boat.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/angry-boat.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/bike-s-bell-ring.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/bike-s-bell-ring.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/bouncing-down.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/bouncing-down.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/cuckoo-clock.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/cuckoo-clock.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/drum-and-bass-hardcore.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/drum-and-bass-hardcore.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/drum-and-bass.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/drum-and-bass.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/dubstep-wobbles.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/dubstep-wobbles.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/glass-ding.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/glass-ding.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/glockenspiel-arpeggio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/glockenspiel-arpeggio.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-arpeggio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-arpeggio.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-chimes.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-chimes.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-chord.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-chord.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-dub.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-dub.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-groove.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-groove.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-harmonics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-harmonics.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/guitar-slide.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/guitar-slide.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/hardstyle-kick.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/hardstyle-kick.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/hover-scooter.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/hover-scooter.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/metal-ding.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/metal-ding.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/movie-swell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/movie-swell.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/piano-attack.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/piano-attack.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/piano-plinks.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/piano-plinks.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/piano-reel.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/piano-reel.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/plucked-synth.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/plucked-synth.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/reversed-door-bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/reversed-door-bell.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/reversed-transform.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/reversed-transform.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/satellite-flyby.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/satellite-flyby.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/science-bells.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/science-bells.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/synth-bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/synth-bell.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/synth-tune.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/synth-tune.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/time-travel.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/time-travel.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/transformer.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/transformer.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/uplifting-synth.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/uplifting-synth.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/audio/timer-end/xylophone-tones.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeterApp/Freeter/f0ddda86b19b3bf5f8b95679ccd6e9a17bd963c0/src/renderer/widgets/timer/audio/timer-end/xylophone-tones.mp3 -------------------------------------------------------------------------------- /src/renderer/widgets/timer/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import playSvg from './play.svg'; 7 | import widgetSvg from './widget.svg'; 8 | 9 | export { 10 | playSvg, 11 | widgetSvg 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/timer/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/timer/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/widgets/appModules'; 7 | import { settingsEditorComp, Settings, createSettingsState } from './settings'; 8 | import { widgetComp } from './widget'; 9 | import { widgetSvg } from './icons'; 10 | 11 | const widgetType: WidgetType = { 12 | id: 'timer', 13 | icon: widgetSvg, 14 | name: 'Timer', 15 | minSize: { 16 | w: 1, 17 | h: 2 18 | }, 19 | description: 'The Timer widget allows you to setup a simple countdown timer that starts with a click and notifies you when time is up.', 20 | createSettingsState, 21 | settingsEditorComp, 22 | widgetComp, 23 | } 24 | 25 | export default widgetType; 26 | -------------------------------------------------------------------------------- /src/renderer/widgets/timer/useAudioFile.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { useEffect, useMemo } from 'react'; 7 | 8 | export function useAudioFile(file: string, volume: number) { 9 | const soundPlayer = useMemo(() => file !== '' ? new Audio() : null, [file]); 10 | useEffect(() => { 11 | if (soundPlayer) { 12 | soundPlayer.src = file; 13 | soundPlayer.volume = volume / 100; 14 | soundPlayer.load(); 15 | return () => soundPlayer.pause(); 16 | } 17 | return undefined; 18 | }, [soundPlayer, file, volume]) 19 | return useMemo(() => ({ 20 | play: () => { 21 | if (soundPlayer) { 22 | soundPlayer.currentTime = 0; 23 | soundPlayer.play(); 24 | } 25 | } 26 | }), [soundPlayer]) 27 | } 28 | -------------------------------------------------------------------------------- /src/renderer/widgets/timer/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .timer-button, .timer-run-screen-mmss { 7 | font-family: 'Roboto Condensed'; 8 | font-size: 24px; 9 | font-weight: 600; 10 | } 11 | 12 | .timer-run-screen { 13 | box-sizing: border-box; 14 | display: flex; 15 | padding: 6px; 16 | height: 100%; 17 | flex-direction: column; 18 | align-items: center; 19 | justify-content: center; 20 | } 21 | 22 | .timer-run-screen-mmss { 23 | margin-bottom: 6px; 24 | } 25 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/dom.ts: -------------------------------------------------------------------------------- 1 | export function scrollToItemInput(elItemInput: HTMLInputElement) { 2 | elItemInput.scrollIntoView(); 3 | } 4 | export function focusItemInput(elItemInput: HTMLInputElement) { 5 | elItemInput.focus(); 6 | } 7 | export function selectAllInItemInput(elItemInput: HTMLInputElement) { 8 | elItemInput.select(); 9 | } 10 | export function activateItemInput(elItemInput: HTMLInputElement) { 11 | scrollToItemInput(elItemInput); 12 | focusItemInput(elItemInput); 13 | } 14 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/icons/add-task.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import addTaskSvg from './add-task.svg'; 7 | import uncheckAllSvg from './uncheck-all.svg'; 8 | import widgetSvg from './widget.svg'; 9 | 10 | export { 11 | addTaskSvg, 12 | uncheckAllSvg, 13 | widgetSvg 14 | } 15 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/icons/uncheck-all.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetType } from '@/widgets/appModules'; 7 | import { settingsEditorComp, Settings, createSettingsState } from './settings'; 8 | import { widgetComp } from './widget'; 9 | import { widgetSvg } from './icons'; 10 | 11 | const widgetType: WidgetType = { 12 | id: 'to-do-list', 13 | icon: widgetSvg, 14 | name: 'To-Do List', 15 | minSize: { 16 | w: 2, 17 | h: 2 18 | }, 19 | description: 'The To-Do List widget allows yout to quickly organize tasks with simple to-do lists.', 20 | createSettingsState, 21 | settingsEditorComp, 22 | widgetComp, 23 | requiresApi: ['dataStorage'] 24 | } 25 | 26 | export default widgetType; 27 | -------------------------------------------------------------------------------- /src/renderer/widgets/to-do-list/state.ts: -------------------------------------------------------------------------------- 1 | import { List } from '@/base/list'; 2 | 3 | export const maxTextLength = 1000; 4 | 5 | export interface ToDoListItem { 6 | id: number; 7 | text: string; 8 | isDone: boolean; 9 | } 10 | 11 | export interface ToDoListState { 12 | items: List; 13 | nextItemId: number; 14 | } 15 | 16 | export type ItemEditorId = 'add-top' | number | 'add-bottom'; // number = item id to edit 17 | export type ActiveItemEditorState = { id: ItemEditorId } | null; 18 | 19 | export type GetToDoListState = () => ToDoListState; 20 | export type SetToDoListState = (newState: ToDoListState) => void; 21 | 22 | export type SetActiveItemEditorState = (newState: ActiveItemEditorState) => void; 23 | -------------------------------------------------------------------------------- /src/renderer/widgets/web-query/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import querySvg from './query.svg'; 7 | import widgetSvg from './widget.svg'; 8 | 9 | export { 10 | querySvg, 11 | widgetSvg 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/widgets/web-query/icons/query.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/web-query/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .not-configured { 7 | display: block; 8 | padding: 6px; 9 | } 10 | 11 | .web-query { 12 | display: flex; 13 | height: 100%; 14 | padding: 6px; 15 | align-items: center; 16 | box-sizing: border-box; 17 | } 18 | 19 | .web-query-input { 20 | min-width: 50px; 21 | flex: 1; 22 | } 23 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import backSvg from './back.svg'; 7 | import forwardSvg from './forward.svg'; 8 | import homeSvg from './home.svg'; 9 | import openInBrowserSvg from './open-in-browser.svg'; 10 | import reloadSvg from './reload.svg'; 11 | import reloadStartSvg from './reload-start.svg'; 12 | import reloadStopSvg from './reload-stop.svg'; 13 | import widgetSvg from './widget.svg'; 14 | 15 | export { 16 | backSvg, 17 | forwardSvg, 18 | homeSvg, 19 | openInBrowserSvg, 20 | reloadSvg, 21 | reloadStartSvg, 22 | reloadStopSvg, 23 | widgetSvg 24 | } 25 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/open-in-browser.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/reload-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/icons/reload-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/widgets/webpage/widget.module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | .webview { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | width: 100%; 11 | height: 100%; 12 | background: #FFF; // when a page has a transparent bg, this will force to show white so that it looked like in a standard browser 13 | } 14 | .loading { 15 | display: inline-block; 16 | position: absolute; 17 | left:0; 18 | bottom:0; 19 | padding: 0 12px; 20 | font-size: 12px; 21 | line-height: 26px; 22 | overflow: hidden; 23 | text-overflow: ellipsis; 24 | max-width: 100%; 25 | background: var(--freeter-componentBackground); 26 | color: var(--freeter-componentColor); 27 | } 28 | .not-configured { 29 | display: block; 30 | padding: 6px; 31 | } 32 | -------------------------------------------------------------------------------- /tests/__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | module.exports = 'test-file-stub'; 7 | -------------------------------------------------------------------------------- /tests/__mocks__/identity-obj-proxy.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | // Original identity-obj-proxy: https://github.com/keyz/identity-obj-proxy/blob/master/src/index.js 7 | // Updated to support ES named exports for styles 8 | module.exports = new Proxy({}, { 9 | get: function getter(target, key) { 10 | if (key === '__esModule') { 11 | return true; 12 | } 13 | return key; 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /tests/common/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import base from '../../eslint.config.mjs'; 2 | 3 | export default [ 4 | ...base, 5 | { 6 | languageOptions: { 7 | globals: { 8 | jest: 'readonly' 9 | } 10 | }, 11 | } 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/common/ipc/ipc.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { channelPrefix, makeIpcChannelName } from '@common/ipc/ipc'; 7 | 8 | describe('Ipc', () => { 9 | describe('makeIpcChannelName()', () => { 10 | it('should return a valid IPC channel name', () => { 11 | const testName = 'TEST-NAME'; 12 | 13 | const channelName = makeIpcChannelName(testName); 14 | 15 | expect(channelName).toBe(channelPrefix + testName); 16 | }) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /tests/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["es2021"], 5 | "module": "CommonJS", 6 | "target": "es2021", 7 | "baseUrl": "../../", 8 | "paths": { 9 | "@common/*": ["src/common/*"], 10 | "@testscommon/*": ["tests/common/*"], 11 | "@utils/*": ["tests/utils/*"], 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/main/base/state/fixtures/windowState.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WindowState } from '@/base/state/window'; 7 | import { StateInStore } from '@common/application/interfaces/store'; 8 | import { deepFreeze } from '@common/helpers/deepFreeze'; 9 | 10 | const windowState: WindowState = { 11 | x: 10, 12 | y: 20, 13 | w: 30, 14 | h: 40, 15 | isFull: false, 16 | isMaxi: false, 17 | isMini: false 18 | }; 19 | 20 | type WindowStateTestData = Partial>; 21 | 22 | export const fixtureWindowState = ( 23 | testData: WindowStateTestData 24 | ) => deepFreeze({ 25 | ...windowState, 26 | ...testData 27 | }); 28 | -------------------------------------------------------------------------------- /tests/main/data/fixtures/windowStore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { fixtureStore } from '@testscommon/data/fixtures/store'; 7 | import { WindowState } from '@/base/state/window'; 8 | 9 | export const fixtureWindowStore = fixtureStore; 10 | -------------------------------------------------------------------------------- /tests/main/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import base from '../../eslint.config.mjs'; 2 | 3 | export default [ 4 | ...base, 5 | { 6 | languageOptions: { 7 | globals: { 8 | jest: 'readonly' 9 | } 10 | }, 11 | } 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/main/infra/mocks/childProcessProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ChildProcessProvider } from '@/application/interfaces/childProcessProvider'; 7 | 8 | const childProcessProvider: ChildProcessProvider = { 9 | spawnDetached: jest.fn() 10 | } 11 | 12 | export const mockChildProcessProvider = (props: Partial) => ({ ...childProcessProvider, ...props }); 13 | -------------------------------------------------------------------------------- /tests/main/infra/mocks/processProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProcessProvider } from '@/application/interfaces/processProvider'; 7 | 8 | const processProvider: ProcessProvider = { 9 | getProcessInfo: jest.fn() 10 | } 11 | 12 | export const mockProcessProvider = (props: Partial) => ({ ...processProvider, ...props }); 13 | -------------------------------------------------------------------------------- /tests/main/infra/mocks/shellProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ShellProvider } from '@/application/interfaces/shellProvider'; 7 | 8 | const shellProvider: ShellProvider = { 9 | openExternal: jest.fn(), 10 | openPath: jest.fn() 11 | } 12 | 13 | export const mockShellProvider = (props: Partial) => ({ ...shellProvider, ...props }); 14 | -------------------------------------------------------------------------------- /tests/main/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["es2021"], 5 | "module": "CommonJS", 6 | "target": "es2021", 7 | "baseUrl": "../../", 8 | "paths": { 9 | "@/*": ["src/main/*"], 10 | "@common/*": ["src/common/*"], 11 | "@tests/*": ["tests/main/*"], 12 | "@testscommon/*": ["tests/common/*"], 13 | "@utils/*": ["tests/utils/*"], 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/renderer/application/useCases/appMenu/clickAppMenuItem.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { createClickAppMenuItemUseCase } from '@/application/useCases/appMenu/clickAppMenuItem'; 7 | import { fixtureMenuItemA } from '@testscommon/base/fixtures/menu'; 8 | 9 | function setup() { 10 | const useCase = createClickAppMenuItemUseCase(); 11 | return { 12 | useCase 13 | } 14 | } 15 | 16 | describe('clickAppMenuItemUseCase()', () => { 17 | it('should call item\'s doAction()', async () => { 18 | const testDoAction = jest.fn(); 19 | const testItem = fixtureMenuItemA({ doAction: () => testDoAction() }) 20 | const { useCase } = setup() 21 | 22 | useCase(testItem); 23 | 24 | expect(testDoAction).toBeCalledTimes(1); 25 | }); 26 | }) 27 | -------------------------------------------------------------------------------- /tests/renderer/application/useCases/trayMenu/clickTrayMenuItem.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { createClickTrayMenuItemUseCase } from '@/application/useCases/trayMenu/clickTrayMenuItem'; 7 | import { fixtureMenuItemA } from '@testscommon/base/fixtures/menu'; 8 | 9 | function setup() { 10 | const useCase = createClickTrayMenuItemUseCase(); 11 | return { 12 | useCase 13 | } 14 | } 15 | 16 | describe('clickTrayMenuItemUseCase()', () => { 17 | it('should call item\'s doAction()', async () => { 18 | const testDoAction = jest.fn(); 19 | const testItem = fixtureMenuItemA({ doAction: () => testDoAction() }) 20 | const { useCase } = setup() 21 | 22 | useCase(testItem); 23 | 24 | expect(testDoAction).toBeCalledTimes(1); 25 | }); 26 | }) 27 | -------------------------------------------------------------------------------- /tests/renderer/base/fixtures/appConfig.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppConfig } from '@/base/appConfig'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const appConfig: AppConfig = { 10 | mainHotkey: '', 11 | memSaver: { 12 | activateWorkflowsOnProjectSwitch: true, 13 | workflowInactiveAfter: -1 14 | }, 15 | uiTheme: 'light' 16 | } 17 | 18 | export const fixtureAppConfig = (testData?: Partial): AppConfig => deepFreeze({ 19 | ...appConfig, 20 | ...testData 21 | }) 22 | -------------------------------------------------------------------------------- /tests/renderer/base/fixtures/menu.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetMenuItem } from '@/base/widget'; 7 | import { makeFixture } from '@utils/makeFixture'; 8 | 9 | const widgetMenuItems: WidgetMenuItem[] = [{ 10 | label: 'M-A' 11 | }, { 12 | label: 'M-B' 13 | }, { 14 | label: 'M-C' 15 | }, { 16 | label: 'M-D' 17 | }] 18 | 19 | export const fixtureWidgetMenuItemA = makeFixture(widgetMenuItems[0]); 20 | export const fixtureWidgetMenuItemB = makeFixture(widgetMenuItems[1]); 21 | export const fixtureWidgetMenuItemC = makeFixture(widgetMenuItems[2]); 22 | export const fixtureWidgetMenuItemD = makeFixture(widgetMenuItems[3]); 23 | -------------------------------------------------------------------------------- /tests/renderer/base/fixtures/widgetList.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetListItem } from '@/base/widgetList'; 7 | import { makeFixture } from '@utils/makeFixture'; 8 | 9 | const widgetList: WidgetListItem[] = [{ 10 | id: 'WL-A', 11 | widgetId: 'W-A' 12 | }, { 13 | id: 'WL-B', 14 | widgetId: 'W-B' 15 | }, { 16 | id: 'WL-C', 17 | widgetId: 'W-C' 18 | }, { 19 | id: 'WL-D', 20 | widgetId: 'W-D' 21 | }] 22 | 23 | export const fixtureWidgetListItemA = makeFixture(widgetList[0]); 24 | export const fixtureWidgetListItemB = makeFixture(widgetList[1]); 25 | export const fixtureWidgetListItemC = makeFixture(widgetList[2]); 26 | export const fixtureWidgetListItemD = makeFixture(widgetList[3]); 27 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/appManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppManagerState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const appManagerState: AppManagerState = { 10 | currentAppId: '', 11 | deleteAppIds: null, 12 | apps: null, 13 | appIds: null, 14 | } 15 | 16 | export const fixtureAppManager = (testData?: Partial): AppManagerState => deepFreeze({ 17 | ...appManagerState, 18 | ...testData 19 | }) 20 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/applicationSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ApplicationSettingsState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const applicationSettingsState: ApplicationSettingsState = { 10 | appConfig: null 11 | } 12 | 13 | export const fixtureApplicationSettings = (testData?: Partial): ApplicationSettingsState => deepFreeze({ 14 | ...applicationSettingsState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/apps.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { AppsState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const appsState: AppsState = { 10 | appIds: [] 11 | } 12 | 13 | export const fixtureApps = (testData?: Partial): AppsState => deepFreeze({ 14 | ...appsState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/copy.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { CopyState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const copyState: CopyState = { 10 | widgets: { 11 | entities: {}, 12 | list: [] 13 | }, 14 | workflows: { 15 | entities: {}, 16 | list: [] 17 | } 18 | } 19 | 20 | export const fixtureCopyState = (testData?: Partial): CopyState => deepFreeze({ 21 | ...copyState, 22 | ...testData 23 | }) 24 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/memSaver.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { MemSaverState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const memSaverState: MemSaverState = { 10 | activeWorkflows: [], 11 | workflowTimeouts: {} 12 | } 13 | 14 | export const fixtureMemSaver = (testData?: Partial): MemSaverState => deepFreeze({ 15 | ...memSaverState, 16 | ...testData 17 | }) 18 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/palette.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { PaletteState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const paletteState: PaletteState = { 10 | widgetTypeIds: [] 11 | } 12 | 13 | export const fixturePalette = (testData?: Partial): PaletteState => deepFreeze({ 14 | ...paletteState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/projectManager.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProjectManagerState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const projectManagerState: ProjectManagerState = { 10 | currentProjectId: '', 11 | deleteProjectIds: null, 12 | projects: null, 13 | projectIds: null, 14 | duplicateProjectIds: null 15 | } 16 | 17 | export const fixtureProjectManager = (testData?: Partial): ProjectManagerState => deepFreeze({ 18 | ...projectManagerState, 19 | ...testData 20 | }) 21 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/projectSwitcher.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ProjectSwitcherState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const projectSwitcherState: ProjectSwitcherState = { 10 | currentProjectId: 'SOME-ID', 11 | projectIds: [] 12 | } 13 | 14 | export const fixtureProjectSwitcher = (testData?: Partial): ProjectSwitcherState => deepFreeze({ 15 | ...projectSwitcherState, 16 | ...testData 17 | }) 18 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/shelf.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ShelfState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const shelfState: ShelfState = { 10 | widgetList: [] 11 | } 12 | 13 | export const fixtureShelf = (testData?: Partial): ShelfState => deepFreeze({ 14 | ...shelfState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/widgetSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WidgetSettingsState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const widgetSettingsState: WidgetSettingsState = { 10 | widgetInEnv: null 11 | } 12 | 13 | export const fixtureWidgetSettings = (testData?: Partial): WidgetSettingsState => deepFreeze({ 14 | ...widgetSettingsState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/base/state/fixtures/workflowSettings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { WorkflowSettingsState } from '@/base/state/ui'; 7 | import { deepFreeze } from '@common/helpers/deepFreeze'; 8 | 9 | const workflowSettingsState: WorkflowSettingsState = { 10 | workflow: null 11 | } 12 | 13 | export const fixtureWorkflowSettings = (testData?: Partial): WorkflowSettingsState => deepFreeze({ 14 | ...workflowSettingsState, 15 | ...testData 16 | }) 17 | -------------------------------------------------------------------------------- /tests/renderer/data/fixtures/appStore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { fixtureStore } from '@testscommon/data/fixtures/store'; 7 | import { AppState } from '@/base/state/app'; 8 | 9 | export const fixtureAppStore = fixtureStore; 10 | -------------------------------------------------------------------------------- /tests/renderer/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import base from '../../eslint.config.mjs'; 2 | import jestDom from 'eslint-plugin-jest-dom'; 3 | 4 | export default [ 5 | ...base, 6 | jestDom.configs['flat/recommended'], 7 | { 8 | languageOptions: { 9 | globals: { 10 | jest: 'readonly' 11 | } 12 | }, 13 | rules: { 14 | '@typescript-eslint/no-non-null-assertion': 'off' 15 | } 16 | } 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/renderer/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.mp3'; 2 | declare module '*.scss'; 3 | declare module '*.svg'; 4 | -------------------------------------------------------------------------------- /tests/renderer/infra/idGenerator/uuidv4IdGenerator.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { uuidv4IdGenerator } from '@/infra/idGenerator/uuidv4IdGenerator' 7 | 8 | describe('uuidv4IdGenerator()', () => { 9 | it('should generate correct UUID', () => { 10 | const uuid = uuidv4IdGenerator(); 11 | expect(uuid).toMatch(/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi) 12 | }) 13 | 14 | it('should generate new UUIDs on each call', () => { 15 | const uuid1 = uuidv4IdGenerator(); 16 | const uuid2 = uuidv4IdGenerator(); 17 | expect(uuid1).not.toBe(uuid2); 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /tests/renderer/infra/mocks/dialogProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { DialogProvider } from '@/application/interfaces/dialogProvider'; 7 | 8 | export const dialogProvider: DialogProvider = { 9 | showMessageBox: jest.fn(), 10 | showOpenDirDialog: jest.fn(), 11 | showOpenFileDialog: jest.fn(), 12 | showSaveFileDialog: jest.fn() 13 | } 14 | 15 | export const mockDialogProvider = (props: Partial) => ({ ...dialogProvider, ...props }); 16 | -------------------------------------------------------------------------------- /tests/renderer/infra/mocks/shellProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { ShellProvider } from '@/application/interfaces/shellProvider'; 7 | 8 | const shellProvider: ShellProvider = { 9 | openApp: jest.fn(), 10 | openExternal: jest.fn(), 11 | openPath: jest.fn(), 12 | } 13 | 14 | export const mockShellProvider = (props: Partial) => ({ ...shellProvider, ...props }); 15 | -------------------------------------------------------------------------------- /tests/renderer/registry/registry.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import widgets from '@/widgets'; 7 | import { registry } from '@/registry/registry'; 8 | 9 | jest.mock('@/widgets') 10 | 11 | describe('Registry', () => { 12 | describe('getWidgetTypes()', () => { 13 | it('should return a default value of Widgets module', () => { 14 | const widgetTypes = registry.getWidgetTypes(); 15 | 16 | expect(widgetTypes).toBe(widgets); 17 | }) 18 | }) 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /tests/renderer/setupTests.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import '@testing-library/jest-dom'; 7 | -------------------------------------------------------------------------------- /tests/renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "module": "ES6", 6 | "target": "ES2021", 7 | "jsx": "react-jsx", 8 | "baseUrl": "../../", 9 | "paths": { 10 | "@/*": ["src/renderer/*"], 11 | "@common/*": ["src/common/*"], 12 | "@tests/*": ["tests/renderer/*"], 13 | "@testscommon/*": ["tests/common/*"], 14 | "@utils/*": ["tests/utils/*"], 15 | }, 16 | "plugins": [{ 17 | "name": "typescript-plugin-css-modules" 18 | }] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/renderer/widgets/_template/widget.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/_template/settings'; 7 | import { widgetComp } from '@/widgets/_template/widget' 8 | import { screen } from '@testing-library/react'; 9 | import { setupWidgetSut } from '@tests/widgets/setupSut' 10 | 11 | describe('Template Widget', () => { 12 | it('should show text specified in the settings', () => { 13 | const settings: Settings = { text: 'SOME TEXT VALUE' }; 14 | setupWidgetSut(widgetComp, settings); 15 | 16 | expect(screen.getByText(settings.text)).toBeInTheDocument(); 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /tests/renderer/widgets/commander/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/commander/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | cmds: ['test-cmd1', 'test-cmd2'], 11 | cwd: 'test/dir', 12 | ...settings 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/renderer/widgets/file-opener/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/file-opener/settings'; 7 | import { SettingsType } from '@/widgets/file-opener/settingsType'; 8 | 9 | export function fixtureSettings(settings: Partial): Settings { 10 | return { 11 | openIn: '', 12 | files: ['file/path1', 'file/path2'], 13 | folders: ['folder/path1', 'folder/path2'], 14 | type: SettingsType.File, 15 | ...settings 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/renderer/widgets/link-opener/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/link-opener/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | urls: ['some://url1', 'some://url2'], 11 | ...settings 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/renderer/widgets/note/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/note/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | spellCheck: true, 11 | markdown: true, 12 | ...settings 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/renderer/widgets/timer/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/timer/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | mins: 25, 11 | endSound: '', 12 | endSoundVol: 80, 13 | ...settings 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/renderer/widgets/to-do-list/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/to-do-list/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | doneToBottom: true, 11 | ...settings 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/renderer/widgets/web-query/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/web-query/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | descr: 'Descr', 11 | engine: 'ddgo', 12 | query: '', 13 | url: '', 14 | ...settings 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/renderer/widgets/webpage/fixtures.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { Settings } from '@/widgets/webpage/settings'; 7 | 8 | export function fixtureSettings(settings: Partial): Settings { 9 | return { 10 | sessionPersist: 'persist', 11 | sessionScope: 'prj', 12 | url: 'https://some.url/', 13 | autoReload: 0, 14 | injectedCSS: '', 15 | injectedJS: '', 16 | userAgent: '', 17 | ...settings 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/utils/makeFixture/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | export * from './makeFixture'; 7 | -------------------------------------------------------------------------------- /tests/utils/makeFixture/makeFixture.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright: (c) 2024, Alex Kaul 3 | * GNU General Public License v3.0 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | */ 5 | 6 | import { deepFreeze } from '@common/helpers/deepFreeze'; 7 | 8 | export const makeFixture = (fixtureData: T) => (testData?: Partial): T => deepFreeze({ ...fixtureData, ...testData }); 9 | -------------------------------------------------------------------------------- /tests/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["es2021"], 5 | "module": "CommonJS", 6 | "target": "es2021", 7 | "baseUrl": "../../", 8 | "paths": { 9 | "@common/*": ["src/common/*"], 10 | "@utils/*": ["tests/utils/*"], 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Node", 4 | "noImplicitAny": true, 5 | "esModuleInterop": true, 6 | "skipLibCheck": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "sourceMap": true 10 | }, 11 | "exclude": [ 12 | "node_modules" 13 | ] 14 | } 15 | --------------------------------------------------------------------------------