├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 1-Problem_report.md │ └── 2-Feature_request.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── arm64-staging-publish.yml │ ├── e2e-test-linux-distros.yml │ ├── e2e-test-mac.yml │ ├── e2e-test-specs.yml │ ├── e2e-test-ubuntu.yml │ ├── e2e-test-windows.yml │ ├── eth-nodes-sync-test-ubuntu.yml │ ├── package.yml │ ├── podman-install-linux.yml │ ├── prod-publish.yml │ ├── staging-publish.yml │ └── test.yml ├── .gitignore ├── .husky └── pre-commit ├── .storybook ├── main.ts ├── manager.ts ├── niceNodeTheme.ts └── preview.tsx ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── PRIVACY.md ├── README.md ├── TERMS.md ├── assets ├── assets.d.ts ├── dmg-background.png ├── dmg-background.tiff ├── dmg-background@2x.png ├── docker_400x400.jpg ├── entitlements.mac.plist ├── icon.icns ├── icon.ico ├── icon.png ├── icon.svg ├── icons │ ├── 1024x1024.png │ ├── 128x128.png │ ├── 16x16.png │ ├── 24x24.png │ ├── 256x256.png │ ├── 32x32.png │ ├── 48x48.png │ ├── 512x512.png │ ├── 64x64.png │ ├── 96x96.png │ ├── icon.svg │ └── tray │ │ ├── NNIconAlertInvertedTemplate.png │ │ ├── NNIconAlertInvertedTemplate@2x.png │ │ ├── NNIconAlertTemplate.png │ │ ├── NNIconAlertTemplate@2x.png │ │ ├── NNIconDefaultInvertedTemplate.png │ │ ├── NNIconDefaultInvertedTemplate@2x.png │ │ ├── NNIconDefaultTemplate.png │ │ ├── NNIconDefaultTemplate@2x.png │ │ └── status │ │ ├── error.svg │ │ ├── stopped.svg │ │ ├── synced.svg │ │ └── syncing.svg ├── installer.icns ├── locales │ ├── cs │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── de │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── en │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── es │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── fr │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── ja │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── ru │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ ├── vi │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json │ └── zh │ │ ├── dialog.json │ │ ├── genericComponents.json │ │ ├── notifications.json │ │ ├── systemRequirements.json │ │ ├── translation.json │ │ ├── updater.json │ │ └── windowMenu.json ├── trayIndex.html └── trayIndex.js ├── biome.jsonc ├── crowdin.yml ├── dev-app-update.yml ├── forge.config.cts ├── forge.env.d.ts ├── funding.json ├── globals.d.ts ├── index.html ├── package-lock.json ├── package.json ├── src ├── __tests__ │ ├── ci │ │ └── installPodman.test.ts │ ├── node │ │ ├── buildCliConfig.test.ts │ │ ├── childProcess.test.ts │ │ ├── mergeConfig.test.ts │ │ ├── mergeConfigOpNode.test.ts │ │ ├── neverEndingProcess.js │ │ ├── parseClientLogLevel.test.ts │ │ ├── parseLogMetadata.test.ts │ │ ├── parseNanoTimestamp.test.ts │ │ └── parsePodmanLogMetadata.test.ts │ └── react │ │ ├── App.test.tsx │ │ └── text-utils.tsx ├── common │ ├── NodeSpecs │ │ ├── README.md │ │ ├── arbitrum │ │ │ └── arbitrum-v1.0.0.json │ │ ├── base │ │ │ ├── base-v1.0.0.json │ │ │ └── files │ │ │ │ ├── genesis-l2.json │ │ │ │ ├── rollup.json │ │ │ │ ├── sepolia-genesis-l2.json │ │ │ │ └── sepolia-rollup.json │ │ ├── besu │ │ │ └── besu-v1.0.0.json │ │ ├── erigon │ │ │ └── erigon-v1.0.0.json │ │ ├── ethereum │ │ │ └── ethereum-v1.0.0.json │ │ ├── farcaster │ │ │ └── farcaster-v1.0.0.json │ │ ├── geth │ │ │ └── geth-v1.0.0.json │ │ ├── hildr │ │ │ └── hildr-v1.0.0.json │ │ ├── home-assistant-service │ │ │ └── home-assistant-service-v1.0.0.json │ │ ├── home-assistant │ │ │ └── home-assistant-v1.0.0.json │ │ ├── hubble │ │ │ └── hubble-v1.0.0.json │ │ ├── index.md │ │ ├── itzg-minecraft │ │ │ └── itzg-minecraft-v1.0.0.json │ │ ├── lighthouse │ │ │ └── lighthouse-v1.0.0.json │ │ ├── lodestar │ │ │ └── lodestar-v1.0.0.json │ │ ├── magi │ │ │ └── magi-v1.0.0.json │ │ ├── minecraft │ │ │ └── minecraft-v1.0.0.json │ │ ├── nethermind │ │ │ └── nethermind-v1.0.0.json │ │ ├── nimbus │ │ │ ├── nimbus-v1.0.0.json │ │ │ └── notes.md │ │ ├── nitro │ │ │ └── nitro-v1.0.0.json │ │ ├── op-erigon │ │ │ ├── op-geth-v1.0.0.json │ │ │ └── static │ │ │ │ └── genesis-l2.json │ │ ├── op-geth │ │ │ └── op-geth-v1.0.0.json │ │ ├── op-node │ │ │ └── op-node-v1.0.0.json │ │ ├── optimism │ │ │ ├── files │ │ │ │ └── sepolia-genesis-l2.json │ │ │ └── optimism-v1.0.0.json │ │ ├── pathfinder │ │ │ └── pathfinder-v1.0.0.json │ │ ├── prysm │ │ │ └── prysm-v1.0.0.json │ │ ├── reth │ │ │ ├── notes.md │ │ │ └── reth-v1.0.0.json │ │ └── teku │ │ │ └── teku-v1.0.0.json │ ├── index.md │ ├── node-spec-tool │ │ ├── injectDefaultControllerConfig.ts │ │ ├── specDiff.ts │ │ ├── updateActiveControllerConfig.ts │ │ └── util.ts │ ├── node.ts │ ├── nodeConfig.ts │ ├── nodePackageConfig.ts │ ├── nodeSpec.ts │ ├── rpcTranslation.ts │ └── systemRequirements.ts ├── main │ ├── arch.ts │ ├── benchbuddy │ │ └── runBenchmark.ts │ ├── consts │ │ └── notifications.ts │ ├── corsMiddleware.ts │ ├── cronJobs.ts │ ├── debug.ts │ ├── dialog.ts │ ├── docker │ │ ├── docker-compose.ts │ │ ├── docker.ts │ │ ├── install.ts │ │ ├── installOnMac.ts │ │ ├── installOnWindows.ts │ │ ├── messageFrontEnd.ts │ │ └── start.ts │ ├── downloadFile.ts │ ├── events.ts │ ├── execHelper.ts │ ├── files.ts │ ├── github.ts │ ├── httpReq.ts │ ├── i18nMain.ts │ ├── ipc.ts │ ├── logger.ts │ ├── main.ts │ ├── menu.ts │ ├── messenger.ts │ ├── minSystemRequirement.ts │ ├── monitor.ts │ ├── nn-auto-updater │ │ ├── findPackageManager.ts │ │ ├── githubReleases.ts │ │ └── main.ts │ ├── node │ │ └── setLastRunningTime.ts │ ├── nodeLibraryManager.ts │ ├── nodeManager.ts │ ├── nodePackageManager.ts │ ├── nuclearUninstall.ts │ ├── platform.ts │ ├── pm2Manager.ts │ ├── podman │ │ ├── details.ts │ │ ├── install │ │ │ ├── aptInstallScript.ts │ │ │ ├── dnfInstallScript.ts │ │ │ ├── install.ts │ │ │ ├── installOnLinux.ts │ │ │ ├── installOnMac.ts │ │ │ ├── installOnWindows.ts │ │ │ ├── installOnWindowsMsi.ts │ │ │ ├── pacmanInstallScript.ts │ │ │ ├── yumInstallScript.ts │ │ │ └── zypperInstallScript.ts │ │ ├── linux-check.ts │ │ ├── machine.ts │ │ ├── messageFrontEnd.ts │ │ ├── metrics.ts │ │ ├── metricsPolling.ts │ │ ├── podman-desktop │ │ │ ├── extension.ts │ │ │ ├── macos-check.ts │ │ │ ├── podman-cli.ts │ │ │ ├── util.ts │ │ │ └── windows-check.ts │ │ ├── podman-env-path.ts │ │ ├── podman.ts │ │ ├── start.ts │ │ ├── types.ts │ │ ├── uninstall │ │ │ ├── aptUninstallScript.ts │ │ │ ├── dnfUninstallScript.ts │ │ │ ├── pacmanUninstallScript.ts │ │ │ ├── uninstall.ts │ │ │ ├── uninstallOnLinux.ts │ │ │ ├── uninstallOnMac.ts │ │ │ ├── uninstallOnWindows.ts │ │ │ ├── yumUninstallScript.ts │ │ │ └── zypperUninstallScript.ts │ │ └── update.ts │ ├── ports.ts │ ├── power.ts │ ├── preload.ts │ ├── processExit.ts │ ├── state │ │ ├── benchmark.ts │ │ ├── eventReporting.ts │ │ ├── nodeLibrary.ts │ │ ├── nodePackages.ts │ │ ├── nodes.ts │ │ ├── notifications.ts │ │ ├── settings.ts │ │ └── store.ts │ ├── systemInfo.ts │ ├── tray.ts │ ├── updater.ts │ ├── util.ts │ └── util │ │ ├── delay.ts │ │ ├── escapePath.js │ │ ├── fixPathEnvVar.js │ │ ├── jwtSecrets.ts │ │ ├── linuxAutostartFile.ts │ │ ├── macos-release.ts │ │ ├── nodeLogUtils.ts │ │ ├── parseFileNameFromPath.ts │ │ ├── parseFileNameFromUrl.ts │ │ ├── sentryWinstonTransport.ts │ │ └── timestamp.js ├── renderer │ ├── App.tsx │ ├── DataRefresher.tsx │ ├── Generics │ │ └── redesign │ │ │ ├── Alert │ │ │ ├── Alert.tsx │ │ │ └── alert.css.ts │ │ │ ├── Banner │ │ │ ├── Banner.tsx │ │ │ └── banner.css.ts │ │ │ ├── Bubble │ │ │ ├── Bubble.tsx │ │ │ └── bubble.css.ts │ │ │ ├── Button │ │ │ ├── Button.tsx │ │ │ └── button.css.ts │ │ │ ├── Chart │ │ │ ├── Chart.tsx │ │ │ └── chart.css.ts │ │ │ ├── Checkbox │ │ │ ├── Checkbox.tsx │ │ │ └── checkbox.css.ts │ │ │ ├── Checklist │ │ │ ├── Checklist.tsx │ │ │ ├── ChecklistItem.tsx │ │ │ ├── checklist.css.ts │ │ │ └── checklistItem.css.ts │ │ │ ├── ClientCard │ │ │ ├── ClientCard.tsx │ │ │ └── clientCard.css.ts │ │ │ ├── ContentHeader │ │ │ ├── ContentHeader.tsx │ │ │ └── contentHeader.css.ts │ │ │ ├── ContentWithSideArt │ │ │ ├── ContentWithSideArt.tsx │ │ │ └── contentWithSideArt.css.ts │ │ │ ├── CopyButton │ │ │ ├── CopyButton.tsx │ │ │ └── copyButton.css.ts │ │ │ ├── DiskCapacityBarChart │ │ │ ├── DiskCapacityBarChart.tsx │ │ │ └── diskCapacityBarChart.css.ts │ │ │ ├── DynamicSettings │ │ │ ├── DynamicControls │ │ │ │ ├── Select.tsx │ │ │ │ └── TextArea.tsx │ │ │ ├── DynamicSettings.tsx │ │ │ ├── Setting.tsx │ │ │ └── convertConfigToLabelSettings.tsx │ │ │ ├── FloatingButton │ │ │ ├── FloatingButton.tsx │ │ │ └── floatingButton.css.ts │ │ │ ├── Header │ │ │ ├── Header.tsx │ │ │ └── header.css.ts │ │ │ ├── HeaderButton │ │ │ ├── HeaderButton.tsx │ │ │ └── headerButton.css.ts │ │ │ ├── HeaderMetrics │ │ │ ├── HeaderMetrics.tsx │ │ │ └── headerMetrics.css.ts │ │ │ ├── HorizontalLine │ │ │ ├── HorizontalLine.tsx │ │ │ └── horizontalLine.css.ts │ │ │ ├── Icon │ │ │ ├── Icon.tsx │ │ │ ├── LoadingIcon.tsx │ │ │ └── loadingIcon.css.ts │ │ │ ├── Input │ │ │ ├── FolderInput.tsx │ │ │ ├── Input.tsx │ │ │ ├── folderInput.css.ts │ │ │ └── input.css.ts │ │ │ ├── Label │ │ │ ├── Label.tsx │ │ │ └── label.css.ts │ │ │ ├── LabelSetting │ │ │ ├── LabelSettings.tsx │ │ │ ├── LabelValuesSection.tsx │ │ │ ├── labelSettings.css.ts │ │ │ └── labelSettingsSection.css.ts │ │ │ ├── LabelValues │ │ │ ├── LabelValues.tsx │ │ │ ├── LabelValuesSection.tsx │ │ │ ├── labelValues.css.ts │ │ │ └── labelValuesSection.css.ts │ │ │ ├── Link │ │ │ ├── DropdownLink.tsx │ │ │ ├── ExternalLink.tsx │ │ │ ├── InternalLink.tsx │ │ │ ├── Linking.tsx │ │ │ ├── externalLink.css.ts │ │ │ ├── internalLink.css.ts │ │ │ └── linking.css.ts │ │ │ ├── LogMessage │ │ │ ├── LogMessage.tsx │ │ │ └── logMessage.css.ts │ │ │ ├── Menu │ │ │ ├── Menu.tsx │ │ │ └── menu.css.ts │ │ │ ├── MenuItem │ │ │ ├── MenuItem.tsx │ │ │ └── menuItem.css.ts │ │ │ ├── Message │ │ │ ├── Message.tsx │ │ │ └── message.css.ts │ │ │ ├── MetricTypes │ │ │ ├── MetricTypes.tsx │ │ │ └── metricTypes.css.ts │ │ │ ├── Modal │ │ │ ├── Modal.tsx │ │ │ └── modal.css.ts │ │ │ ├── NodeIcon │ │ │ ├── NodeIcon.tsx │ │ │ └── nodeIcon.css.ts │ │ │ ├── NotificationIcon │ │ │ ├── NotificationIcon.tsx │ │ │ └── notificationIcon.css.ts │ │ │ ├── NotificationItem │ │ │ ├── NotificationItem.tsx │ │ │ └── notificationItem.css.ts │ │ │ ├── ProgressBar │ │ │ ├── ProgressBar.tsx │ │ │ ├── TimedProgressBar.tsx │ │ │ └── progressBar.css.ts │ │ │ ├── RedesignContainer.tsx │ │ │ ├── Select │ │ │ ├── MultiSelect.tsx │ │ │ └── Select.tsx │ │ │ ├── SelectCard │ │ │ ├── SelectCard.tsx │ │ │ └── selectCard.css.ts │ │ │ ├── SidebarLinkItem │ │ │ ├── SidebarLinkItem.tsx │ │ │ └── sidebarLinkItem.css.ts │ │ │ ├── SidebarNodeItem │ │ │ ├── SidebarNodeItem.tsx │ │ │ └── sideBarNodeItem.css.ts │ │ │ ├── SidebarTitleItem │ │ │ ├── SidebarTitleItem.tsx │ │ │ └── sidebarTitleItem.css.ts │ │ │ ├── SpecialSelect │ │ │ ├── SpecialSelect.tsx │ │ │ └── specialSelect.css.ts │ │ │ ├── Splash │ │ │ ├── Splash.tsx │ │ │ └── splash.css.ts │ │ │ ├── Stepper │ │ │ ├── Stepper.tsx │ │ │ └── stepper.css.ts │ │ │ ├── SyncModes │ │ │ ├── SyncMode.tsx │ │ │ ├── SyncModes.tsx │ │ │ └── syncModes.css.ts │ │ │ ├── SystemMonitor │ │ │ └── SystemMonitor.tsx │ │ │ ├── TabContent │ │ │ ├── TabContent.tsx │ │ │ ├── tabContent.css.ts │ │ │ └── utils.tsx │ │ │ ├── TabItem │ │ │ ├── TabItem.tsx │ │ │ └── tabItem.css.ts │ │ │ ├── Tabs │ │ │ ├── Tabs.tsx │ │ │ └── tabs.css.ts │ │ │ ├── Tag │ │ │ ├── Tag.tsx │ │ │ └── tag.css.ts │ │ │ ├── Toggle │ │ │ ├── Toggle.tsx │ │ │ └── toggle.css.ts │ │ │ ├── Tooltip │ │ │ ├── Tooltip.tsx │ │ │ └── tooltip.css.ts │ │ │ ├── Typography │ │ │ ├── Caption.tsx │ │ │ └── caption.css.ts │ │ │ ├── UpdateCallout │ │ │ ├── UpdateCallout.tsx │ │ │ └── updateCallout.css.ts │ │ │ ├── VerticalLine │ │ │ ├── VerticalLine.tsx │ │ │ └── verticalLine.css.ts │ │ │ ├── WalletPrompt │ │ │ ├── WalletPrompt.tsx │ │ │ └── walletPrompt.css.ts │ │ │ ├── consts.ts │ │ │ ├── globalStyle.css.ts │ │ │ ├── theme.css.ts │ │ │ └── utils.ts │ ├── LanguageSelect.tsx │ ├── Presentational │ │ ├── AddNode │ │ │ ├── AddNode.tsx │ │ │ └── addNode.css.ts │ │ ├── AddNodeConfiguration │ │ │ ├── AddNodeConfiguration.tsx │ │ │ ├── InitialClientConfigs.tsx │ │ │ ├── addNodeConfiguration.css.ts │ │ │ ├── deepMerge.ts │ │ │ └── mergePackageAndClientConfigValues.ts │ │ ├── AddNodeStepper │ │ │ ├── AddNodeStepper.tsx │ │ │ ├── AddNodeStepperModal.tsx │ │ │ ├── addNodeStepper.css.ts │ │ │ ├── mergeNodeRequirements.ts │ │ │ └── podmanRequirements.ts │ │ ├── AlphaBuild │ │ │ ├── AlphaBuild.tsx │ │ │ └── alphaBuild.css.ts │ │ ├── ContentMultipleClients │ │ │ ├── ContentMultipleClients.tsx │ │ │ └── contentMultipleClients.css.ts │ │ ├── ContentSingleClient │ │ │ ├── ContentSingleClient.tsx │ │ │ ├── contentSingleClient.css.ts │ │ │ └── resources.json │ │ ├── ControllerUpdate │ │ │ ├── ControllerUpdate.tsx │ │ │ └── controllerUpdate.css.ts │ │ ├── DevMode │ │ │ └── DevMode.tsx │ │ ├── FailSystemRequirements │ │ │ ├── FailSystemRequirementsDetector.tsx │ │ │ └── requirementsChecklistUtil.tsx │ │ ├── Logs │ │ │ ├── Logs.tsx │ │ │ └── logs.css.ts │ │ ├── LogsWrapper │ │ │ └── LogsWrapper.tsx │ │ ├── ModalManager │ │ │ ├── AddNodeModal.tsx │ │ │ ├── AlphaBuildModal.tsx │ │ │ ├── ControllerUpdateModal.tsx │ │ │ ├── FailSystemRequirementsModal.tsx │ │ │ ├── ModalManager.tsx │ │ │ ├── NodeSettingsModal.tsx │ │ │ ├── PodmanModal.tsx │ │ │ ├── PreferencesModal.tsx │ │ │ ├── RemoveNodeModal.tsx │ │ │ ├── ResetConfigModal.tsx │ │ │ ├── UpdateModal.tsx │ │ │ └── modalUtils.tsx │ │ ├── NodePackageScreen │ │ │ ├── NodePackageScreen.css.ts │ │ │ └── NodePackageScreen.tsx │ │ ├── NodeRequirements │ │ │ ├── NodeRequirements.tsx │ │ │ ├── nodeRequirements.css.ts │ │ │ ├── nodeStorageUtil.ts │ │ │ └── requirementsChecklistUtil.tsx │ │ ├── NodeScreen │ │ │ ├── NodeScreen.css.ts │ │ │ └── NodeScreen.tsx │ │ ├── NodeSettings │ │ │ ├── NodeSettings.css.ts │ │ │ ├── NodeSettings.tsx │ │ │ ├── NodeSettingsWrapper.tsx │ │ │ ├── WalletSettings.css.ts │ │ │ └── WalletSettings.tsx │ │ ├── NodeSetup │ │ │ └── NodeSetup.tsx │ │ ├── Notifications │ │ │ ├── Notifications.tsx │ │ │ ├── NotificationsWrapper.tsx │ │ │ ├── notifications.css.ts │ │ │ └── notificationsData.json │ │ ├── PodmanInstallation │ │ │ ├── PodmanInstallation.tsx │ │ │ └── podmanInstallation.css.ts │ │ ├── PodmanModal │ │ │ └── PodmanWrapper.tsx │ │ ├── Preferences │ │ │ ├── Preferences.tsx │ │ │ ├── PreferencesWrapper.tsx │ │ │ └── preferences.css.ts │ │ ├── RemoveNodeModal │ │ │ ├── RemoveNode.tsx │ │ │ ├── RemoveNodeWrapper.tsx │ │ │ └── removeNode.css.ts │ │ ├── ResetConfigModal │ │ │ └── ResetConfigWrapper.tsx │ │ ├── Sidebar │ │ │ ├── Sidebar.tsx │ │ │ └── sidebar.css.ts │ │ ├── SidebarNodeItemWrapper │ │ │ └── SidebarNodeItemWrapper.tsx │ │ ├── SidebarWrapper │ │ │ └── SidebarWrapper.tsx │ │ ├── StorybookLanguageSelect.tsx │ │ ├── SystemMonitor │ │ │ ├── Benchmarks.tsx │ │ │ ├── SystemMonitor.tsx │ │ │ └── systemMonitor.css.ts │ │ └── UpdateModal │ │ │ ├── Update.tsx │ │ │ ├── UpdateWrapper.tsx │ │ │ └── update.css.ts │ ├── ThemeManager.tsx │ ├── __mocks__ │ │ ├── custom-preload-mock.ts │ │ ├── electronGlobal.ts │ │ ├── react-i18next.ts │ │ └── svg.ts │ ├── app.css.ts │ ├── assets │ │ ├── fonts │ │ │ ├── Inter-Bold.ttf │ │ │ ├── Inter-ExtraLight.ttf │ │ │ ├── Inter-Light.ttf │ │ │ ├── Inter-Medium.ttf │ │ │ ├── Inter-SemiBold.ttf │ │ │ └── Inter.ttf │ │ └── images │ │ │ ├── artwork │ │ │ ├── alphaBanner.svg │ │ │ ├── auto-dark.png │ │ │ ├── auto-light.png │ │ │ ├── dark-dark.png │ │ │ ├── dark-light.png │ │ │ ├── light-dark.png │ │ │ ├── light-light.png │ │ │ ├── onboarding-01-Dm.png │ │ │ ├── onboarding-01-Lm.png │ │ │ ├── onboarding-02-Dm.png │ │ │ ├── onboarding-02-Lm.png │ │ │ ├── onboarding-03-Dm.png │ │ │ ├── onboarding-03-Lm.png │ │ │ ├── wallet.png │ │ │ ├── welcome-Dm.png │ │ │ └── welcome-Lm.png │ │ │ ├── icons │ │ │ ├── Add.svg │ │ │ ├── Bell.svg │ │ │ ├── Binoculars.svg │ │ │ ├── Block.svg │ │ │ ├── Blocks.svg │ │ │ ├── Bolt-strike.svg │ │ │ ├── Bolt.svg │ │ │ ├── CPU.svg │ │ │ ├── Calendar.svg │ │ │ ├── Check-badge-filled-1.svg │ │ │ ├── Check-badge-filled.svg │ │ │ ├── Check-circle-filled.svg │ │ │ ├── Check-circle.svg │ │ │ ├── Check-double.svg │ │ │ ├── Check.svg │ │ │ ├── Check2.svg │ │ │ ├── Close-circle-filled.svg │ │ │ ├── Close-circle.svg │ │ │ ├── Close.svg │ │ │ ├── Copy.svg │ │ │ ├── Disk.svg │ │ │ ├── Disks.svg │ │ │ ├── Down-large.svg │ │ │ ├── Down.svg │ │ │ ├── Download-1.svg │ │ │ ├── Download.svg │ │ │ ├── Ellipsis.svg │ │ │ ├── External.svg │ │ │ ├── Filter-large-filled.svg │ │ │ ├── Filter-large.svg │ │ │ ├── Filter.svg │ │ │ ├── Health.svg │ │ │ ├── Info-circle-filled.svg │ │ │ ├── Info-circle.svg │ │ │ ├── Intermediate.svg │ │ │ ├── Left-large.svg │ │ │ ├── Left.svg │ │ │ ├── Lightning.svg │ │ │ ├── Logs.svg │ │ │ ├── Mail.svg │ │ │ ├── Nicenode-darkmode.svg │ │ │ ├── Nicenode-lightmode.svg │ │ │ ├── Nodes.svg │ │ │ ├── Peers.svg │ │ │ ├── Play.svg │ │ │ ├── Popup.svg │ │ │ ├── Preferences.svg │ │ │ ├── Right-large.svg │ │ │ ├── Right.svg │ │ │ ├── Scroll-fill.svg │ │ │ ├── Scroll.svg │ │ │ ├── Search.svg │ │ │ ├── Settings.svg │ │ │ ├── Shape1.svg │ │ │ ├── Shape2.svg │ │ │ ├── Shape3.svg │ │ │ ├── Shape4.svg │ │ │ ├── Slots.svg │ │ │ ├── Speedometer.svg │ │ │ ├── Spinner-endless.svg │ │ │ ├── Spinner-small.svg │ │ │ ├── Spinner.svg │ │ │ ├── Stop.svg │ │ │ ├── Sync-small.svg │ │ │ ├── Sync.svg │ │ │ ├── Syncing.svg │ │ │ ├── Up-large.svg │ │ │ ├── Up.svg │ │ │ ├── Warning-circle-filled.svg │ │ │ ├── Warning-circle.svg │ │ │ └── index.tsx │ │ │ ├── logo │ │ │ ├── color.svg │ │ │ ├── mono-inverse.svg │ │ │ └── mono.svg │ │ │ ├── nodeBackgrounds │ │ │ ├── Besu.png │ │ │ ├── Erigon.png │ │ │ ├── Geth.png │ │ │ ├── Lighthouse.png │ │ │ ├── Lodestar.png │ │ │ ├── Nethermind.png │ │ │ ├── Nimbus.png │ │ │ ├── Prysm.png │ │ │ ├── Reth.png │ │ │ ├── Teku.png │ │ │ └── index.tsx │ │ │ ├── nodeIcons │ │ │ ├── Logo-Arbitrum.png │ │ │ ├── Logo-Base.png │ │ │ ├── Logo-Besu.png │ │ │ ├── Logo-Erigon.png │ │ │ ├── Logo-Ethereum.png │ │ │ ├── Logo-Farcaster.png │ │ │ ├── Logo-Geth.png │ │ │ ├── Logo-Lighthouse.png │ │ │ ├── Logo-Livepeer.png │ │ │ ├── Logo-Lodestar.png │ │ │ ├── Logo-Magi.png │ │ │ ├── Logo-Minecraft.png │ │ │ ├── Logo-Nethermind.png │ │ │ ├── Logo-Nimbus.png │ │ │ ├── Logo-OP.png │ │ │ ├── Logo-Optimism.png │ │ │ ├── Logo-OptimismJava.png │ │ │ ├── Logo-Prysm.png │ │ │ ├── Logo-Radicle.png │ │ │ ├── Logo-Reth.png │ │ │ ├── Logo-Starknet.png │ │ │ ├── Logo-Teku.png │ │ │ ├── Logo-zkSync.png │ │ │ ├── error.svg │ │ │ ├── healthy.svg │ │ │ ├── index.tsx │ │ │ ├── sync.svg │ │ │ └── warning.svg │ │ │ ├── syncModes │ │ │ ├── syncMode1.svg │ │ │ ├── syncMode2.svg │ │ │ └── syncMode3.svg │ │ │ └── wallets │ │ │ ├── argent.png │ │ │ ├── brave.png │ │ │ ├── coinbase.png │ │ │ ├── index.tsx │ │ │ ├── metamask.png │ │ │ └── tally.png │ ├── electronGlobal.ts │ ├── env.d.ts │ ├── ethers.js │ ├── events │ │ ├── environment.ts │ │ ├── events.ts │ │ └── reportEvent.ts │ ├── i18n.js │ ├── index.tsx │ ├── ipc.ts │ ├── jsonRpcClient.ts │ ├── preload.d.ts │ ├── renderer.ts │ ├── reset.css │ ├── state │ │ ├── hooks.ts │ │ ├── modal.ts │ │ ├── network.ts │ │ ├── node.ts │ │ ├── nodeService.ts │ │ ├── notificationsService.ts │ │ ├── rpcExecuteTranslation.ts │ │ ├── services.ts │ │ ├── settingsService.ts │ │ └── store.ts │ ├── themeManager.css.ts │ └── utils.ts └── stories │ ├── Generic │ ├── Alert.stories.tsx │ ├── Banner.stories.tsx │ ├── Bubble.stories.tsx │ ├── Button.stories.tsx │ ├── Checkbox.stories.tsx │ ├── Checklist.stories.tsx │ ├── ClientCard.stories.tsx │ ├── ContentHeader.stories.tsx │ ├── DynamicSettings.stories.tsx │ ├── ExternalLink.stories.tsx │ ├── Header.stories.tsx │ ├── HeaderButton.stories.tsx │ ├── HeaderMetrics.stories.tsx │ ├── Input.stories.tsx │ ├── InternalLink.stories.tsx │ ├── Label.stories.tsx │ ├── LabelSettings.stories.tsx │ ├── LineKeyValues.stories.tsx │ ├── Link.stories.tsx │ ├── LogMessage.stories.tsx │ ├── Menu.stories.tsx │ ├── Message.stories.tsx │ ├── MetricTypes.stories.tsx │ ├── Modal.stories.tsx │ ├── NodeIcon.stories.tsx │ ├── NotificationIcon.stories.tsx │ ├── NotificationItem.stories.tsx │ ├── ProgressBar.stories.tsx │ ├── Select.stories.tsx │ ├── SelectCard.stories.tsx │ ├── SidebarLinkItem.stories.tsx │ ├── SidebarNodeItem.stories.tsx │ ├── SpecialSelect.stories.tsx │ ├── Splash.stories.tsx │ ├── Stepper.stories.tsx │ ├── SyncModes.stories.tsx │ ├── TabItem.stories.tsx │ ├── Tabs.stories.tsx │ ├── Tag.stories.tsx │ ├── Toggle.stories.tsx │ ├── Tooltip.stories.tsx │ └── UpdateCallout.stories.tsx │ ├── Introduction.mdx │ ├── Presentational │ ├── AddEthereumNode.stories.tsx │ ├── AddNodeStepper.stories.tsx │ ├── ContentSingleClient.stories.tsx │ ├── DockerInstallation.stories.tsx │ ├── Logs.stories.tsx │ ├── NodeRequirements.stories.tsx │ ├── NodeSettings.stories.tsx │ ├── Notifications.stories.tsx │ ├── Preferences.stories.tsx │ └── RemoveNode.stories.tsx │ ├── RedesignContainer.tsx │ ├── StorybookLanguageSelect.tsx │ └── assets │ ├── fonts │ └── Inter.ttf │ └── icons │ ├── index.tsx │ ├── play.svg │ └── settings.svg ├── test ├── containers.conf ├── debian12.dockerfile ├── fedora40.dockerfile ├── podman-containers.conf ├── podman-fedora-wdio.dockerfile ├── specs │ ├── ci │ │ └── test.e2e.ts │ └── longRunningEthNodes.e2e.ts └── ubuntu24.dockerfile ├── tsconfig.json ├── vite.base.config.ts ├── vite.main.config.ts ├── vite.preload.config.ts ├── vite.renderer.config.ts ├── vite.storybook.config.ts ├── wdio.conf.ts └── wdioEthNodeSpecs.conf.ts /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vite/ 3 | out/ 4 | -------------------------------------------------------------------------------- /.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 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.exe binary 3 | *.png binary 4 | *.jpg binary 5 | *.jpeg binary 6 | *.ico binary 7 | *.icns binary 8 | *.eot binary 9 | *.otf binary 10 | *.ttf binary 11 | *.woff binary 12 | *.woff2 binary 13 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: nicenode.eth 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-Problem_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem report 3 | about: You're having technical issues. 🐞 4 | labels: 'problem' 5 | --- 6 | 7 | 8 | 9 | ## Problem details 10 | 11 | 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: You want something added to NiceNode. 🎉 4 | labels: 'enhancement' 5 | --- 6 | 7 | ## Feature details 8 | 9 | 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Maintain dependencies for GitHub Actions 9 | - package-ecosystem: 'github-actions' 10 | directory: '/' 11 | schedule: 12 | interval: 'monthly' 13 | 14 | - package-ecosystem: 'npm' 15 | directory: '/' # Location of package manifests 16 | schedule: 17 | interval: 'monthly' 18 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 90 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 10 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - discussion 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.github/workflows/podman-install-linux.yml: -------------------------------------------------------------------------------- 1 | name: Podman Install on Linux Distros 2 | on: 3 | push: 4 | # branches: [ main ] 5 | workflow_dispatch: 6 | 7 | jobs: 8 | container-test-job: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | container: [ 14 | "ubuntu:24.10", 15 | "ubuntu:24.04", 16 | "debian:12", 17 | "fedora:40", 18 | "fedora:39", 19 | "manjarolinux/base", 20 | "archlinux:latest", 21 | ] 22 | 23 | container: 24 | image: ${{ matrix.container }} 25 | env: 26 | NODE_ENV: test 27 | steps: 28 | - name: print os version details 29 | run: cat /etc/os-release 30 | 31 | - uses: actions/checkout@v4 32 | - uses: actions/setup-node@v4 33 | with: 34 | node-version: 20 35 | 36 | - name: 🧱 Install Dependencies 37 | run: | 38 | npm ci 39 | 40 | - name: 🧱 Run tests 41 | run: | 42 | npm run testCi 43 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | timeout-minutes: 25 8 | environment: staging 9 | 10 | runs-on: ${{ matrix.os }} 11 | 12 | strategy: 13 | matrix: 14 | os: [macos-latest, windows-latest, ubuntu-latest] 15 | 16 | steps: 17 | - name: Check out Git repository 18 | uses: actions/checkout@v4 19 | 20 | - name: Install Node.js and NPM 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: 20 24 | cache: npm 25 | 26 | - name: npm install 27 | run: | 28 | npm install 29 | 30 | - name: npm lint 31 | run: | 32 | npm run lint 33 | 34 | # - name: npm exec tsc 35 | # run: | 36 | # npm exec tsc --verbose 37 | 38 | - name: npm test 39 | run: | 40 | npm run test 41 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | npm run safeFix 4 | npm run lint 5 | # npm exec tsc 6 | npm run package 7 | npm run test 8 | -------------------------------------------------------------------------------- /.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import type { StorybookConfig } from '@storybook/react-vite'; 2 | 3 | const config: StorybookConfig = { 4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], 5 | addons: [ 6 | '@storybook/addon-links', 7 | '@storybook/addon-essentials', 8 | '@storybook/addon-interactions' 9 | ], 10 | logLevel: 'debug', 11 | docs: { 12 | autodocs: 'tag', 13 | }, 14 | framework: { 15 | name: '@storybook/react-vite', 16 | options: {} 17 | }, 18 | core: { 19 | builder: { 20 | name: '@storybook/builder-vite', 21 | options: { 22 | viteConfigPath: './vite.storybook.config.ts', 23 | }, 24 | }, 25 | }, 26 | }; 27 | 28 | export default config; 29 | -------------------------------------------------------------------------------- /.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/manager-api'; 2 | import niceNodeTheme from './niceNodeTheme'; 3 | 4 | addons.setConfig({ 5 | theme: niceNodeTheme, 6 | }); 7 | -------------------------------------------------------------------------------- /.storybook/niceNodeTheme.ts: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming/create'; 2 | import { processes } from 'systeminformation'; 3 | 4 | let brandUrl = 'https://nndesign.netlify.app/' 5 | if(process.env.NODE_ENV === 'development') { 6 | brandUrl = 'http://localhost:6006/' 7 | } 8 | 9 | export default create({ 10 | base: 'dark', 11 | brandTitle: 'NiceNode UI Components', 12 | brandUrl, 13 | brandImage: 'https://www.nicenode.xyz/favicon.png', 14 | brandTarget: '_self', 15 | }); 16 | -------------------------------------------------------------------------------- /.storybook/preview.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RedesignContainer from '../src/renderer/Generics/redesign/RedesignContainer'; 4 | import type { Preview } from '@storybook/react'; 5 | 6 | export const parameters = { 7 | // actions: { argTypesRegex: '^on[A-Z].*' }, 8 | controls: { 9 | matchers: { 10 | // color: /(background|color)$/i, 11 | date: /Date$/, 12 | }, 13 | }, 14 | }; 15 | const preview: Preview = { 16 | parameters, 17 | decorators: [ 18 | (Story) => ( 19 | 20 | 21 | 22 | ), 23 | ], 24 | }; 25 | 26 | export default preview; 27 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["biomejs.biome", "editorconfig.editorconfig"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Electron: Main", 6 | "type": "node", 7 | "request": "launch", 8 | "protocol": "inspector", 9 | "runtimeExecutable": "npm", 10 | "runtimeArgs": [ 11 | "run start:main --inspect=5858 --remote-debugging-port=9223" 12 | ], 13 | "preLaunchTask": "Start Webpack Dev" 14 | }, 15 | { 16 | "name": "Electron: Renderer", 17 | "type": "chrome", 18 | "request": "attach", 19 | "port": 9223, 20 | "webRoot": "${workspaceFolder}", 21 | "timeout": 15000 22 | } 23 | ], 24 | "compounds": [ 25 | { 26 | "name": "Electron: All", 27 | "configurations": ["Electron: Main", "Electron: Renderer"] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.defaultFormatter": "biomejs.biome", 4 | "javascript.validate.enable": false, 5 | "javascript.format.enable": false, 6 | "typescript.format.enable": false, 7 | "search.exclude": { 8 | ".git": true, 9 | ".eslintcache": true, 10 | ".erb/dll": true, 11 | "release/{build,app/dist}": true, 12 | "node_modules": true, 13 | "npm-debug.log.*": true, 14 | "test/**/__snapshots__": true, 15 | "package-lock.json": true, 16 | "*.{css,sass,scss}.d.ts": true 17 | }, 18 | "[typescript]": { 19 | "editor.defaultFormatter": "biomejs.biome" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "label": "Start Webpack Dev", 7 | "script": "start:renderer", 8 | "options": { 9 | "cwd": "${workspaceFolder}" 10 | }, 11 | "isBackground": true, 12 | "problemMatcher": { 13 | "owner": "custom", 14 | "pattern": { 15 | "regexp": "____________" 16 | }, 17 | "background": { 18 | "activeOnStart": true, 19 | "beginsPattern": "Compiling\\.\\.\\.$", 20 | "endsPattern": "(Compiled successfully|Failed to compile)\\.$" 21 | } 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022-present NiceNode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/assets.d.ts: -------------------------------------------------------------------------------- 1 | type Styles = Record; 2 | 3 | declare module '*.svg' { 4 | const content: string; 5 | export default content; 6 | } 7 | 8 | declare module '*.png' { 9 | const content: string; 10 | export default content; 11 | } 12 | 13 | declare module '*.jpg' { 14 | const content: string; 15 | export default content; 16 | } 17 | 18 | declare module '*.scss' { 19 | const content: Styles; 20 | export default content; 21 | } 22 | 23 | declare module '*.sass' { 24 | const content: Styles; 25 | export default content; 26 | } 27 | 28 | declare module '*.css' { 29 | const content: Styles; 30 | export default content; 31 | } 32 | -------------------------------------------------------------------------------- /assets/dmg-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/dmg-background.png -------------------------------------------------------------------------------- /assets/dmg-background.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/dmg-background.tiff -------------------------------------------------------------------------------- /assets/dmg-background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/dmg-background@2x.png -------------------------------------------------------------------------------- /assets/docker_400x400.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/docker_400x400.jpg -------------------------------------------------------------------------------- /assets/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-jit 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icon.icns -------------------------------------------------------------------------------- /assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icon.ico -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icon.png -------------------------------------------------------------------------------- /assets/icons/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/1024x1024.png -------------------------------------------------------------------------------- /assets/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/128x128.png -------------------------------------------------------------------------------- /assets/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/16x16.png -------------------------------------------------------------------------------- /assets/icons/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/24x24.png -------------------------------------------------------------------------------- /assets/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/256x256.png -------------------------------------------------------------------------------- /assets/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/32x32.png -------------------------------------------------------------------------------- /assets/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/48x48.png -------------------------------------------------------------------------------- /assets/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/512x512.png -------------------------------------------------------------------------------- /assets/icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/64x64.png -------------------------------------------------------------------------------- /assets/icons/96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/96x96.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconAlertInvertedTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconAlertInvertedTemplate.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconAlertInvertedTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconAlertInvertedTemplate@2x.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconAlertTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconAlertTemplate.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconAlertTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconAlertTemplate@2x.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconDefaultInvertedTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconDefaultInvertedTemplate.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconDefaultInvertedTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconDefaultInvertedTemplate@2x.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconDefaultTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconDefaultTemplate.png -------------------------------------------------------------------------------- /assets/icons/tray/NNIconDefaultTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/icons/tray/NNIconDefaultTemplate@2x.png -------------------------------------------------------------------------------- /assets/icons/tray/status/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/tray/status/stopped.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/tray/status/synced.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/tray/status/syncing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/installer.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/assets/installer.icns -------------------------------------------------------------------------------- /assets/locales/cs/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Vyberte složku pro {{storageForName}} úložiště", 3 | "SelectNodeFolder": "Vyberte složku pro ukládání dat uzlu" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/cs/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Málo místa na disku", 3 | "LowDiskSpaceDescription": "Místo na disku je menší než 40GB", 4 | "InternetConnectionDownTitle": "Nemáte přístup k Internetu", 5 | "InternetConnectionDownDescription": "Všechny uzly ovlivněny", 6 | "ClosedPortsTitle": "Uzavřené porty", 7 | "ClosedPortsDescription": "Porty {{variable}} nemusí být otevřeny ve vaší lokální síti", 8 | "UnexpectedPortsOpenTitle": "Nečekaně otevřené porty", 9 | "UnexpectedPortsOpenDescription": "Porty {{variable}} jsou otevřené a měly by být uzavřeny ve vaší lokální síti" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/cs/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Aktualizace pro NiceNode k dispozici", 3 | "DownloadingUpdate": "Stahování NiceNode aktualizace...", 4 | "UpdateNiceNode": "Chcete nyní aktualizovat NiceNode? Po stažení aktualizace se NiceNode restartuje. Aktualizovat na verzi", 5 | "Yes": "Ano", 6 | "No": "Ne", 7 | "NoUpdateAvailable": "Nejsou dostupné žádné aktualizace", 8 | "ErrorUpdating": "Omlouváme se, došlo k chybě při aktualizaci NiceNode", 9 | "UnableToInstallUpdate": "Není možné nainstalovat novou verzi NiceNode. Můžete zkusit stáhnout novou verzi manuálně na {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/de/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Ordner für {{storageForName}}-Speicher auswählen", 3 | "SelectNodeFolder": "Ordner für die Speicherung von Knotendaten auswählen" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/de/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Niedriger Speicherplatz", 3 | "LowDiskSpaceDescription": "Der Speicherplatz ist niedriger als 40GB", 4 | "InternetConnectionDownTitle": "Internetverbindung unterbrochen", 5 | "InternetConnectionDownDescription": "Alle Knoten sind betroffen" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/de/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Updates für NiceNode verfügbar", 3 | "DownloadingUpdate": "NiceNode Update wird heruntergeladen...", 4 | "UpdateNiceNode": "Möchten Sie NiceNode jetzt aktualisieren? NiceNode wird nach dem Herunterladen des Updates neu gestartet. Aktualisieren auf Version.", 5 | "Yes": "Ja", 6 | "No": "Nein", 7 | "NoUpdateAvailable": "Kein Update verfügbar", 8 | "ErrorUpdating": "Entschuldigung, beim Aktualisieren von NiceNode ist ein Fehler aufgetreten", 9 | "UnableToInstallUpdate": "Kann die neue Version von NiceNode nicht installieren. Sie können versuchen, die neue Version manuell unter {{downloadLink}} herunterzuladen" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/en/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Select folder for {{storageForName}} storage", 3 | "SelectNodeFolder": "Select a folder for storing node data" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/en/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "ClientSuccessfulyUpdatedTitle": "Client successfully updated", 3 | "ClientSuccessfulyUpdatedDescription": "{{variable}} has been updated", 4 | "ClientUpdateErrorTitle": "Client update error", 5 | "ClientUpdateErrorDescription": "An error occurred while updating {{variable}}", 6 | "LowDiskSpaceTitle": "Low disk space", 7 | "LowDiskSpaceDescription": "Disk space is lower than 40GB", 8 | "InternetConnectionDownTitle": "Internet connection down", 9 | "InternetConnectionDownDescription": "All nodes affected", 10 | "ClosedPortsTitle": "Closed ports", 11 | "ClosedPortsDescription": "Ports {{variable}} may not be open on your local network", 12 | "UnexpectedPortsOpenTitle": "Unexpected ports open", 13 | "UnexpectedPortsOpenDescription": "Ports {{variable}} are open and should be closed on your local network" 14 | } 15 | -------------------------------------------------------------------------------- /assets/locales/en/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Updates for NiceNode available", 3 | "DownloadingUpdate": "Downloading NiceNode update...", 4 | "UpdateNiceNode": "Do you want to update NiceNode now? NiceNode will restart after downloading the update. Update to version", 5 | "Yes": "Yes", 6 | "No": "No", 7 | "NoUpdateAvailable": "No update available", 8 | "ErrorUpdating": "Sorry, there was an error updating NiceNode", 9 | "UnableToInstallUpdate": "Unable to install the new version of NiceNode. You can try downloading the new version manually at {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/es/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Seleccionar carpeta para almacenamiento de {{storageForName}}", 3 | "SelectNodeFolder": "Seleccionar una carpeta para almacenar los datos del nodo" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/es/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Espacio en disco bajo", 3 | "LowDiskSpaceDescription": "El espacio en disco es inferior a 40GB", 4 | "InternetConnectionDownTitle": "Conexión a Internet caida", 5 | "InternetConnectionDownDescription": "Todos los nodos afectados" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/es/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Actualizaciones disponibles para NiceNode", 3 | "DownloadingUpdate": "Descargando la actualización de NiceNode...", 4 | "UpdateNiceNode": "¿Desea actualizar NiceNode ahora? NiceNode se reiniciará después de descargar la actualización. Actualizar a la versión", 5 | "Yes": "Sí", 6 | "No": "No", 7 | "NoUpdateAvailable": "No hay actualizaciones disponibles", 8 | "ErrorUpdating": "Lo siento, se produjo un error al actualizar NiceNode", 9 | "UnableToInstallUpdate": "No se puede instalar la nueva versión de NiceNode. Puede intentar descargar la nueva versión manualmente en {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/fr/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Sélectionner un dossier pour le stockage {{storageForName}}", 3 | "SelectNodeFolder": "Sélectionner un dossier pour stocker les données du nœud" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/fr/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Espace disque faible", 3 | "LowDiskSpaceDescription": "L'espace disque est inférieur à 40 Go", 4 | "InternetConnectionDownTitle": "Connexion Internet interrompue", 5 | "InternetConnectionDownDescription": "Tous les nœuds sont affectés" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/fr/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Mises à jour disponibles pour NiceNode", 3 | "DownloadingUpdate": "Téléchargement de la mise à jour de NiceNode...", 4 | "UpdateNiceNode": "Voulez-vous mettre à jour NiceNode maintenant ? NiceNode redémarrera après le téléchargement de la mise à jour. Mettre à jour vers la version", 5 | "Yes": "Oui", 6 | "No": "Non", 7 | "NoUpdateAvailable": "Aucune mise à jour disponible", 8 | "ErrorUpdating": "Désolé, une erreur s'est produite lors de la mise à jour de NiceNode", 9 | "UnableToInstallUpdate": "Impossible d'installer la nouvelle version de NiceNode. Vous pouvez essayer de télécharger la nouvelle version manuellement à {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/ja/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "{{storageForName}}ストレージ用のフォルダーを選択", 3 | "SelectNodeFolder": "ノードデータを保存するためのフォルダを選択" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/ja/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "ディスクの空き容量が少ない", 3 | "LowDiskSpaceDescription": "ディスクの空き容量が40GB未満です", 4 | "InternetConnectionDownTitle": "インターネット接続が切断されました", 5 | "InternetConnectionDownDescription": "すべてのノードに影響があります" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/ja/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "NiceNodeのアップデートが利用可能です", 3 | "DownloadingUpdate": "NiceNodeのアップデートをダウンロード中...", 4 | "UpdateNiceNode": "NiceNodeを今すぐアップデートしますか?アップデートのダウンロード後にNiceNodeが再起動します。バージョンにアップデート", 5 | "Yes": "はい", 6 | "No": "いいえ", 7 | "NoUpdateAvailable": "アップデートはありません", 8 | "ErrorUpdating": "申し訳ありませんが、NiceNodeのアップデート中にエラーが発生しました", 9 | "UnableToInstallUpdate": "NiceNodeの新しいバージョンをインストールできません。{{downloadLink}}で新しいバージョンを手動でダウンロードしてみてください。" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/ja/windowMenu.json: -------------------------------------------------------------------------------- 1 | { 2 | "CheckForUpdates": "アップデートを確認...", 3 | "AboutNiceNode": "NiceNodeについて", 4 | "HideNiceNode": "NiceNodeを隠す", 5 | "Quit": "終了", 6 | "Edit": "編集", 7 | "Undo": "元に戻す", 8 | "Cut": "切り取り", 9 | "Copy": "コピー", 10 | "Paste": "貼り付け", 11 | "Select All": "すべて選択", 12 | "View": "表示", 13 | "Reload": "再読み込み", 14 | "ToggleFullScreen": "フルスクリーン切り替え", 15 | "ToggleDeveloperTools": "開発者ツール切り替え", 16 | "Window": "ウィンドウ", 17 | "Minimize": "最小化", 18 | "Close": "閉じる", 19 | "Bring All to Front": "全て前面へ", 20 | "Help": "ヘルプ", 21 | "NiceNodeWebsite": "NiceNode ウェブサイト", 22 | "ReportAProblem": "問題を報告", 23 | "RemoveAllNodesAndData": "全ノードとデータを削除", 24 | "UninstallPodman": "Podmanをアンインストール", 25 | "NuclearUninstall": "核アンインストール (Podmanをアンインストールし、全ノードとデータを削除)", 26 | "LogMinimumSystemRequirementCheck": "最小システム要件チェックを記録", 27 | "ShowSplashScreenAgain": "スプラッシュスクリーンを再表示", 28 | "CopyConfigurationDetailsToClipboard": "設定詳細をクリップボードにコピー", 29 | "Show Alpha Modal": "アルファモーダルを表示", 30 | "Check Ports": "ポートをチェック" 31 | } 32 | -------------------------------------------------------------------------------- /assets/locales/ru/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Выберите папку для хранения {{storageForName}}", 3 | "SelectNodeFolder": "Выберите папку для хранения данных узла" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/ru/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Низкое место на диске", 3 | "LowDiskSpaceDescription": "Дисковое пространство меньше 40ГБ", 4 | "InternetConnectionDownTitle": "Подключение к интернету отключено", 5 | "InternetConnectionDownDescription": "Все узлы затронуты" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/ru/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Доступны обновления для NiceNode", 3 | "DownloadingUpdate": "Загрузка обновления NiceNode...", 4 | "UpdateNiceNode": "Вы хотите обновить NiceNode сейчас? NiceNode перезапустится после загрузки обновления. Обновить до версии", 5 | "Yes": "Да", 6 | "No": "Нет", 7 | "NoUpdateAvailable": "Обновление не доступно", 8 | "ErrorUpdating": "Извините, произошла ошибка при обновлении NiceNode", 9 | "UnableToInstallUpdate": "Не удаётся установить новую версию NiceNode. Вы можете попробовать скачать новую версию вручную по адресу {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/vi/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "Chọn thư mục cho bộ nhớ {{storageForName}}", 3 | "SelectNodeFolder": "Chọn một thư mục để lưu trữ dữ liệu của nút" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/vi/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "Dung lượng đĩa thấp", 3 | "LowDiskSpaceDescription": "Dung lượng đĩa thấp hơn 40GB", 4 | "InternetConnectionDownTitle": "Mất kết nối Internet", 5 | "InternetConnectionDownDescription": "Tất cả các nút đều bị ảnh hưởng" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/vi/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "Có cập nhật cho NiceNode", 3 | "DownloadingUpdate": "Đang tải về cập nhật cho NiceNode...", 4 | "UpdateNiceNode": "Bạn có muốn cập nhật NiceNode ngay bây giờ không? NiceNode sẽ khởi động lại sau khi tải xong cập nhật. Cập nhật lên phiên bản", 5 | "Yes": "Có", 6 | "No": "Không", 7 | "NoUpdateAvailable": "Không có cập nhật", 8 | "ErrorUpdating": "Xin lỗi, đã xảy ra lỗi khi cập nhật NiceNode", 9 | "UnableToInstallUpdate": "Không thể cài đặt phiên bản mới của NiceNode. Bạn có thể thử tải xuống phiên bản mới thủ công tại {{downloadLink}}" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/zh/dialog.json: -------------------------------------------------------------------------------- 1 | { 2 | "SelectFolderForStorage": "选择{{storageForName}}存储的文件夹", 3 | "SelectNodeFolder": "选择一个用于存储节点数据的文件夹" 4 | } 5 | -------------------------------------------------------------------------------- /assets/locales/zh/notifications.json: -------------------------------------------------------------------------------- 1 | { 2 | "LowDiskSpaceTitle": "磁盘空间不足", 3 | "LowDiskSpaceDescription": "磁盘空间低于40GB", 4 | "InternetConnectionDownTitle": "网络连接中断", 5 | "InternetConnectionDownDescription": "所有节点受影响" 6 | } 7 | -------------------------------------------------------------------------------- /assets/locales/zh/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpdateAvailable": "NiceNode 有更新", 3 | "DownloadingUpdate": "正在下载 NiceNode 更新...", 4 | "UpdateNiceNode": "您现在要更新 NiceNode 吗?NiceNode 将在下载更新后重新启动。更新到版本", 5 | "Yes": "是", 6 | "No": "否", 7 | "NoUpdateAvailable": "没有可用更新", 8 | "ErrorUpdating": "抱歉,更新 NiceNode 时出现错误", 9 | "UnableToInstallUpdate": "无法安装NiceNode的新版本。您可以尝试在{{downloadLink}}手动下载新版本。" 10 | } 11 | -------------------------------------------------------------------------------- /assets/locales/zh/windowMenu.json: -------------------------------------------------------------------------------- 1 | { 2 | "CheckForUpdates": "检查更新...", 3 | "AboutNiceNode": "关于NiceNode", 4 | "HideNiceNode": "隐藏NiceNode", 5 | "Quit": "退出", 6 | "Edit": "编辑", 7 | "Undo": "撤销", 8 | "Cut": "剪切", 9 | "Copy": "复制", 10 | "Paste": "粘贴", 11 | "Select All": "全选", 12 | "View": "查看", 13 | "Reload": "重新加载", 14 | "ToggleFullScreen": "切换全屏", 15 | "ToggleDeveloperTools": "切换开发者工具", 16 | "Window": "窗口", 17 | "Minimize": "最小化", 18 | "Close": "关闭", 19 | "Bring All to Front": "全部带到前面", 20 | "Help": "帮助", 21 | "NiceNodeWebsite": "NiceNode 网站", 22 | "ReportAProblem": "报告问题", 23 | "RemoveAllNodesAndData": "删除所有节点和数据", 24 | "UninstallPodman": "卸载 Podman", 25 | "NuclearUninstall": "核卸载(卸载 Podman 并删除所有节点和数据)", 26 | "LogMinimumSystemRequirementCheck": "记录系统最低要求检查", 27 | "ShowSplashScreenAgain": "再次显示启动屏幕", 28 | "CopyConfigurationDetailsToClipboard": "复制配置详细信息到剪贴板", 29 | "Show Alpha Modal": "显示 Alpha 模态窗口", 30 | "Check Ports": "检查端口" 31 | } 32 | -------------------------------------------------------------------------------- /biome.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.6.4/schema.json", 3 | "organizeImports": { 4 | "enabled": true 5 | }, 6 | "linter": { 7 | "enabled": true, 8 | "rules": { 9 | "recommended": true, 10 | "suspicious": { 11 | "noImplicitAnyLet": "off", 12 | "noExplicitAny": "off" 13 | }, 14 | "complexity": { 15 | "noForEach": "off" 16 | }, 17 | "correctness": { 18 | "useExhaustiveDependencies": "off" 19 | } 20 | } 21 | }, 22 | "formatter": { 23 | "indentStyle": "space" 24 | }, 25 | "javascript": { 26 | "formatter": { 27 | "quoteStyle": "single" 28 | } 29 | }, 30 | "files": { 31 | "ignore": [ 32 | "src/renderer/ethers.js", 33 | "src/main/util/*.js", 34 | "*genesis-l2.json" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /assets/locales/en/*.json 3 | translation: /assets/locales/%two_letters_code%/%original_file_name% 4 | commit_message: '[ci skip]' 5 | pull_request_labels: 6 | - crowdin 7 | - l10n 8 | -------------------------------------------------------------------------------- /dev-app-update.yml: -------------------------------------------------------------------------------- 1 | provider: github 2 | owner: jgresham 3 | repo: nice-node 4 | -------------------------------------------------------------------------------- /forge.env.d.ts: -------------------------------------------------------------------------------- 1 | export type {}; // Make this a module 2 | 3 | declare global { 4 | // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Vite 5 | // plugin that tells the Electron app where to look for the Vite-bundled app code (depending on 6 | // whether you're running in development or production). 7 | const MAIN_WINDOW_VITE_DEV_SERVER_URL: string; 8 | const MAIN_WINDOW_VITE_NAME: string; 9 | 10 | namespace NodeJS { 11 | interface Process { 12 | // Used for hot reload after preload scripts. 13 | viteDevServers: Record; 14 | } 15 | } 16 | 17 | type VitePluginConfig = ConstructorParameters[0]; 18 | 19 | interface VitePluginRuntimeKeys { 20 | VITE_DEV_SERVER_URL: `${string}_VITE_DEV_SERVER_URL`; 21 | VITE_NAME: `${string}_VITE_NAME`; 22 | } 23 | } 24 | 25 | declare module 'vite' { 26 | interface ConfigEnv { 27 | root: string; 28 | forgeConfig: VitePluginConfig; 29 | forgeConfigSelf: VitePluginConfig[K][number]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /funding.json: -------------------------------------------------------------------------------- 1 | { 2 | "drips": { 3 | "ethereum": { 4 | "ownedBy": "0x9cce47E9cF12C6147c9844adBB81fE85880c4df4" 5 | } 6 | }, 7 | "opRetro": { 8 | "projectId": "0xf603b0a365deb7d7130d5c6ebd2ca4f8b7661aae8dcbee822d0ff4187dbcfc76" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'await-sleep'; 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | NiceNode 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/__tests__/node/neverEndingProcess.js: -------------------------------------------------------------------------------- 1 | setInterval(() => { 2 | console.log('Test process!'); 3 | }, 500); 4 | -------------------------------------------------------------------------------- /src/common/NodeSpecs/README.md: -------------------------------------------------------------------------------- 1 | # NodeSpecs 2 | 3 | ## Modify an existing node 4 | 5 | Want to add a setting to an existing node? Find the node spec and add a config control translation! 6 | 7 | ## Add a new node 8 | 9 | Want to add a new node? Create a new folder with a spec file. Use one of the existing nodes as an example! 10 | 11 | ## Questions 12 | 13 | Join the [discord](https://discord.gg/k3dpYU4Pn9) and get help with creating or modifying a node spec 14 | -------------------------------------------------------------------------------- /src/common/NodeSpecs/base/files/rollup.json: -------------------------------------------------------------------------------- 1 | { 2 | "genesis": { 3 | "l1": { 4 | "hash": "0x5c13d307623a926cd31415036c8b7fa14572f9dac64528e857a470511fc30771", 5 | "number": 17481768 6 | }, 7 | "l2": { 8 | "hash": "0xf712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd", 9 | "number": 0 10 | }, 11 | "l2_time": 1686789347, 12 | "system_config": { 13 | "batcherAddr": "0x5050f69a9786f081509234f1a7f4684b5e5b76c9", 14 | "overhead": "0x00000000000000000000000000000000000000000000000000000000000000bc", 15 | "scalar": "0x00000000000000000000000000000000000000000000000000000000000a6fe0", 16 | "gasLimit": 30000000 17 | } 18 | }, 19 | "block_time": 2, 20 | "max_sequencer_drift": 600, 21 | "seq_window_size": 3600, 22 | "channel_timeout": 300, 23 | "l1_chain_id": 1, 24 | "l2_chain_id": 8453, 25 | "regolith_time": 0, 26 | "batch_inbox_address": "0xff00000000000000000000000000000000008453", 27 | "deposit_contract_address": "0x49048044d57e1c92a77f79988d21fa8faf74e97e", 28 | "l1_system_config_address": "0x73a79fab69143498ed3712e519a88a918e1f4072" 29 | } 30 | -------------------------------------------------------------------------------- /src/common/NodeSpecs/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/common/NodeSpecs/index.md -------------------------------------------------------------------------------- /src/common/NodeSpecs/nimbus/notes.md: -------------------------------------------------------------------------------- 1 | No checkpoint sync flag used for nimbus. Issue filed https://github.com/status-im/nimbus-eth2/issues/5511 2 | -------------------------------------------------------------------------------- /src/common/NodeSpecs/reth/notes.md: -------------------------------------------------------------------------------- 1 | `--color never` is set to avoid reth from using non-readble characters in the logs 2 | -------------------------------------------------------------------------------- /src/common/nodePackageConfig.ts: -------------------------------------------------------------------------------- 1 | import type { ConfigKey, ConfigValuesMap } from './nodeConfig'; 2 | 3 | /** 4 | * "serviceConfigs": { 5 | "services": [ 6 | { 7 | "serviceId": "executionClient", 8 | "configValues": { 9 | "network": "Mainnet", 10 | "genesisFile": "" 11 | } 12 | }, 13 | { 14 | "serviceId": "consensusClient", 15 | "configValues": { 16 | "network": "Mainnet" 17 | } 18 | } 19 | ] 20 | } 21 | */ 22 | export type ServiceConfigs = { 23 | services: { 24 | serviceId: string; 25 | configKey?: ConfigKey; // used for text type controls 26 | configValues?: ConfigValuesMap; // used for select controls 27 | }[]; 28 | // clientExceptionConfigValues?: { 29 | // cliendId: string; 30 | // configValues: ConfigValuesMap; 31 | // }[]; 32 | }; 33 | -------------------------------------------------------------------------------- /src/common/systemRequirements.ts: -------------------------------------------------------------------------------- 1 | export type CpuRequirements = { 2 | cores?: number; 3 | minSpeedGHz?: number; 4 | }; 5 | export type MemoryRequirements = { 6 | minSizeGBs?: number; 7 | minSpeedGHz?: number; 8 | }; 9 | export type StorageRequirements = { 10 | minSizeGBs?: number; 11 | minWriteSpeedMBps?: number; 12 | ssdRequired?: boolean; 13 | // NVMe? 14 | }; 15 | export type InternetRequirements = { 16 | minDownloadSpeedMbps?: number; 17 | minUploadSpeedMbps?: number; 18 | noDataCapRecommended?: boolean; 19 | // and {{minUploadSpeed}} up 20 | // etherenetRequired?: boolean; 21 | // latency? 22 | }; 23 | export type DockerRequirements = { 24 | required?: boolean; 25 | minVersion?: string; 26 | }; 27 | 28 | export type SystemRequirements = { 29 | documentationUrl?: string; 30 | description?: string; 31 | cpu?: CpuRequirements; 32 | memory?: MemoryRequirements; 33 | storage?: StorageRequirements; 34 | internet?: InternetRequirements; 35 | docker?: DockerRequirements; 36 | }; 37 | -------------------------------------------------------------------------------- /src/main/docker/docker-compose.ts: -------------------------------------------------------------------------------- 1 | import { execAwait } from '../execHelper'; 2 | import logger from '../logger'; 3 | 4 | const VERSION_COMMAND = 'docker-compose --version'; 5 | 6 | export const getVersion = async () => { 7 | const { stdout, stderr } = await execAwait(VERSION_COMMAND, { 8 | log: true, 9 | }); 10 | return `${stdout + stderr}`; 11 | }; 12 | 13 | /** 14 | * Only logs the docker compose version, if available 15 | */ 16 | export const initialize = async () => { 17 | // run "docker-compose --version" 18 | try { 19 | logger.info(`${VERSION_COMMAND} result: ${await getVersion()}`); 20 | } catch (err) { 21 | logger.error(err); 22 | logger.info('Unable to get the docker compose version.'); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/main/docker/install.ts: -------------------------------------------------------------------------------- 1 | import logger from '../logger'; 2 | import * as platform from '../platform'; 3 | import installOnMac from './installOnMac'; 4 | import installOnWindows from './installOnWindows'; 5 | 6 | const installDocker = async (): Promise => { 7 | logger.info('Starting docker install...'); 8 | 9 | let result; 10 | if (platform.isMac()) { 11 | result = await installOnMac(); 12 | } else if (platform.isWindows()) { 13 | result = await installOnWindows(); 14 | } else { 15 | result = { error: 'Unable to install Docker on this operating system.' }; 16 | } 17 | logger.info(`Finished docker install. Result: ${result}`); 18 | return result; 19 | }; 20 | 21 | export default installDocker; 22 | -------------------------------------------------------------------------------- /src/main/docker/messageFrontEnd.ts: -------------------------------------------------------------------------------- 1 | import type { FileDownloadProgress } from '../downloadFile'; 2 | import { CHANNELS, send } from '../messenger'; 3 | 4 | export const sendMessageOnDownloadProgress = ( 5 | downloadProgress: FileDownloadProgress, 6 | ) => { 7 | send(CHANNELS.podman, downloadProgress); 8 | }; 9 | 10 | export const sendMessageOnThemeChange = () => { 11 | send(CHANNELS.theme, 'themeChange'); 12 | }; 13 | -------------------------------------------------------------------------------- /src/main/events.ts: -------------------------------------------------------------------------------- 1 | import type { ReportEventData } from '../renderer/events/reportEvent'; 2 | import { CHANNELS, send } from './messenger'; 3 | 4 | export const reportEvent = (event: string, eventData?: ReportEventData) => { 5 | // console.log('reportEvent: ', event, eventData); 6 | send(CHANNELS.reportEvent, event, eventData); 7 | }; 8 | -------------------------------------------------------------------------------- /src/main/messenger.ts: -------------------------------------------------------------------------------- 1 | import type { BrowserWindow } from 'electron'; 2 | 3 | // import logger from './logger'; 4 | 5 | let mainWindow: BrowserWindow; 6 | 7 | export const setWindow = (inMainWindow: BrowserWindow): void => { 8 | mainWindow = inMainWindow; 9 | }; 10 | 11 | export const send = (channel: string, ...args: any[]): void => { 12 | if (!mainWindow) { 13 | return; 14 | } 15 | // console.log('sending', channel, args); 16 | mainWindow.webContents.send(channel, args); 17 | }; 18 | 19 | export const CHANNELS = { 20 | userNodes: 'userNodes', 21 | userNodePackages: 'userNodePackages', 22 | nodeLogs: 'nodeLogs', 23 | podman: 'podman', 24 | podmanInstall: 'podmanInstall', 25 | openPodmanModal: 'openPodmanModal', 26 | openNodePackageScreen: 'openNodePackageScreen', 27 | theme: 'theme', 28 | notifications: 'notifications', 29 | reportEvent: 'reportEvent', 30 | }; 31 | export const CHANNELS_ARRAY = Object.keys(CHANNELS); 32 | -------------------------------------------------------------------------------- /src/main/nuclearUninstall.ts: -------------------------------------------------------------------------------- 1 | import { removeAllNodePackages } from './nodePackageManager'; 2 | import uninstallPodman from './podman/uninstall/uninstall'; 3 | 4 | /** 5 | * Uninstalls and deletes dependencies, removes all nodes and delets their data. 6 | * The only thing it keeps are NiceNode app settings. 7 | * Technicals: 8 | * podman machine rm nicenode-machine 9 | * remove files at podman path 10 | * remove all nodes 11 | * delete nodes directory 12 | * todo: (linux) remove source from package thingy? 13 | * todo: (windows) unregister fedora wsl2 distro? 14 | */ 15 | const nuclearUninstall = async () => { 16 | // remove all node packages (removes each package's nodes/clients/services too) 17 | await removeAllNodePackages(); 18 | // todo: delete nodes dir or other NN data (preferences?) 19 | await uninstallPodman(); 20 | }; 21 | 22 | export default nuclearUninstall; 23 | -------------------------------------------------------------------------------- /src/main/platform.ts: -------------------------------------------------------------------------------- 1 | import { platform } from 'node:process'; 2 | 3 | export const isMac = () => { 4 | return platform === 'darwin'; 5 | }; 6 | 7 | export const isLinux = () => { 8 | return platform === 'linux'; 9 | }; 10 | 11 | export const isWindows = () => { 12 | return platform === 'win32'; 13 | }; 14 | 15 | export const getPlatform = () => { 16 | return platform; 17 | }; 18 | 19 | export const doesStringIncludePlatform = (inputStr: string) => { 20 | const str = inputStr.toLowerCase(); 21 | if (isWindows()) { 22 | return ( 23 | str.toLowerCase().includes('win32') || 24 | str.toLowerCase().includes('windows') 25 | ); 26 | } 27 | if (isLinux()) { 28 | return str.toLowerCase().includes('linux'); 29 | } 30 | if (isMac()) { 31 | return ( 32 | str.toLowerCase().includes('darwin') || str.toLowerCase().includes('mac') 33 | ); 34 | } 35 | return false; 36 | }; 37 | -------------------------------------------------------------------------------- /src/main/podman/install/aptInstallScript.ts: -------------------------------------------------------------------------------- 1 | // Reference https://podman.io/docs/installation 2 | // first line is to remove a depracted apt source that will conflict with the official one 3 | export const script = ` 4 | rm -rf /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list 5 | apt -y update -qq 6 | apt install -y podman 7 | `; 8 | -------------------------------------------------------------------------------- /src/main/podman/install/dnfInstallScript.ts: -------------------------------------------------------------------------------- 1 | // Same script as on https://podman.io/docs/installation, except the 'sudo' is removed as 2 | // sudo-prompt will not execute a command with sudo 3 | export const script = 'dnf -y update && dnf -y install podman'; 4 | -------------------------------------------------------------------------------- /src/main/podman/install/pacmanInstallScript.ts: -------------------------------------------------------------------------------- 1 | // Same script as on https://podman.io/docs/installation, except the 'sudo' is removed as 2 | // sudo-prompt will not execute a command with sudo 3 | export const script = 'pacman -Syu --noconfirm && pacman -S podman --noconfirm'; 4 | -------------------------------------------------------------------------------- /src/main/podman/install/yumInstallScript.ts: -------------------------------------------------------------------------------- 1 | // Same script as on https://podman.io/docs/installation, except the 'sudo' is removed as 2 | // sudo-prompt will not execute a command with sudo 3 | export const script = 'dnf -y update && dnf -y install podman'; 4 | -------------------------------------------------------------------------------- /src/main/podman/install/zypperInstallScript.ts: -------------------------------------------------------------------------------- 1 | // Reference https://podman.io/docs/installation 2 | // biome-ignore lint/style/noUnusedTemplateLiteral: less diff for future changes 3 | export const script = `zypper install -y podman`; 4 | -------------------------------------------------------------------------------- /src/main/podman/messageFrontEnd.ts: -------------------------------------------------------------------------------- 1 | import type { FileDownloadProgress } from '../downloadFile'; 2 | import { CHANNELS, send } from '../messenger'; 3 | 4 | export interface IpcMessage { 5 | messageId: string; 6 | value: unknown; 7 | } 8 | 9 | export class MessageGrantPermissionToInstallPodman { 10 | messageId = 'isGrantedPermission'; 11 | value = false; 12 | } 13 | 14 | export const sendMessageOnDownloadProgress = ( 15 | downloadProgress: FileDownloadProgress, 16 | ) => { 17 | send(CHANNELS.podman, downloadProgress); 18 | }; 19 | 20 | export const sendMessageOnGrantPermissionToInstallPodman = ( 21 | isGrantedPermission: boolean, 22 | ) => { 23 | const message: MessageGrantPermissionToInstallPodman = 24 | new MessageGrantPermissionToInstallPodman(); 25 | message.messageId = 'isGrantedPermission'; 26 | message.value = isGrantedPermission; 27 | send(CHANNELS.podmanInstall, message); 28 | }; 29 | 30 | export const sendMessageOnThemeChange = () => { 31 | send(CHANNELS.theme, 'themeChange'); 32 | }; 33 | -------------------------------------------------------------------------------- /src/main/podman/podman-env-path.ts: -------------------------------------------------------------------------------- 1 | import { getInstallationPath } from './podman-desktop/podman-cli'; 2 | 3 | /** 4 | * In production(packaged) mode, applications don't have access to the 'user' 5 | * path like brew 6 | * @returns process.env with env.PATH set to installed podman location 7 | */ 8 | export const getPodmanEnvWithPath = () => { 9 | return { ...process.env, PATH: getInstallationPath() }; 10 | }; 11 | -------------------------------------------------------------------------------- /src/main/podman/types.ts: -------------------------------------------------------------------------------- 1 | export type MachineJSON = { 2 | Name: string; 3 | Default: boolean; 4 | Created: string; 5 | Running: boolean; 6 | Starting: boolean; 7 | LastUp: string; 8 | Stream: string; 9 | VMType: string; 10 | CPUs: number; 11 | Memory: string; 12 | DiskSize: string; 13 | Port: number; 14 | RemoteUsername: string; 15 | IdentityPath: string; 16 | UserModeNetworking: boolean; 17 | }; 18 | 19 | /** 20 | * Follows format and types from Podman's API 21 | * https://docs.podman.io/en/latest/_static/api.html?version=v4.4#tag/containers/operation/ContainersStatsAllLibpod 22 | * 23 | * This is starting as a subset of all the values because we are currently using 24 | * Podman CLI instead of their API. 25 | */ 26 | export type ContainerStats = { 27 | ContainerID: string; 28 | Name: string; 29 | // CPUTime: number; 30 | PercCPU: number; 31 | // MemUsage: string; 32 | MemPerc: number; 33 | // NetInput: number; 34 | // BlockInput: number; 35 | // BlockOutput: number; 36 | // PIDs: number; 37 | }; 38 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/aptUninstallScript.ts: -------------------------------------------------------------------------------- 1 | export const script = `rm -rf /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list 2 | apt remove -y podman`; 3 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/dnfUninstallScript.ts: -------------------------------------------------------------------------------- 1 | export const script = 'dnf remove -y podman'; 2 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/pacmanUninstallScript.ts: -------------------------------------------------------------------------------- 1 | export const script = 'pacman -Rs podman --noconfirm'; 2 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/uninstall.ts: -------------------------------------------------------------------------------- 1 | import logger from '../../logger'; 2 | import * as platform from '../../platform'; 3 | import { removeNiceNodeMachine } from '../machine'; 4 | import uninstallOnLinux from './uninstallOnLinux'; 5 | import uninstallOnMac from './uninstallOnMac'; 6 | import uninstallOnWindows from './uninstallOnWindows'; 7 | 8 | const uninstallPodman = async (): Promise => { 9 | logger.info('Starting podman uninstall...'); 10 | 11 | // force stop and remove nicenode-machine 12 | await removeNiceNodeMachine(); 13 | 14 | let result; 15 | if (platform.isMac()) { 16 | result = await uninstallOnMac(); 17 | } else if (platform.isWindows()) { 18 | result = await uninstallOnWindows(); 19 | } else if (platform.isLinux()) { 20 | result = await uninstallOnLinux(); 21 | } else { 22 | result = { error: 'Unable to uninstall Podman on this operating system.' }; 23 | } 24 | logger.info(`Finished podman uninstall. Result: ${result}`); 25 | return result; 26 | }; 27 | 28 | export default uninstallPodman; 29 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/yumUninstallScript.ts: -------------------------------------------------------------------------------- 1 | export const script = 'yum remove -y podman'; 2 | -------------------------------------------------------------------------------- /src/main/podman/uninstall/zypperUninstallScript.ts: -------------------------------------------------------------------------------- 1 | // biome-ignore lint/style/noUnusedTemplateLiteral: less diff for future changes 2 | export const script = `zypper remove -y podman`; 3 | -------------------------------------------------------------------------------- /src/main/state/benchmark.ts: -------------------------------------------------------------------------------- 1 | import { send } from '../messenger'; 2 | import store from './store'; 3 | 4 | export const BENCHMARKS_KEY = 'benchmarks'; 5 | 6 | export interface Benchmark { 7 | type: string; 8 | timestamp: number; 9 | results: any; 10 | } 11 | 12 | /** 13 | * Called on app launch. 14 | * Initializes internal data structures for readiness. 15 | */ 16 | const initialize = () => { 17 | const benchmarks = store.get(BENCHMARKS_KEY); 18 | if (!benchmarks) { 19 | store.set(BENCHMARKS_KEY, []); 20 | } 21 | 22 | // Notify the UI when values change 23 | store.onDidChange(BENCHMARKS_KEY, () => { 24 | send(BENCHMARKS_KEY); 25 | }); 26 | }; 27 | initialize(); 28 | 29 | export const getBenchmarks = () => { 30 | const benchmarks = store.get(BENCHMARKS_KEY) || []; 31 | return benchmarks; 32 | }; 33 | 34 | export const addBenchmark = (benchmark: Benchmark) => { 35 | const benchmarks = store.get(BENCHMARKS_KEY) || []; 36 | benchmarks.unshift(benchmark); 37 | store.set(BENCHMARKS_KEY, benchmarks); 38 | return benchmarks; 39 | }; 40 | -------------------------------------------------------------------------------- /src/main/state/store.ts: -------------------------------------------------------------------------------- 1 | import Store from 'electron-store'; 2 | 3 | const store = new Store(); 4 | 5 | export const setIsStartOnLogin = (isStartOnLogin: boolean): void => { 6 | store.set('isStartOnLogin', isStartOnLogin); 7 | }; 8 | 9 | export const getIsStartOnLogin = (): boolean => { 10 | return store.get('isStartOnLogin') as boolean; 11 | }; 12 | 13 | export const watchIsStartOnLogin = (handler: () => void): void => { 14 | store.onDidChange('isStartOnLogin', handler); 15 | }; 16 | 17 | export default store; 18 | -------------------------------------------------------------------------------- /src/main/util.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | import { URL } from 'node:url'; 3 | import url from 'node:url'; 4 | 5 | export const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); 6 | 7 | export function resolveHtmlPath(htmlFileName: string) { 8 | if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { 9 | const url = new URL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}/${htmlFileName}`); 10 | url.pathname = htmlFileName; 11 | return url.href; 12 | } 13 | return `file://${path.join( 14 | __dirname, 15 | `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html?${htmlFileName}`, 16 | )}`; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/util/delay.ts: -------------------------------------------------------------------------------- 1 | export const delay = async (ms: number) => { 2 | await new Promise((resolve) => setTimeout(resolve, ms)); 3 | }; 4 | -------------------------------------------------------------------------------- /src/main/util/fixPathEnvVar.js: -------------------------------------------------------------------------------- 1 | import process from 'node:process'; 2 | import { isMac } from '../platform'; 3 | 4 | export const fixPathEnvVar = () => { 5 | if (!isMac()) { 6 | return; 7 | } 8 | // fix path env variable so that child processes paths 9 | // code from https://github.com/sindresorhus/fix-path 10 | console.log('Env var PATH before change: ', process.env.PATH); 11 | process.env.PATH = [ 12 | './node_modules/.bin', 13 | // '/.nodebrew/current/bin', 14 | '/usr/local/bin', 15 | process.env.PATH, 16 | ].join(':'); 17 | console.log('Env var PATH after change: ', process.env.PATH); 18 | }; 19 | -------------------------------------------------------------------------------- /src/main/util/parseFileNameFromPath.ts: -------------------------------------------------------------------------------- 1 | import * as platform from '../platform'; 2 | 3 | export const parseFileNameFromPath = ( 4 | inPath: string, 5 | excludeExension?: boolean, 6 | ) => { 7 | // ex. 'C:\Windows\crazy\inPath' 8 | // ex. '/root/usr/yay.zip 9 | let pathSlash = '/'; 10 | if (platform.isWindows()) { 11 | pathSlash = '\\'; 12 | } 13 | if (excludeExension) { 14 | const tarGzIndex = inPath.lastIndexOf('.tar.gz'); 15 | const zipIndex = inPath.lastIndexOf('.zip'); 16 | const extensionIndex = tarGzIndex > 0 ? tarGzIndex : zipIndex; 17 | 18 | return inPath.substring(inPath.lastIndexOf(pathSlash) + 1, extensionIndex); 19 | } 20 | return inPath.substring(inPath.lastIndexOf(pathSlash) + 1); 21 | }; 22 | -------------------------------------------------------------------------------- /src/main/util/parseFileNameFromUrl.ts: -------------------------------------------------------------------------------- 1 | export const parseFileNameFromUrl = ( 2 | url: string, 3 | excludeExension?: boolean, 4 | ) => { 5 | // ex. 'https://gethstore.blob.core.windows.net/builds/geth-darwin-amd64-1.10.17-25c9b49f.tar.gz' 6 | let urlEncodedFilename; 7 | if (excludeExension) { 8 | const tarGzIndex = url.lastIndexOf('.tar.gz'); 9 | const zipIndex = url.lastIndexOf('.zip'); 10 | const extensionIndex = tarGzIndex > 0 ? tarGzIndex : zipIndex; 11 | urlEncodedFilename = url.substring( 12 | url.lastIndexOf('/') + 1, 13 | extensionIndex, 14 | ); 15 | } else { 16 | urlEncodedFilename = url.substring(url.lastIndexOf('/') + 1); 17 | } 18 | const filename = urlEncodedFilename.replaceAll('%20', ''); 19 | return filename; 20 | }; 21 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Banner/banner.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | padding: '8px 0px', 6 | width: '100%', 7 | }); 8 | 9 | export const innerContainer = style({ 10 | display: 'flex', 11 | flexDirection: 'row', 12 | alignItems: 'flex-start', 13 | gap: '12px', 14 | minHeight: 56, 15 | boxSizing: 'border-box', 16 | background: vars.components.bannerBackground, 17 | boxShadow: vars.components.bannerBoxShadow, 18 | borderRadius: '5px', 19 | color: vars.color.font70, 20 | padding: '12px', 21 | selectors: { 22 | '&.loading': { 23 | color: vars.color.font50, 24 | }, 25 | }, 26 | }); 27 | 28 | export const textContainer = style({}); 29 | 30 | export const titleStyle = style({ 31 | fontStyle: 'normal', 32 | fontWeight: '590', 33 | fontSize: '13px', 34 | lineHeight: '16px', 35 | letterSpacing: '-0.12px', 36 | marginBottom: '2px', 37 | }); 38 | 39 | export const descriptionStyle = style({ 40 | fontWeight: '400', 41 | fontSize: '11px', 42 | lineHeight: '14px', 43 | }); 44 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Bubble/Bubble.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './bubble.css'; 2 | 3 | export interface BubbleProps { 4 | /** 5 | * What background color to use 6 | */ 7 | backgroundColor?: string; 8 | /** 9 | * Button contents 10 | */ 11 | count: number; 12 | } 13 | 14 | /** 15 | * Primary UI component for user interaction 16 | */ 17 | export const Bubble = ({ backgroundColor, count, ...props }: BubbleProps) => { 18 | return ( 19 |
20 | {count} 21 |
22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Bubble/bubble.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { common } from '../theme.css'; 3 | 4 | export const container = style({ 5 | flex: 'none', 6 | display: 'flex', 7 | flexDirection: 'row', 8 | alignItems: 'flex-start', 9 | padding: '2px 6px', 10 | gap: '10px', 11 | fontStyle: 'normal', 12 | fontWeight: '590', 13 | fontSize: '11px', 14 | lineHeight: '14px', 15 | textAlign: 'center', 16 | color: common.color.white100, 17 | maxWidth: 'fit-content', 18 | background: common.color.red500, 19 | borderRadius: '9px', 20 | }); 21 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Chart/chart.css.ts: -------------------------------------------------------------------------------- 1 | import { keyframes, style } from '@vanilla-extract/css'; 2 | 3 | const rotate = keyframes({ 4 | '0%': { transform: 'rotate(0deg)' }, 5 | '100%': { transform: 'rotate(359deg)' }, 6 | }); 7 | 8 | export const container = style({ 9 | width: '100%', 10 | height: 196, 11 | selectors: { 12 | '&.spaceBetween': { 13 | justifyContent: 'space-between', 14 | }, 15 | }, 16 | }); 17 | 18 | export const iconContainer = style({ 19 | display: 'flex', 20 | justifyContent: 'center', 21 | alignItems: 'center', 22 | height: '100%', 23 | }); 24 | 25 | export const iconComponent = style({ 26 | animationDuration: '2s', 27 | animationIterationCount: 'infinite', 28 | animationTimingFunction: 'linear', 29 | animationName: rotate, 30 | width: 20, 31 | height: 20, 32 | }); 33 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Checklist/checklist.css.ts: -------------------------------------------------------------------------------- 1 | import { keyframes, style } from '@vanilla-extract/css'; 2 | 3 | const rotate = keyframes({ 4 | '0%': { transform: 'rotate(0deg)' }, 5 | '100%': { transform: 'rotate(359deg)' }, 6 | }); 7 | 8 | export const container = style({ 9 | display: 'flex', 10 | flexDirection: 'column', 11 | alignItems: 'flex-start', 12 | gap: 16, 13 | paddingBottom: 15, 14 | }); 15 | 16 | export const iconContainer = style({ 17 | display: 'flex', 18 | justifyContent: 'center', 19 | alignItems: 'center', 20 | height: '100%', 21 | }); 22 | 23 | export const iconComponent = style({ 24 | animationDuration: '2s', 25 | animationIterationCount: 'infinite', 26 | animationTimingFunction: 'linear', 27 | animationName: rotate, 28 | width: 20, 29 | height: 20, 30 | }); 31 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/ContentWithSideArt/contentWithSideArt.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const container = style({ 4 | display: 'flex', 5 | flexDirection: 'row', 6 | width: '100%', 7 | height: '100%', 8 | }); 9 | 10 | export const graphicsContainer = style({ 11 | minWidth: 380, // min-width works with flexGrow: 1 on the content 12 | backgroundSize: 'cover', 13 | '@media': { 14 | 'screen and (max-width: 980px)': { 15 | display: 'none', 16 | }, 17 | }, 18 | }); 19 | 20 | export const contentContainer = style({ 21 | flexGrow: 1, 22 | overflow: 'auto', 23 | padding: '80px 64px', 24 | selectors: { 25 | '&.modal': { 26 | padding: 0, 27 | overflow: 'visible', 28 | }, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/CopyButton/copyButton.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { common, vars } from '../theme.css'; 3 | 4 | export const copyIcon = style({ 5 | color: vars.color.font40, 6 | cursor: 'pointer', 7 | selectors: { 8 | '&:hover': { 9 | color: common.color.purple600, 10 | }, 11 | }, 12 | }); 13 | 14 | export const checkIcon = style({ 15 | color: 'green', 16 | }); 17 | 18 | export const copyMessage = style({ 19 | position: 'absolute', 20 | top: '-3em', 21 | left: '-3em', 22 | color: vars.color.font70, 23 | backgroundColor: vars.color.background, 24 | padding: '0.5em', 25 | borderRadius: '4px', 26 | display: 'none', 27 | boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)', 28 | }); 29 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/FloatingButton/floatingButton.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const baseButton = style({ 5 | cursor: 'pointer', 6 | userSelect: 'none', 7 | boxSizing: 'border-box', 8 | display: 'flex', 9 | flexDirection: 'row', 10 | justifyContent: 'center', 11 | alignItems: 'center', 12 | padding: '8px 12px', 13 | gap: 6, 14 | border: '1px solid', 15 | zIndex: 3, 16 | bottom: 16, 17 | position: 'absolute', 18 | borderRadius: 20, 19 | borderColor: vars.color.font10, 20 | fontWeight: 500, 21 | fontSize: 13, 22 | lineHeight: '16px', 23 | height: '32px', 24 | color: vars.color.background, 25 | boxShadow: vars.color.elevation3boxShadow, 26 | background: vars.color.font70, 27 | left: 'calc(50% - 155px/2 - 0.5px)', 28 | selectors: { 29 | '&:hover:enabled': { 30 | background: vars.color.font85, 31 | }, 32 | }, 33 | }); 34 | 35 | export const iconLeft = style({ 36 | order: 1, 37 | }); 38 | 39 | export const iconStyle = style({ 40 | width: 16, 41 | height: 16, 42 | }); 43 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/HeaderButton/headerButton.css.ts: -------------------------------------------------------------------------------- 1 | import { type ComplexStyleRule, style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | boxSizing: 'border-box', 6 | flex: 'none', 7 | '-webkit-app-region': 'no-drag', 8 | display: 'flex', 9 | flexDirection: 'row', 10 | justifyContent: 'center', 11 | alignItems: 'center', 12 | padding: 5, 13 | gap: 10, 14 | width: 28, 15 | height: 28, 16 | borderRadius: 5, 17 | zIndex: 4, 18 | color: vars.color.font, 19 | ':hover': { 20 | backgroundColor: vars.components.headerButtonHover, 21 | }, 22 | ':active': { 23 | backgroundColor: vars.components.headerButtonActive, 24 | }, 25 | selectors: { 26 | '&.toggled': { 27 | color: vars.color.primaryActive, 28 | backgroundColor: vars.components.headerButtonHover, 29 | }, 30 | }, 31 | } as ComplexStyleRule); // fix for lacking '-webkit-app-region' type 32 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/HeaderMetrics/headerMetrics.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const activeContainer = style({}); 4 | 5 | export const container = style({ 6 | display: 'flex', 7 | flexDirection: 'row', 8 | alignItems: 'center', 9 | padding: 0, 10 | gap: 16, 11 | height: 38, 12 | }); 13 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/HorizontalLine/HorizontalLine.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './horizontalLine.css'; 2 | 3 | export interface HorizontalLineProps { 4 | type?: 'content' | 'menu' | 'above-tab'; 5 | } 6 | 7 | export const HorizontalLine = ({ type }: HorizontalLineProps) => { 8 | return
; 9 | }; 10 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/HorizontalLine/horizontalLine.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | width: '100%', 6 | height: 1, 7 | background: vars.color.font10, 8 | selectors: { 9 | '&.content': { 10 | margin: '34px 0px', 11 | }, 12 | '&.menu': { 13 | margin: '4px 0px', 14 | background: vars.color.font8, 15 | }, 16 | '&.above-tab': { 17 | marginTop: 34, 18 | }, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Icon/Icon.tsx: -------------------------------------------------------------------------------- 1 | import { ICONS, type IconId } from '../../../assets/images/icons'; 2 | 3 | export interface IconProps { 4 | /** 5 | * What icon do we want to display? 6 | */ 7 | iconId: IconId; 8 | } 9 | 10 | /** 11 | * Primary UI component for user interaction 12 | */ 13 | export const Icon = ({ iconId }: IconProps) => { 14 | return <>{ICONS[iconId]}; 15 | }; 16 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Icon/LoadingIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from './Icon'; 2 | import { loadingIcon } from './loadingIcon.css'; 3 | 4 | export const LoadingIcon = () => { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Icon/loadingIcon.css.ts: -------------------------------------------------------------------------------- 1 | import { keyframes, style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | const rotate = keyframes({ 5 | '0%': { transform: 'rotate(0deg)' }, 6 | '100%': { transform: 'rotate(360deg)' }, 7 | }); 8 | 9 | export const loadingIcon = style({ 10 | fill: vars.color.font, 11 | animationName: rotate, 12 | animationDuration: '3s', 13 | animationIterationCount: 'infinite', 14 | // todo: more generic fix height to icon size 15 | // since a container span is rotating, not the icon directly, 16 | // this has to be the same height of the icon 17 | height: 16, 18 | width: 16, 19 | }); 20 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Input/folderInput.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | gap: 8, 8 | width: '100%', 9 | minWidth: 400, 10 | }); 11 | 12 | export const pathAndChangeContainer = style({ 13 | boxSizing: 'border-box', 14 | display: 'flex', 15 | flexDirection: 'row', 16 | alignItems: 'flex-start', 17 | padding: '0px', 18 | gap: 5, 19 | }); 20 | 21 | export const freeStorageSpaceFontStyle = style({ 22 | fontSize: 11, 23 | color: vars.color.font50, 24 | flexDirection: 'row', 25 | display: 'flex', 26 | }); 27 | 28 | export const checkCircleIcon = style({ 29 | width: 12, 30 | height: 12, 31 | marginRight: 3, 32 | }); 33 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Label/Label.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './label.css'; 2 | 3 | export type LabelColor = 4 | | 'green' 5 | | 'red' 6 | | 'gray' 7 | | 'pink' 8 | | 'purple' 9 | | 'orange' 10 | | 'pink2'; 11 | export interface LabelProps { 12 | label: string; 13 | /** 14 | * Label color 15 | */ 16 | type?: LabelColor; 17 | /** 18 | * Label size TODO: better way? 19 | */ 20 | size?: null | 'small'; 21 | /** 22 | * Bold text? 23 | */ 24 | bold?: boolean; 25 | } 26 | 27 | export const Label = ({ label, type, size, bold = true }: LabelProps) => { 28 | const sizing = size || ''; 29 | const boldText = bold ? 'bold' : ''; 30 | return ( 31 |
34 |
{label}
35 |
36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/LabelSetting/labelSettings.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const titleFont = style({ 4 | fontWeight: 590, 5 | fontSize: 15, 6 | lineHeight: '20px', 7 | letterSpacing: '-0.24px', 8 | }); 9 | 10 | export const columnContainerStyle = style({ 11 | display: 'grid', 12 | columnGap: 41, 13 | gridTemplateColumns: 'repeat(2, 1fr)', 14 | gridTemplateRows: 'masonry', 15 | }); 16 | 17 | export const columnItemStyle = style({ 18 | margin: 0, 19 | display: 'grid', 20 | gridTemplateRows: '1fr auto', 21 | }); 22 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/LabelValues/labelValues.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const titleFont = style({ 4 | fontWeight: 590, 5 | fontSize: 15, 6 | lineHeight: '20px', 7 | letterSpacing: '-0.24px', 8 | }); 9 | 10 | export const columnContainerStyle = style({ 11 | display: 'grid', 12 | columnGap: 41, 13 | gridTemplateColumns: 'repeat(2, 1fr)', 14 | gridTemplateRows: 'masonry', 15 | }); 16 | 17 | export const columnItemStyle = style({ 18 | margin: 0, 19 | display: 'grid', 20 | gridTemplateRows: '1fr auto', 21 | }); 22 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Link/DropdownLink.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '../Icon/Icon'; 2 | import { blockContainer, inlineContainer, linkText } from './externalLink.css'; 3 | 4 | // todo: variants for downloads or internal links 5 | export interface DropdownLinkProps { 6 | /** 7 | * The link text 8 | */ 9 | text?: string; 10 | /** 11 | * Inline the link 12 | */ 13 | inline?: boolean; 14 | onClick?: () => void; 15 | isDown?: boolean; 16 | } 17 | 18 | const DropdownLink = ({ text, inline, onClick, isDown }: DropdownLinkProps) => { 19 | const classContainer = inline ? inlineContainer : blockContainer; 20 | return ( 21 |
29 | {/* biome-ignore lint/a11y/useValidAnchor: */} 30 | 31 | {text} 32 | 33 | {isDown === true ? : } 34 |
35 | ); 36 | }; 37 | export default DropdownLink; 38 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Link/ExternalLink.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '../Icon/Icon'; 2 | import { blockContainer, inlineContainer, linkText } from './externalLink.css'; 3 | 4 | // todo: variants for downloads or internal links 5 | export interface ExternalLinkProps { 6 | /** 7 | * The link url 8 | */ 9 | url: string; 10 | /** 11 | * The link text 12 | */ 13 | text?: string; 14 | /** 15 | * Inline the link 16 | */ 17 | inline?: boolean; 18 | /** 19 | * Hide the external link icon 20 | */ 21 | hideIcon?: boolean; 22 | } 23 | 24 | const ExternalLink = ({ url, text, inline, hideIcon }: ExternalLinkProps) => { 25 | const classContainer = inline ? inlineContainer : blockContainer; 26 | return ( 27 |
28 | 29 | {text} 30 | 31 | {!hideIcon && } 32 |
33 | ); 34 | }; 35 | export default ExternalLink; 36 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Link/InternalLink.tsx: -------------------------------------------------------------------------------- 1 | import { dangerLinkText, linkText } from './internalLink.css'; 2 | 3 | export interface InternalLinkProps { 4 | /** 5 | * The link url 6 | */ 7 | onClick: () => void; 8 | /** 9 | * The link text 10 | */ 11 | text?: string; 12 | /** 13 | * Does the link remove or delete something? 14 | */ 15 | danger?: boolean; 16 | } 17 | 18 | const InternalLink = ({ onClick, text, danger }: InternalLinkProps) => { 19 | const linkStyles = [linkText]; 20 | if (danger) { 21 | linkStyles.push(dangerLinkText); 22 | } 23 | return ( 24 | // biome-ignore lint/a11y/useValidAnchor: 25 | { 29 | console.log('Internal link a onclik'); 30 | e.preventDefault(); 31 | onClick(); 32 | }} 33 | > 34 | {text} 35 | 36 | ); 37 | }; 38 | export default InternalLink; 39 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Link/externalLink.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | // required to export even if not using in a component 5 | export const container = style({ 6 | flexDirection: 'row', 7 | alignItems: 'center', 8 | padding: '0px', 9 | gap: '4px', 10 | color: vars.color.primary, 11 | ':hover': { 12 | color: vars.color.primaryHover, 13 | }, 14 | }); 15 | export const inlineContainer = style([container, { display: 'inline-flex' }]); 16 | export const blockContainer = style([container, { display: 'flex' }]); 17 | 18 | export const linkText = style({ 19 | color: vars.color.primaryLink, 20 | ':hover': { 21 | color: vars.color.primaryLinkHover, 22 | }, 23 | // todo: remove when app.css is removed. Legacy fix 24 | margin: 0, 25 | }); 26 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Link/internalLink.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { common, vars } from '../theme.css'; 3 | 4 | export const linkText = style({ 5 | color: vars.color.primaryLink, 6 | letterSpacing: '-0.08px', 7 | textDecoration: 'none', 8 | ':hover': { 9 | color: vars.color.primaryLinkHover, 10 | textDecoration: 'none', 11 | }, 12 | ':link': { 13 | textDecoration: 'none', 14 | }, 15 | ':visited': { 16 | textDecoration: 'none', 17 | }, 18 | }); 19 | 20 | export const dangerLinkText = style({ 21 | color: common.color.red500, 22 | ':hover': { 23 | color: vars.color.dangerLinkHover, 24 | }, 25 | ':visited': { 26 | color: common.color.red500, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Menu/Menu.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import { container } from './menu.css'; 3 | 4 | export interface MenuProps { 5 | /** 6 | * What's the width? 7 | */ 8 | width?: number; 9 | /** 10 | * Menu Items? 11 | */ 12 | children?: React.ReactNode; 13 | } 14 | 15 | /** 16 | * Primary UI component for user interaction 17 | */ 18 | export const Menu = ({ width, children }: MenuProps) => { 19 | return ( 20 |
21 | {children} 22 |
23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Menu/menu.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | alignItems: 'flex-start', 8 | boxSizing: 'border-box', 9 | background: vars.components.menuBackground, 10 | border: vars.components.menuBorder, 11 | boxShadow: vars.color.elevation4boxShadow, 12 | borderRadius: '5px', 13 | padding: '4px 0', 14 | }); 15 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/SidebarLinkItem/sidebarLinkItem.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const activeContainer = style({}); 5 | 6 | export const container = style({ 7 | display: 'flex', 8 | flexDirection: 'row', 9 | alignItems: 'center', 10 | gap: '8px', 11 | padding: '6px 10px', 12 | height: '18px', 13 | borderRadius: '5px', 14 | cursor: 'pointer', 15 | userSelect: 'none', 16 | }); 17 | 18 | export const selectedContainer = style({ 19 | background: vars.color.background96, 20 | }); 21 | 22 | export const labelText = style({ 23 | flex: '1', 24 | fontWeight: '500', 25 | fontSize: '13px', 26 | lineHeight: '16px', 27 | color: vars.color.font70, 28 | }); 29 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/SidebarTitleItem/SidebarTitleItem.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './sidebarTitleItem.css'; 2 | 3 | export interface SidebarTitleItemProps { 4 | /** 5 | * Sidebar title content 6 | */ 7 | title: string; 8 | } 9 | 10 | /** 11 | * Primary UI component for user interaction 12 | */ 13 | export const SidebarTitleItem = ({ title }: SidebarTitleItemProps) => { 14 | return
{title}
; 15 | }; 16 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/SidebarTitleItem/sidebarTitleItem.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const activeContainer = style({}); 5 | 6 | export const container = style({ 7 | display: 'flex', 8 | flexDirection: 'row', 9 | fontStyle: 'normal', 10 | fontWeight: '590', 11 | fontSize: '11px', 12 | lineHeight: '14px', 13 | padding: '8px 10px', 14 | width: '100%', 15 | color: vars.color.font40, 16 | }); 17 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/SpecialSelect/specialSelect.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const base = style({}); 4 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Stepper/stepper.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const bottomBar = style({ 5 | height: 60, 6 | width: '100%', 7 | // Prevents from shrinking height below 60px. Idk why it is needed 8 | flexShrink: 0, 9 | borderTop: '1px solid', 10 | borderColor: vars.color.font10, 11 | display: 'flex', 12 | flexDirection: 'row', 13 | justifyContent: 'space-between', 14 | }); 15 | 16 | export const previousButton = style({ 17 | marginLeft: '14px', 18 | marginTop: '14px', 19 | }); 20 | 21 | export const nextButton = style({ 22 | marginRight: '14px', 23 | marginTop: '14px', 24 | }); 25 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/TabContent/tabContent.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | // required to export even if not using in a component 4 | export const container = style({}); 5 | 6 | export const contentHeader = style({ 7 | height: 28, 8 | display: 'flex', 9 | flexDirection: 'row', 10 | alignItems: 'center', 11 | justifyContent: 'space-between', 12 | marginBottom: 28, 13 | }); 14 | 15 | export const contentPeriod = style({}); 16 | 17 | export const contentTitle = style({ 18 | fontWeight: 590, 19 | fontSize: 15, 20 | lineHeight: '20px', 21 | letterSpacing: '-0.24px', 22 | }); 23 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/TabItem/TabItem.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import { container } from './tabItem.css'; 3 | 4 | export interface TabItemProps { 5 | /** 6 | * What's the current active tab id? 7 | */ 8 | activeTabId: string | undefined; 9 | 10 | /** 11 | * Required tab label 12 | */ 13 | label: string | undefined; 14 | 15 | /** 16 | * Tab action 17 | */ 18 | onClickTabItem: (tab: string | undefined) => void; 19 | } 20 | 21 | const TabItem = ({ activeTabId, label, onClickTabItem }: TabItemProps) => { 22 | const onClickAction = () => { 23 | onClickTabItem(label); 24 | }; 25 | const tabActiveStyle = activeTabId === label ? 'active' : ''; 26 | return ( 27 |
  • 32 | {label} 33 |
  • 34 | ); 35 | }; 36 | 37 | export default memo(TabItem); 38 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/TabItem/tabItem.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { common, vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | listStyleType: 'none', 6 | fontWeight: 590, 7 | fontSize: '13px', 8 | height: '100%', 9 | display: 'flex', 10 | flexDirection: 'column', 11 | justifyContent: 'center', 12 | lineHeight: '16px', 13 | letterSpacing: '-0.12px', 14 | color: vars.color.font50, 15 | userSelect: 'none', 16 | cursor: 'pointer', 17 | selectors: { 18 | '&.active': { 19 | color: common.color.purple600, 20 | }, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Tabs/tabs.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | // required to export even if not using in a component 5 | export const container = style({}); 6 | 7 | export const tabsContainer = style({ 8 | selectors: { 9 | '&.modal': { 10 | position: 'sticky', 11 | top: 0, 12 | backgroundColor: vars.color.background, 13 | zIndex: 1, 14 | }, 15 | }, 16 | }); 17 | 18 | export const tabsList = style({ 19 | display: 'flex', 20 | flexDirection: 'row', 21 | gap: 24, 22 | height: 28, 23 | alignItems: 'center', 24 | padding: '10px 0', 25 | selectors: { 26 | '&.modal': { 27 | paddingLeft: 32, 28 | }, 29 | }, 30 | }); 31 | 32 | export const tabContent = style({ 33 | paddingTop: 36, 34 | selectors: { 35 | '&.modal': { 36 | boxSizing: 'border-box', 37 | overflowY: 'hidden', 38 | // extra padding from scrollbar 39 | padding: '36px 32px 0px 32px', 40 | height: 'auto', 41 | width: 624, 42 | }, 43 | }, 44 | }); 45 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Tag/Tag.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './tag.css'; 2 | 3 | export interface TagProps { 4 | label: string; 5 | /** 6 | * Tag color 7 | */ 8 | type?: 'pink' | 'pink2' | 'green'; 9 | } 10 | 11 | const Tag = ({ label, type }: TagProps) => { 12 | return ( 13 |
    14 |
    {label}
    15 |
    16 | ); 17 | }; 18 | 19 | export default Tag; 20 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Tag/tag.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | // required to export even if not using in a component 5 | export const container = style({ 6 | display: 'flex', 7 | flexDirection: 'row', 8 | justifyContent: 'center', 9 | alignItems: 'center', 10 | padding: '3px 6px', 11 | gap: '4px', 12 | borderRadius: '5px', 13 | fontSize: '11px', 14 | lineHeight: '14px', 15 | flex: 'none', 16 | order: 0, 17 | flexGrow: 0, 18 | width: 'fit-content', 19 | selectors: { 20 | '&.pink': { 21 | background: vars.components.tagPinkBackground, 22 | color: vars.components.tagPinkFontColor, 23 | }, 24 | '&.pink2': { 25 | background: vars.components.tagPink2Background, 26 | color: vars.components.tagPink2FontColor, 27 | }, 28 | '&.green': { 29 | background: vars.components.tagGreenBackground, 30 | color: vars.components.tagGreenFontColor, 31 | }, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Tooltip/Tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { container, contentStyle, titleStyle } from './tooltip.css'; 2 | 3 | export interface TooltipProps { 4 | /** 5 | * What's the title? 6 | */ 7 | title: string; 8 | /** 9 | * Is there content? 10 | */ 11 | content?: string; 12 | } 13 | 14 | /** 15 | * Primary UI component for user interaction 16 | */ 17 | export const Tooltip = ({ title, content }: TooltipProps) => { 18 | return ( 19 |
    20 |
    {title}
    21 |
    {content}
    22 |
    23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Tooltip/tooltip.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | // required to export even if not using in a component 5 | export const container = style({ 6 | display: 'flex', 7 | flexDirection: 'column', 8 | alignItems: 'flex-start', 9 | padding: 8, 10 | gap: 2, 11 | fontSize: '11px', 12 | lineHeight: '14px', 13 | width: 177, 14 | color: vars.color.font70, 15 | border: vars.components.menuBorder, 16 | boxShadow: vars.color.elevation4boxShadow, 17 | backgroundColor: vars.components.menuBackground, 18 | borderRadius: 5, 19 | }); 20 | 21 | export const titleStyle = style({ 22 | fontWeight: 600, 23 | }); 24 | 25 | export const contentStyle = style({ 26 | fontWeight: 400, 27 | }); 28 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Typography/Caption.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import { captionTextClass } from './caption.css'; 3 | 4 | export interface CaptionProps { 5 | children?: React.ReactNode; 6 | text?: React.ReactNode | string; 7 | type?: string; 8 | // todo: display block or inline? 9 | } 10 | 11 | const Caption = ({ text, children, type }: CaptionProps) => { 12 | return ( 13 |
    {children ?? text}
    14 | ); 15 | }; 16 | 17 | export default Caption; 18 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/Typography/caption.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const captionTextClass = style({ 5 | fontWeight: 400, 6 | fontSize: 11, 7 | lineHeight: '14px', 8 | color: vars.color.font70, 9 | selectors: { 10 | '&.modal': { 11 | color: vars.color.font50, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/UpdateCallout/updateCallout.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | // required to export even if not using in a component 5 | export const container = style({ 6 | position: 'relative', 7 | overflow: 'hidden', 8 | }); 9 | 10 | export const title = style({ 11 | fontStyle: 'normal', 12 | fontWeight: 590, 13 | fontSize: 13, 14 | lineHeight: '16px', 15 | letterSpacing: '-0.12px', 16 | color: vars.color.font, 17 | marginBottom: 8, 18 | }); 19 | 20 | export const description = style({ 21 | fontStyle: 'normal', 22 | fontWeight: 400, 23 | fontSize: 13, 24 | lineHeight: '18px', 25 | letterSpacing: '-0.08px', 26 | color: vars.color.font70, 27 | marginBottom: 8, 28 | }); 29 | 30 | export const link = style({ 31 | marginBottom: 8, 32 | }); 33 | 34 | export const buttonContainer = style({ 35 | display: 'flex', 36 | flexDirection: 'row', 37 | alignItems: 'center', 38 | padding: 0, 39 | gap: 8, 40 | marginTop: 13, 41 | }); 42 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/VerticalLine/VerticalLine.tsx: -------------------------------------------------------------------------------- 1 | import { container } from './verticalLine.css'; 2 | 3 | export interface VerticalLineProps { 4 | type?: 'content'; 5 | } 6 | 7 | const VerticalLine = ({ type }: VerticalLineProps) => { 8 | return
    ; 9 | }; 10 | export default VerticalLine; 11 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/VerticalLine/verticalLine.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../theme.css'; 3 | 4 | export const container = style({ 5 | height: '100%', 6 | width: 1, 7 | background: vars.color.font10, 8 | selectors: { 9 | '&.content': { 10 | margin: '34px 0px', 11 | }, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /src/renderer/Generics/redesign/globalStyle.css.ts: -------------------------------------------------------------------------------- 1 | import { globalStyle } from '@vanilla-extract/css'; 2 | import { vars } from './theme.css'; 3 | 4 | globalStyle('#onBoarding', { 5 | fontFamily: 6 | '-apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Ubuntu', 7 | fontSize: 13, 8 | color: vars.color.font, 9 | }); 10 | 11 | globalStyle('.redesignComponent', { 12 | fontFamily: 13 | '-apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Ubuntu', 14 | fontSize: 13, 15 | background: vars.color.background, 16 | color: vars.color.font, 17 | }); 18 | -------------------------------------------------------------------------------- /src/renderer/Presentational/AddNode/addNode.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | alignItems: 'flex-start', 8 | gap: 16, 9 | paddingBottom: 20, 10 | minHeight: '40vh', 11 | // height must be set along with border box to avoid a small scroll bar 12 | // due to the 20px of padding on the bottom 13 | height: '100%', 14 | boxSizing: 'border-box', 15 | }); 16 | 17 | export const titleFont = style({ 18 | fontWeight: 500, 19 | fontSize: 32, 20 | lineHeight: '32px', 21 | letterSpacing: '-0.01em', 22 | }); 23 | 24 | export const descriptionFont = style({ 25 | fontWeight: 400, 26 | fontSize: 13, 27 | lineHeight: '18px', 28 | color: vars.color.font70, 29 | marginBottom: 8, 30 | }); 31 | 32 | export const sectionFont = style({ 33 | fontWeight: 600, 34 | marginBottom: 0, 35 | }); 36 | 37 | export const descriptionContainer = style({ 38 | marginBottom: 16, 39 | }); 40 | -------------------------------------------------------------------------------- /src/renderer/Presentational/AddNodeStepper/podmanRequirements.ts: -------------------------------------------------------------------------------- 1 | import type { PodmanDetails } from '../../../main/podman/details'; 2 | 3 | export const arePodmanRequirementsMet = ( 4 | podmanDetails: PodmanDetails, 5 | ): boolean => { 6 | let isPodmanRequirementsMet = false; 7 | if (podmanDetails?.isRunning && !podmanDetails.isOutdated) { 8 | isPodmanRequirementsMet = true; 9 | } 10 | return isPodmanRequirementsMet; 11 | }; 12 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ContentMultipleClients/contentMultipleClients.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | // margin: '64px 40px', 6 | boxSizing: 'border-box', 7 | }); 8 | 9 | export const promptContainer = style({ 10 | marginBottom: 34, 11 | }); 12 | 13 | export const sectionTitle = style({ 14 | fontWeight: 590, 15 | fontSize: '20px', 16 | lineHeight: '100%', 17 | letterSpacing: '-0.4px', 18 | marginBottom: 20, 19 | }); 20 | 21 | export const sectionDescription = style({ 22 | fontStyle: 'normal', 23 | fontWeight: 400, 24 | fontSize: 13, 25 | lineHeight: '18px', 26 | letterSpacing: '-0.08px', 27 | color: vars.color.font50, 28 | }); 29 | 30 | export const clientCardsContainer = style({ 31 | display: 'flex', 32 | flexDirection: 'row', 33 | alignItems: 'flex-start', 34 | padding: 0, 35 | gap: 24, 36 | }); 37 | 38 | export const resourcesContainer = style({ 39 | marginTop: 32, 40 | }); 41 | 42 | export const horizontalLine = style({ 43 | padding: '0 20px', 44 | }); 45 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ContentSingleClient/contentSingleClient.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const sectionTitle = style({ 5 | fontWeight: 590, 6 | fontSize: '20px', 7 | lineHeight: '100%', 8 | letterSpacing: '-0.4px', 9 | marginBottom: 20, 10 | }); 11 | 12 | export const sectionDescription = style({ 13 | fontStyle: 'normal', 14 | fontWeight: 400, 15 | fontSize: 13, 16 | lineHeight: '18px', 17 | letterSpacing: '-0.08px', 18 | color: vars.color.font50, 19 | }); 20 | 21 | export const clientCardsContainer = style({ 22 | display: 'flex', 23 | flexDirection: 'row', 24 | alignItems: 'flex-start', 25 | padding: 0, 26 | gap: 24, 27 | }); 28 | 29 | export const resourcesContainer = style({ 30 | marginTop: 32, 31 | }); 32 | 33 | export const horizontalLine = style({ 34 | padding: '0 20px', 35 | }); 36 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ControllerUpdate/controllerUpdate.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { common } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | width: 624, 8 | }); 9 | 10 | export const topBanner = style({ 11 | height: 92, 12 | backgroundColor: common.color.pink100, 13 | borderTopLeftRadius: 14, 14 | borderTopRightRadius: 14, 15 | display: 'flex', 16 | justifyContent: 'center', 17 | }); 18 | 19 | export const contentContainer = style({ 20 | padding: '24px 24px 0px 24px', 21 | gap: 24, 22 | display: 'flex', 23 | flexDirection: 'column', 24 | }); 25 | 26 | export const contentSection = style({ 27 | display: 'flex', 28 | flexDirection: 'column', 29 | gap: 8, 30 | fontSize: 13, 31 | fontWeight: 400, 32 | lineHeight: '18px', 33 | letterSpacing: '-0.08px', 34 | }); 35 | 36 | export const contentMajorTitle = style({ 37 | fontWeight: 590, 38 | fontSize: 20, 39 | lineHeight: '24px', 40 | letterSpacing: '-0.4px', 41 | }); 42 | 43 | export const contentTitle = style({ 44 | fontWeight: 590, 45 | }); 46 | -------------------------------------------------------------------------------- /src/renderer/Presentational/DevMode/DevMode.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import type { Settings } from '../../../main/state/settings.js'; 3 | import { useGetSettingsQuery } from '../../state/settingsService.js'; 4 | 5 | export const DevMode = ({ children }) => { 6 | const [sIsVisible, setIsVisible] = useState(false); 7 | const qSettings = useGetSettingsQuery(); 8 | 9 | useEffect(() => { 10 | qSettings.refetch(); 11 | const settingsData = qSettings?.data as Settings; 12 | // console.log('DEV MODE: settingsData', settingsData); 13 | setIsVisible(settingsData?.appIsDeveloperModeEnabled === true); 14 | }, [qSettings.data]); 15 | 16 | if (sIsVisible) { 17 | return ( 18 |
    19 | 👷 20 | {children} 21 |
    22 | ); 23 | } 24 | return null; 25 | }; 26 | -------------------------------------------------------------------------------- /src/renderer/Presentational/FailSystemRequirements/FailSystemRequirementsDetector.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import electron from '../../electronGlobal'; 3 | import { useAppDispatch } from '../../state/hooks'; 4 | import { setModalState } from '../../state/modal'; 5 | 6 | const FailSystemRequirementsDetector = () => { 7 | const dispatch = useAppDispatch(); 8 | 9 | useEffect(() => { 10 | const asyncData = async () => { 11 | const failSystemRequirementsData = 12 | await electron.getFailSystemRequirements(); 13 | console.log( 14 | 'pref failSystemRequirementsData', 15 | failSystemRequirementsData, 16 | ); 17 | if (failSystemRequirementsData.failedRequirements.length > 0) { 18 | // if there is a failed requirement, show the alert 19 | dispatch( 20 | setModalState({ 21 | isModalOpen: true, 22 | screen: { route: 'failSystemRequirements', type: 'modal' }, 23 | }), 24 | ); 25 | } 26 | }; 27 | asyncData(); 28 | }, [dispatch]); 29 | 30 | return <>; 31 | }; 32 | 33 | export default FailSystemRequirementsDetector; 34 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ModalManager/AlphaBuildModal.tsx: -------------------------------------------------------------------------------- 1 | import { Modal } from '../../Generics/redesign/Modal/Modal'; 2 | import electron from '../../electronGlobal'; 3 | import AlphaBuild from '../AlphaBuild/AlphaBuild'; 4 | import { modalRoutes } from './modalUtils'; 5 | 6 | type Props = { 7 | modalOnClose: () => void; 8 | }; 9 | 10 | export const AlphaBuildModal = ({ modalOnClose }: Props) => { 11 | const buttonSaveLabel = 'I Understand'; 12 | 13 | const modalOnSaveConfig = async () => { 14 | await electron.getSetHasSeenAlphaModal(true); 15 | console.log('save!'); 16 | modalOnClose(); 17 | }; 18 | 19 | return ( 20 | 29 | 30 | 31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ModalManager/UpdateModal.tsx: -------------------------------------------------------------------------------- 1 | import { Modal } from '../../Generics/redesign/Modal/Modal.js'; 2 | import UpdateWrapper from '../UpdateModal/UpdateWrapper.js'; 3 | import { type ModalConfig, modalOnChangeConfig } from './modalUtils.js'; 4 | import { modalRoutes } from './modalUtils.js'; 5 | 6 | type Props = { 7 | modalOnClose: () => void; 8 | data: any; 9 | }; 10 | 11 | export const UpdateModal = ({ modalOnClose, data }: Props) => { 12 | const { deeplink, nodeOverview } = data; 13 | const modalOnSaveConfig = async (updatedConfig: ModalConfig | undefined) => { 14 | modalOnClose(); 15 | }; 16 | 17 | return ( 18 | 26 | 31 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /src/renderer/Presentational/NodePackageScreen/NodePackageScreen.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | width: '100%', 6 | height: '100%', 7 | display: 'flex', 8 | justifyContent: 'center', 9 | alignItems: 'center', 10 | }); 11 | 12 | export const contentContainer = style({ 13 | alignItems: 'center', 14 | display: 'flex', 15 | flexDirection: 'column', 16 | width: 520, 17 | }); 18 | 19 | export const titleFont = style({ 20 | fontWeight: 590, 21 | fontSize: 15, 22 | lineHeight: '20px', 23 | color: vars.color.font, 24 | letterSpacing: '-0.24px', 25 | textAlign: 'center', 26 | marginBottom: 8, 27 | }); 28 | 29 | export const descriptionFont = style({ 30 | fontWeight: 400, 31 | fontSize: 13, 32 | lineHeight: '18px', 33 | color: vars.color.font70, 34 | letterSpacing: '-0.08px', 35 | marginBottom: 24, 36 | }); 37 | -------------------------------------------------------------------------------- /src/renderer/Presentational/NodeRequirements/nodeRequirements.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | alignItems: 'flex-start', 8 | gap: 16, 9 | }); 10 | 11 | export const titleFont = style({ 12 | fontWeight: 500, 13 | fontSize: 32, 14 | lineHeight: '32px', 15 | letterSpacing: '-0.01em', 16 | }); 17 | 18 | export const descriptionFont = style({ 19 | fontWeight: 400, 20 | fontSize: 13, 21 | lineHeight: '18px', 22 | color: vars.color.font70, 23 | }); 24 | 25 | export const checklistContainer = style({ 26 | selectors: { 27 | '&.loading': { 28 | height: 445, 29 | width: '100%', 30 | }, 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /src/renderer/Presentational/NodeScreen/NodeScreen.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const container = style({ 5 | width: '100%', 6 | height: '100%', 7 | display: 'flex', 8 | justifyContent: 'center', 9 | alignItems: 'center', 10 | }); 11 | 12 | export const contentContainer = style({ 13 | alignItems: 'center', 14 | display: 'flex', 15 | flexDirection: 'column', 16 | width: 520, 17 | }); 18 | 19 | export const titleFont = style({ 20 | fontWeight: 590, 21 | fontSize: 15, 22 | lineHeight: '20px', 23 | color: vars.color.font, 24 | letterSpacing: '-0.24px', 25 | textAlign: 'center', 26 | marginBottom: 8, 27 | }); 28 | 29 | export const descriptionFont = style({ 30 | fontWeight: 400, 31 | fontSize: 13, 32 | lineHeight: '18px', 33 | color: vars.color.font70, 34 | letterSpacing: '-0.08px', 35 | marginBottom: 24, 36 | }); 37 | 38 | export const backButtonContainer = style({ 39 | position: 'absolute', 40 | left: 14, 41 | top: 12, 42 | zIndex: 4, 43 | }); 44 | -------------------------------------------------------------------------------- /src/renderer/Presentational/NodeSettings/NodeSettings.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const nodeCommandTitle = style({ 5 | fontWeight: 590, 6 | color: vars.color.font70, 7 | letterSpacing: '-0.12px', 8 | fontSize: '13px', 9 | lineHeight: '16px', 10 | }); 11 | 12 | export const nodeCommandContainer = style({ 13 | display: 'flex', 14 | paddingTop: 8, 15 | }); 16 | 17 | export const nodeCommand = style({ 18 | fontFamily: 'monospace', 19 | fontSize: 11, 20 | lineHeight: '14px', 21 | color: vars.color.font50, 22 | }); 23 | 24 | export const emptyContainer = style({ 25 | minHeight: 1000, 26 | minWidth: 624, 27 | }); 28 | -------------------------------------------------------------------------------- /src/renderer/Presentational/NodeSetup/NodeSetup.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { useNavigate } from 'react-router-dom'; 3 | import Splash from '../../Generics/redesign/Splash/Splash'; 4 | import electron from '../../electronGlobal'; 5 | import AddNodeStepper from '../AddNodeStepper/AddNodeStepper'; 6 | import FailSystemRequirementsDetector from '../FailSystemRequirements/FailSystemRequirementsDetector'; 7 | 8 | const NodeSetup = () => { 9 | const [hasClicked, setHasClicked] = useState(false); 10 | const navigate = useNavigate(); 11 | 12 | if (!hasClicked) { 13 | return ( 14 | <> 15 | setHasClicked(true)} /> 16 | 17 | 18 | ); 19 | } 20 | return ( 21 | { 23 | if (newValue === 'done' || newValue === 'cancel') { 24 | navigate('/main/nodePackage'); 25 | electron.getSetHasSeenSplashscreen(true); 26 | } 27 | }} 28 | /> 29 | ); 30 | }; 31 | 32 | export default NodeSetup; 33 | -------------------------------------------------------------------------------- /src/renderer/Presentational/Notifications/NotificationsWrapper.tsx: -------------------------------------------------------------------------------- 1 | import electron from '../../electronGlobal'; 2 | import { useGetNotificationsQuery } from '../../state/notificationsService'; 3 | import Notifications from './Notifications'; 4 | 5 | export const NotificationsWrapper = () => { 6 | const qNotifications = useGetNotificationsQuery(); 7 | 8 | const onNotificationItemClick = () => { 9 | console.log('notification was clicked, open the route'); 10 | }; 11 | 12 | return ( 13 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /src/renderer/Presentational/PodmanModal/PodmanWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import type { ModalConfig } from '../ModalManager/modalUtils.js'; 3 | import PodmanInstallation from '../PodmanInstallation/PodmanInstallation.tsx'; 4 | 5 | export interface PodmanWrapperProps { 6 | modalOnChangeConfig: (config: ModalConfig, save?: boolean) => void; 7 | disableSaveButton: (value: boolean) => void; 8 | } 9 | 10 | const PodmanWrapper = ({ 11 | modalOnChangeConfig, 12 | disableSaveButton, 13 | }: PodmanWrapperProps) => { 14 | const onChangeDockerInstall = useCallback((newValue: string) => { 15 | if (newValue === 'done') { 16 | disableSaveButton(false); 17 | } 18 | }, []); 19 | 20 | return ( 21 | 25 | ); 26 | }; 27 | 28 | export default PodmanWrapper; 29 | -------------------------------------------------------------------------------- /src/renderer/Presentational/RemoveNodeModal/removeNode.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | 3 | export const container = style({ 4 | display: 'flex', 5 | flexDirection: 'column', 6 | gap: 16, 7 | width: 332, 8 | }); 9 | 10 | export const removeText = style({ 11 | lineHeight: '18px', 12 | }); 13 | -------------------------------------------------------------------------------- /src/renderer/Presentational/ResetConfigModal/ResetConfigWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useAppSelector } from '../../state/hooks'; 3 | import { selectSelectedNode } from '../../state/node'; 4 | import type { ModalConfig } from '../ModalManager/modalUtils'; 5 | 6 | export interface ResetConfigWrapperProps { 7 | modalOnChangeConfig: (config: ModalConfig, save?: boolean) => void; 8 | } 9 | 10 | const ResetConfigWrapper = ({ 11 | modalOnChangeConfig, 12 | }: ResetConfigWrapperProps) => { 13 | const selectedNode = useAppSelector(selectSelectedNode); 14 | 15 | useEffect(() => { 16 | modalOnChangeConfig({ selectedNode }); 17 | }, [selectedNode]); 18 | 19 | return <>; 20 | }; 21 | 22 | export default ResetConfigWrapper; 23 | -------------------------------------------------------------------------------- /src/renderer/Presentational/SystemMonitor/SystemMonitor.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslation } from 'react-i18next'; 2 | 3 | import { SystemMonitor as SystemMonitorLabels } from '../../Generics/redesign/SystemMonitor/SystemMonitor'; 4 | import { Benchmarks } from './Benchmarks'; 5 | import { headerContainer, titleStyle } from './systemMonitor.css'; 6 | 7 | const SystemMonitor = () => { 8 | const { t } = useTranslation(); 9 | 10 | return ( 11 | <> 12 |
    13 |
    {t('SystemMonitor')}
    14 |
    15 | 16 | 17 | 18 | ); 19 | }; 20 | export default SystemMonitor; 21 | -------------------------------------------------------------------------------- /src/renderer/Presentational/SystemMonitor/systemMonitor.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from '../../Generics/redesign/theme.css'; 3 | 4 | export const headerContainer = style({ 5 | display: 'flex', 6 | flexDirection: 'row', 7 | marginBottom: 32, 8 | gap: 5, 9 | alignItems: 'center', 10 | }); 11 | 12 | export const titleStyle = style({ 13 | alignSelf: 'stretch', 14 | fontStyle: 'normal', 15 | fontWeight: '590', 16 | fontSize: '32px', 17 | lineHeight: '100%', 18 | textTransform: 'capitalize', 19 | color: vars.color.font, 20 | }); 21 | 22 | export const emptyNotifications = style({}); 23 | -------------------------------------------------------------------------------- /src/renderer/__mocks__/electronGlobal.ts: -------------------------------------------------------------------------------- 1 | import createIPCMock from 'electron-mock-ipc'; 2 | import * as customPreloads from './custom-preload-mock'; 3 | 4 | const mocked = createIPCMock(); 5 | const { ipcMain, ipcRenderer } = mocked; 6 | const electron = { ipcMain, ipcRenderer, ...customPreloads }; 7 | export default electron; 8 | -------------------------------------------------------------------------------- /src/renderer/__mocks__/react-i18next.ts: -------------------------------------------------------------------------------- 1 | export const changeLanguage = () => {}; 2 | export const useTranslation = () => { 3 | return { 4 | t: (str: string) => str, 5 | i18n: { 6 | changeLanguage: () => {}, 7 | }, 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /src/renderer/__mocks__/svg.ts: -------------------------------------------------------------------------------- 1 | export default 'SvgrURL'; 2 | export const ReactComponent = 'div'; 3 | -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter-Bold.ttf -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter-ExtraLight.ttf -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter-Light.ttf -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter-SemiBold.ttf -------------------------------------------------------------------------------- /src/renderer/assets/fonts/Inter.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/fonts/Inter.ttf -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/auto-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/auto-dark.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/auto-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/auto-light.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/dark-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/dark-dark.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/dark-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/dark-light.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/light-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/light-dark.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/light-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/light-light.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-01-Dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-01-Dm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-01-Lm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-01-Lm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-02-Dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-02-Dm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-02-Lm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-02-Lm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-03-Dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-03-Dm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/onboarding-03-Lm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/onboarding-03-Lm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/wallet.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/welcome-Dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/welcome-Dm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/artwork/welcome-Lm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/artwork/welcome-Lm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Block.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Bolt-strike.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Bolt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check-badge-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check-circle-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check-double.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Check2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Close-circle-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Down-large.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Download-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Ellipsis.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Health.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Info-circle-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Info-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Intermediate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Left-large.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Lightning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Mail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Right-large.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Shape2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Shape3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Slots.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Spinner-endless.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Spinner-small.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Sync-small.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Sync.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Up-large.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Warning-circle-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/icons/Warning-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Besu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Besu.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Erigon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Erigon.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Geth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Geth.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Lighthouse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Lighthouse.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Lodestar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Lodestar.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Nethermind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Nethermind.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Nimbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Nimbus.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Prysm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Prysm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Reth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Reth.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeBackgrounds/Teku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeBackgrounds/Teku.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Arbitrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Arbitrum.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Base.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Besu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Besu.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Erigon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Erigon.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Ethereum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Ethereum.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Farcaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Farcaster.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Geth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Geth.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Lighthouse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Lighthouse.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Livepeer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Livepeer.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Lodestar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Lodestar.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Magi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Magi.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Minecraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Minecraft.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Nethermind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Nethermind.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Nimbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Nimbus.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-OP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-OP.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Optimism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Optimism.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-OptimismJava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-OptimismJava.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Prysm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Prysm.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Radicle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Radicle.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Reth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Reth.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Starknet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Starknet.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-Teku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-Teku.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/Logo-zkSync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/nodeIcons/Logo-zkSync.png -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/healthy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/sync.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/assets/images/nodeIcons/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/assets/images/syncModes/syncMode1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/renderer/assets/images/syncModes/syncMode3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/argent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/wallets/argent.png -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/brave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/wallets/brave.png -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/coinbase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/wallets/coinbase.png -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/index.tsx: -------------------------------------------------------------------------------- 1 | import argent from './argent.png'; 2 | import brave from './brave.png'; 3 | import coinbase from './coinbase.png'; 4 | import metamask from './metamask.png'; 5 | import tally from './tally.png'; 6 | 7 | export interface WalletBackgrounds { 8 | argent?: string; 9 | brave?: string; 10 | coinbase?: string; 11 | metamask?: string; 12 | tally?: string; 13 | } 14 | 15 | // Define all wallets here 16 | export const WALLET_BACKGROUNDS: WalletBackgrounds = { 17 | argent, 18 | brave, 19 | coinbase, 20 | metamask, 21 | tally, 22 | }; 23 | 24 | export type WalletBackgroundId = keyof WalletBackgrounds; 25 | -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/metamask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/wallets/metamask.png -------------------------------------------------------------------------------- /src/renderer/assets/images/wallets/tally.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NiceNode/nice-node/17209271af13ea95f3ce74196353f3648fa47691/src/renderer/assets/images/wallets/tally.png -------------------------------------------------------------------------------- /src/renderer/electronGlobal.ts: -------------------------------------------------------------------------------- 1 | // export const { ipcRenderer } = window.electron; 2 | export default window.electron; 3 | -------------------------------------------------------------------------------- /src/renderer/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_APP_TITLE: string; 5 | readonly MP_PROJECT_ENV: string; 6 | readonly NICENODE_ENV: string; 7 | // more env variables... 8 | } 9 | 10 | interface ImportMeta { 11 | readonly env: ImportMetaEnv; 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/events/environment.ts: -------------------------------------------------------------------------------- 1 | // declares the type of the injected variable process from webpack plugin 2 | declare let process: { env: Record }; 3 | 4 | type Envs = 'dev' | 'staging' | 'prod'; 5 | // do not destruct because webpack replaces exact string match to 'process.env.' 6 | export const MP_PROJECT_TOKEN = import.meta.env.MP_PROJECT_TOKEN; 7 | export const MP_PROJECT_ENV: Envs = 8 | (import.meta.env.MP_PROJECT_ENV as Envs) || 'dev'; 9 | -------------------------------------------------------------------------------- /src/renderer/events/events.ts: -------------------------------------------------------------------------------- 1 | export type NNEvent = 2 | | 'OpenApp' 3 | | 'AddNode' 4 | | 'AddNodePackage' 5 | | 'RemoveNodePackage' 6 | | 'InstalledPodman' 7 | | 'OpenAddNodeModal' 8 | | 'UpdatedNiceNode' 9 | | 'UserCheckForUpdateNN' 10 | | 'DisablePreReleaseUpdates' 11 | | 'EnablePreReleaseUpdates' 12 | | 'DisableEventReporting' 13 | | 'EnableEventReporting'; 14 | -------------------------------------------------------------------------------- /src/renderer/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import { Provider } from 'react-redux'; 4 | 5 | import App from './App'; 6 | // import i18n (needs to be bundled) 7 | import './i18n'; 8 | import { store } from './state/store'; 9 | 10 | const container = document.getElementById('root'); 11 | if (!container) { 12 | throw new Error('No root html element found'); 13 | } 14 | const root = createRoot(container); 15 | root.render( 16 | 17 | 18 | , 19 | ); 20 | -------------------------------------------------------------------------------- /src/renderer/jsonRpcClient.ts: -------------------------------------------------------------------------------- 1 | export const callJsonRpc = async (method: string, params: any[]) => { 2 | const resp = await fetch('http://localhost:9545', { 3 | method: 'POST', 4 | headers: { 5 | 'content-type': 'application/json', 6 | }, 7 | mode: 'no-cors', 8 | body: JSON.stringify({ 9 | id: 'id', 10 | jsonrpc: '2.0', 11 | method, 12 | params, 13 | }), 14 | }); 15 | return resp.json(); 16 | }; 17 | -------------------------------------------------------------------------------- /src/renderer/renderer.ts: -------------------------------------------------------------------------------- 1 | import './index'; 2 | -------------------------------------------------------------------------------- /src/renderer/state/hooks.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type TypedUseSelectorHook, 3 | useDispatch, 4 | useSelector, 5 | } from 'react-redux'; 6 | import type { AppDispatch, RootState } from './store'; 7 | 8 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 9 | export const useAppDispatch = () => useDispatch(); 10 | export const useAppSelector: TypedUseSelectorHook = useSelector; 11 | -------------------------------------------------------------------------------- /src/renderer/themeManager.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css'; 2 | import { vars } from './Generics/redesign/theme.css'; 3 | 4 | export const background = style({ 5 | background: vars.color.background, 6 | selectors: { 7 | '&.darwin': { 8 | background: 'none', 9 | }, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /src/stories/Generic/Alert.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Alert } from '../../renderer/Generics/redesign/Alert/Alert'; 4 | 5 | export default { 6 | title: 'Generic/Alert', 7 | component: Alert, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | title: 'Something happened', 13 | isOpen: true, 14 | message: 15 | 'You need to be aware this happened. Let NiceNode fix this automatically?', 16 | onClickCloseButton: () => alert('Closing does not work in Storybook'), 17 | onClickActionButton: () => alert('The user confirmed the alert.'), 18 | }, 19 | }; 20 | 21 | export const RemoveNode = { 22 | args: { 23 | title: 'Remove node', 24 | isOpen: true, 25 | message: 26 | 'Are you sure you want to delete “Ethereum node”? Chain related data and configuration settings will be removed.', 27 | onClickCloseButton: () => alert('Closing does not work in Storybook'), 28 | onClickActionButton: () => alert('The user confirmed the remove.'), 29 | acceptText: 'Remove', 30 | acceptType: 'danger', 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /src/stories/Generic/Banner.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Banner } from '../../renderer/Generics/redesign/Banner/Banner'; 4 | 5 | export default { 6 | title: 'Generic/Banner', 7 | component: Banner, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | updateAvailable: true, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/stories/Generic/Bubble.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Bubble } from '../../renderer/Generics/redesign/Bubble/Bubble'; 4 | 5 | export default { 6 | title: 'Generic/Bubble', 7 | component: Bubble, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | count: 23, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/stories/Generic/Checkbox.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Checkbox } from '../../renderer/Generics/redesign/Checkbox/Checkbox'; 4 | 5 | export default { 6 | title: 'Generic/Checkbox', 7 | component: Checkbox, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: {}, 15 | }; 16 | -------------------------------------------------------------------------------- /src/stories/Generic/ClientCard.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { ClientCard } from '../../renderer/Generics/redesign/ClientCard/ClientCard'; 4 | 5 | export default { 6 | title: 'Generic/ClientCard', 7 | component: ClientCard, 8 | } as Meta; 9 | 10 | export const Nethermind = { 11 | args: { 12 | name: 'erigon', 13 | version: 'v10', 14 | nodeType: 'execution', 15 | status: { 16 | updating: false, 17 | initialized: true, 18 | lowPeerCount: false, 19 | synchronized: true, 20 | updateAvailable: true, 21 | blocksBehind: false, 22 | noConnection: false, 23 | stopped: false, 24 | error: false, 25 | }, 26 | stats: { 27 | peers: 16, 28 | currentSlot: 90, 29 | highestSlot: 190, 30 | cpuLoad: 82, 31 | diskUsageGBs: 5000, 32 | }, 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /src/stories/Generic/ContentHeader.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { ContentHeader } from '../../renderer/Generics/redesign/ContentHeader/ContentHeader'; 4 | 5 | export default { 6 | title: 'Generic/ContentHeader', 7 | component: ContentHeader, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | title: 'Title', 16 | subtitle: 'Subtitle', 17 | leftButtonIconId: 'left', 18 | rightButtonIconId: 'close', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /src/stories/Generic/ExternalLink.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import ExternalLink from '../../renderer/Generics/redesign/Link/ExternalLink'; 4 | 5 | export default { 6 | title: 'Generic/ExternalLink', 7 | component: ExternalLink, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | text: 'Docker Install Guide', 13 | url: 'https://docs.docker.com/desktop/#download-and-install', 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /src/stories/Generic/Header.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Header } from '../../renderer/Generics/redesign/Header/Header'; 4 | 5 | export default { 6 | title: 'Generic/Header', 7 | component: Header, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | nodeOverview: { 13 | name: 'besu', 14 | title: 'Ethereum node', 15 | info: 'Non-Validating Node — Ethereum mainnet', 16 | screenType: 'nodePackage', 17 | rpcTranslation: 'eth-l1', 18 | status: { 19 | updating: false, 20 | initialized: true, 21 | synchronized: true, 22 | lowPeerCount: true, 23 | updateAvailable: true, 24 | blocksBehind: false, 25 | noConnection: false, 26 | stopped: false, 27 | error: false, 28 | }, 29 | stats: { 30 | currentSlot: 90, 31 | highestSlot: 190, 32 | cpuLoad: 90, 33 | diskUsageGBs: 10000, 34 | }, 35 | }, 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /src/stories/Generic/HeaderButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { HeaderButton } from '../../renderer/Generics/redesign/HeaderButton/HeaderButton'; 4 | 5 | export default { 6 | title: 'Generic/HeaderButton', 7 | component: HeaderButton, 8 | } as Meta; 9 | 10 | export const Close = { 11 | args: { 12 | type: 'close', 13 | onClick: () => { 14 | console.log('close!'); 15 | }, 16 | }, 17 | }; 18 | 19 | export const Left = { 20 | args: { 21 | type: 'left', 22 | onClick: () => { 23 | console.log('left!'); 24 | }, 25 | }, 26 | }; 27 | 28 | export const Filter = { 29 | args: { 30 | type: 'filter', 31 | onClick: () => { 32 | console.log('filter!'); 33 | }, 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/stories/Generic/HeaderMetrics.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { HeaderMetrics } from '../../renderer/Generics/redesign/HeaderMetrics/HeaderMetrics'; 4 | 5 | export default { 6 | title: 'Generic/HeaderMetrics', 7 | component: HeaderMetrics, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | name: 'besu', 13 | title: 'Ethereum node', 14 | info: 'Non-Validating Node — Ethereum mainnet', 15 | screenType: 'nodePackage', 16 | status: { 17 | updating: false, 18 | initialized: true, 19 | synchronized: true, 20 | lowPeerCount: true, 21 | updateAvailable: true, 22 | blocksBehind: false, 23 | noConnection: false, 24 | stopped: false, 25 | error: false, 26 | }, 27 | stats: { 28 | currentSlot: 90, 29 | highestSlot: 190, 30 | cpuLoad: 90, 31 | diskUsageGBs: 10000, 32 | }, 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /src/stories/Generic/InternalLink.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import InternalLink from '../../renderer/Generics/redesign/Link/InternalLink'; 4 | 5 | export default { 6 | title: 'Generic/InternalLink', 7 | component: InternalLink, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | text: 'Docker Install Guide', 13 | onClick: () => alert('Click!'), 14 | }, 15 | }; 16 | 17 | export const Danger = { 18 | args: { 19 | text: 'Delete this thing', 20 | onClick: () => alert('Click!'), 21 | danger: true, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /src/stories/Generic/Label.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Label } from '../../renderer/Generics/redesign/Label/Label'; 4 | 5 | export default { 6 | title: 'Generic/Label', 7 | component: Label, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | label: 'Minority Client', 16 | type: 'pink', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/stories/Generic/Link.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import Link from '../../renderer/Generics/redesign/Link/Linking'; 4 | 5 | export default { 6 | title: 'Generic/Link', 7 | component: Link, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const External = { 14 | args: { 15 | text: 'This is an external link', 16 | url: 'http://google.com', 17 | }, 18 | }; 19 | 20 | export const Internal = { 21 | args: { 22 | text: 'Add Row', 23 | leftIconId: 'add', 24 | }, 25 | }; 26 | 27 | export const Dropdown = { 28 | args: { 29 | text: 'This is a dropdown', 30 | dropdown: true, 31 | }, 32 | }; 33 | 34 | export const Danger = { 35 | args: { 36 | text: 'This will delete the nodes', 37 | danger: true, 38 | }, 39 | }; 40 | 41 | export const Small = { 42 | args: { 43 | text: 'This is so small', 44 | small: true, 45 | }, 46 | }; 47 | -------------------------------------------------------------------------------- /src/stories/Generic/Message.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Message } from '../../renderer/Generics/redesign/Message/Message'; 4 | 5 | export default { 6 | title: 'Generic/Message', 7 | component: Message, 8 | } as Meta; 9 | 10 | export const Info = { 11 | args: { 12 | type: 'info', 13 | title: 'Initial sync process started', 14 | description: 15 | 'When adding a node it first needs to catch up on the history of the network. This process downloads all the necessary data and might take a couple of days. After synchronization is complete your node will be online and part of the network.', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/stories/Generic/MetricTypes.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | import { SYNC_STATUS } from '../../renderer/Generics/redesign/consts'; 3 | 4 | import { MetricTypes } from '../../renderer/Generics/redesign/MetricTypes/MetricTypes'; 5 | 6 | export default { 7 | title: 'Generic/MetricTypes', 8 | component: MetricTypes, 9 | argTypes: { 10 | backgroundColor: { control: 'color' }, 11 | }, 12 | } as Meta; 13 | 14 | export const Status = { 15 | args: { 16 | statsValue: SYNC_STATUS.SYNCHRONIZED, 17 | statsType: 'status', 18 | }, 19 | }; 20 | 21 | export const Stats = { 22 | args: { 23 | statsValue: 100, 24 | statsType: 'diskUsageGBs', 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /src/stories/Generic/Modal.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Modal } from '../../renderer/Generics/redesign/Modal/Modal'; 4 | 5 | export default { 6 | title: 'Generic/Modal', 7 | component: Modal, 8 | } as Meta; 9 | 10 | export const Primary = {}; 11 | -------------------------------------------------------------------------------- /src/stories/Generic/NodeIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import NodeIcon from '../../renderer/Generics/redesign/NodeIcon/NodeIcon'; 4 | 5 | export default { 6 | title: 'Generic/NodeIcon', 7 | component: NodeIcon, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Default = { 14 | args: { 15 | iconId: 'ethereum', 16 | size: 'small', 17 | }, 18 | }; 19 | 20 | export const Small = { 21 | args: { 22 | iconId: 'ethereum', 23 | status: 'online', 24 | size: 'small', 25 | }, 26 | }; 27 | 28 | export const Medium = { 29 | args: { 30 | iconId: 'ethereum', 31 | status: 'warning', 32 | size: 'medium', 33 | }, 34 | }; 35 | 36 | export const Large = { 37 | args: { 38 | iconId: 'ethereum', 39 | status: 'error', 40 | size: 'large', 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /src/stories/Generic/NotificationIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { NotificationIcon } from '../../renderer/Generics/redesign/NotificationIcon/NotificationIcon'; 4 | 5 | export default { 6 | title: 'Generic/NotificationIcon', 7 | component: NotificationIcon, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Unread = { 14 | args: { 15 | status: 'info', 16 | unread: true, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/stories/Generic/NotificationItem.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { NotificationItem } from '../../renderer/Generics/redesign/NotificationItem/NotificationItem'; 4 | 5 | export default { 6 | title: 'Generic/NotificationItem', 7 | component: NotificationItem, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Completed = { 14 | args: { 15 | unread: true, 16 | status: 'completed', 17 | title: 'Client successfuly updated', 18 | description: 'Lodestar consensus client', 19 | timestamp: 1673384953, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /src/stories/Generic/Select.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import Select from '../../renderer/Generics/redesign/Select/Select'; 4 | 5 | export default { 6 | title: 'Generic/Select', 7 | component: Select, 8 | } as Meta; 9 | 10 | export const Single = { 11 | args: { 12 | value: 'dark', 13 | options: [ 14 | { 15 | value: 'auto', 16 | label: 'Auto (Follows computer settings)', 17 | }, 18 | { value: 'light', label: 'Light mode' }, 19 | { value: 'dark', label: 'Dark mode' }, 20 | ], 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/stories/Generic/SidebarLinkItem.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { SidebarLinkItem } from '../../renderer/Generics/redesign/SidebarLinkItem/SidebarLinkItem'; 4 | 5 | export default { 6 | title: 'Generic/SidebarLinkItem', 7 | component: SidebarLinkItem, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Notifications = { 14 | args: { 15 | count: 4, 16 | label: 'Notifications', 17 | iconId: 'bell', 18 | }, 19 | }; 20 | 21 | export const Add = { 22 | args: { 23 | label: 'Add Node', 24 | iconId: 'add', 25 | }, 26 | }; 27 | 28 | export const Preferences = { 29 | args: { 30 | label: 'Preferences', 31 | iconId: 'preferences', 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /src/stories/Generic/SidebarNodeItem.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { SidebarNodeItem } from '../../renderer/Generics/redesign/SidebarNodeItem/SidebarNodeItem'; 4 | 5 | export default { 6 | title: 'Generic/SidebarNodeItem', 7 | component: SidebarNodeItem, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Ethereum = { 14 | args: { 15 | iconId: 'ethereum', 16 | status: 'online', 17 | title: 'Ethereum node', 18 | info: 'Mainnet', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /src/stories/Generic/Splash.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import Splash from '../../renderer/Generics/redesign/Splash/Splash'; 4 | 5 | export default { 6 | title: 'Generic/SplashScreen', 7 | component: Splash, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | title: 'Welcome to NiceNode', 13 | description: 14 | 'Run a node how you want it — without commands and a terminal. NiceNode shows what the node is doing at a glance. Stats like how many peer nodes are connected and synching progress are built into the app.', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /src/stories/Generic/Stepper.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import Stepper from '../../renderer/Generics/redesign/Stepper/Stepper'; 4 | 5 | export default { 6 | title: 'Generic/Stepper', 7 | component: Stepper, 8 | } as Meta; 9 | 10 | export const Primary: StoryObj = { 11 | args: { 12 | onChange: (change) => window.alert(change), 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/stories/Generic/SyncModes.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import SyncModes from '../../renderer/Generics/redesign/SyncModes/SyncModes'; 4 | 5 | export default { 6 | title: 'Generic/SyncModes', 7 | component: SyncModes, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | controlTranslations: [ 16 | { 17 | value: 'snap', 18 | config: '--syncmode snap', 19 | }, 20 | { 21 | value: 'full', 22 | config: '--syncmode full', 23 | }, 24 | { 25 | value: 'archive', 26 | config: '--syncmode full --gcmode archive', 27 | }, 28 | ], 29 | type: 'pink', 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /src/stories/Generic/TabItem.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import TabItem from '../../renderer/Generics/redesign/TabItem/TabItem'; 4 | 5 | export default { 6 | title: 'Generic/TabItem', 7 | component: TabItem, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const TabItemActive = { 14 | args: { 15 | activeTabId: 'Sync', 16 | label: 'Sync', 17 | }, 18 | }; 19 | 20 | export const TabItemIdle = { 21 | args: { 22 | activeTabId: 'Sync', 23 | label: 'CPU', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /src/stories/Generic/Tag.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import Tag from '../../renderer/Generics/redesign/Tag/Tag'; 4 | 5 | export default { 6 | title: 'Generic/Tag', 7 | component: Tag, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | label: 'Minority Client', 16 | type: 'pink', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/stories/Generic/Toggle.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Toggle } from '../../renderer/Generics/redesign/Toggle/Toggle'; 4 | 5 | export default { 6 | title: 'Generic/Toggle', 7 | component: Toggle, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: {}, 15 | }; 16 | -------------------------------------------------------------------------------- /src/stories/Generic/Tooltip.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { Tooltip } from '../../renderer/Generics/redesign/Tooltip/Tooltip'; 4 | 5 | export default { 6 | title: 'Generic/Tooltip', 7 | component: Tooltip, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | } as Meta; 12 | 13 | export const Primary = { 14 | args: { 15 | title: 'Low peer count', 16 | content: 'Try lorem ipsum sit dolor amet.', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/stories/Generic/UpdateCallout.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import { UpdateCallout } from '../../renderer/Generics/redesign/UpdateCallout/UpdateCallout'; 4 | 5 | export default { 6 | title: 'Generic/UpdateCallout', 7 | component: UpdateCallout, 8 | } as Meta; 9 | 10 | export const Single = {}; 11 | -------------------------------------------------------------------------------- /src/stories/Introduction.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/blocks'; 2 | 3 | 4 | 5 | # Welcome NiceNode's UI Component Library 6 | 7 | Storybook helps build and test UI components in isolation from your app's business logic, data, and context. 8 | 9 | 10 | NiceNode Figma 11 | 12 | -------------------------------------------------------------------------------- /src/stories/Presentational/AddEthereumNode.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import AddNodeConfiguration from '../../renderer/Presentational/AddNodeConfiguration/AddNodeConfiguration'; 4 | 5 | export default { 6 | title: 'Presentational/AddNodeConfiguration', 7 | component: AddNodeConfiguration, 8 | } as Meta; 9 | 10 | export const Primary: StoryObj = { 11 | args: { 12 | onChange: (newValue) => console.log(newValue), 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/stories/Presentational/AddNodeStepper.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import AddNodeStepper from '../../renderer/Presentational/AddNodeStepper/AddNodeStepper'; 4 | 5 | export default { 6 | title: 'Presentational/AddNodeStepper', 7 | component: AddNodeStepper, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | onChange: (newValue: string) => console.log(newValue), 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/stories/Presentational/DockerInstallation.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import PodmanInstallation from '../../renderer/Presentational/PodmanInstallation/PodmanInstallation'; 4 | 5 | export default { 6 | title: 'Presentational/PodmanInstallation', 7 | component: PodmanInstallation, 8 | } as Meta; 9 | 10 | export const Primary: StoryObj = { 11 | args: { 12 | onChange: (newValue) => console.log(newValue), 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/stories/Presentational/Preferences.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import Preferences from '../../renderer/Presentational/Preferences/Preferences'; 4 | 5 | export default { 6 | title: 'Presentational/Preferences', 7 | component: Preferences, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | themeSetting: 'dark', 13 | isOpenOnStartup: true, 14 | version: 'v69.69', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /src/stories/Presentational/RemoveNode.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta } from '@storybook/react'; 2 | 3 | import RemoveNode from '../../renderer/Presentational/RemoveNodeModal/RemoveNode'; 4 | 5 | export default { 6 | title: 'Presentational/RemoveNode', 7 | component: RemoveNode, 8 | } as Meta; 9 | 10 | export const Primary = { 11 | args: { 12 | nodeStorageUsedGBs: 100.543, 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/stories/StorybookLanguageSelect.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { useTranslation } from 'react-i18next'; 3 | import Select from '../renderer/Generics/redesign/Select/Select'; 4 | 5 | const StorybookLanguageSelect = () => { 6 | const { i18n } = useTranslation(); 7 | const [sLang, setLang] = useState('en'); 8 | 9 | const onChangeLanguage = async (newLang: any) => { 10 | console.log('language selected: ', newLang.value); 11 | setLang(newLang.value); 12 | i18n.changeLanguage(newLang.value); 13 | }; 14 | 15 | return ( 16 |