waybetter 0.1.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -9
- package/bin/waybetter.mjs +46 -0
- package/build/runtime.mjs +105 -0
- package/cli/buildenv.mjs +130 -0
- package/cli/dev.mjs +97 -0
- package/cli/i18n.mjs +382 -0
- package/cli/manifests.mjs +383 -0
- package/cli/privacy.mjs +768 -0
- package/cli/release.mjs +444 -0
- package/cli/remote.mjs +260 -0
- package/cli/store.mjs +326 -0
- package/cli/strings.mjs +121 -0
- package/dist/runtime/column.d.ts +93 -0
- package/dist/runtime/column.js +451 -0
- package/dist/runtime/column.js.map +1 -0
- package/dist/runtime/commandReport.d.ts +19 -0
- package/dist/runtime/commandReport.js +47 -0
- package/dist/runtime/commandReport.js.map +1 -0
- package/dist/runtime/commands.d.ts +72 -0
- package/dist/runtime/commands.js +214 -0
- package/dist/runtime/commands.js.map +1 -0
- package/dist/runtime/devErrors.d.ts +16 -0
- package/dist/runtime/devErrors.js +30 -0
- package/dist/runtime/devErrors.js.map +1 -0
- package/dist/runtime/domHub.d.ts +21 -0
- package/dist/runtime/domHub.js +139 -4
- package/dist/runtime/domHub.js.map +1 -1
- package/dist/runtime/featureModules.d.ts +157 -0
- package/dist/runtime/featureModules.js +484 -0
- package/dist/runtime/featureModules.js.map +1 -0
- package/dist/runtime/featureTable.d.ts +144 -0
- package/dist/runtime/featureTable.js +223 -0
- package/dist/runtime/featureTable.js.map +1 -0
- package/dist/runtime/fonts.d.ts +22 -0
- package/dist/runtime/fonts.js +72 -0
- package/dist/runtime/fonts.js.map +1 -0
- package/dist/runtime/i18n.d.ts +138 -0
- package/dist/runtime/i18n.js +614 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/i18nCheck.d.ts +30 -0
- package/dist/runtime/i18nCheck.js +224 -0
- package/dist/runtime/i18nCheck.js.map +1 -0
- package/dist/runtime/pageLang.d.ts +8 -0
- package/dist/runtime/pageLang.js +64 -0
- package/dist/runtime/pageLang.js.map +1 -0
- package/dist/runtime/pageStrings.d.ts +35 -0
- package/dist/runtime/pageStrings.js +76 -0
- package/dist/runtime/pageStrings.js.map +1 -0
- package/dist/runtime/panelButton.d.ts +33 -0
- package/dist/runtime/panelButton.js +83 -0
- package/dist/runtime/panelButton.js.map +1 -0
- package/dist/runtime/permissions.d.ts +47 -0
- package/dist/runtime/permissions.js +141 -0
- package/dist/runtime/permissions.js.map +1 -0
- package/dist/runtime/pluginApi.d.ts +51 -2
- package/dist/runtime/pluginApi.js +137 -22
- package/dist/runtime/pluginApi.js.map +1 -1
- package/dist/runtime/pluginI18n.d.ts +29 -0
- package/dist/runtime/pluginI18n.js +119 -0
- package/dist/runtime/pluginI18n.js.map +1 -0
- package/dist/runtime/settingsForm.d.ts +66 -0
- package/dist/runtime/settingsForm.js +114 -0
- package/dist/runtime/settingsForm.js.map +1 -0
- package/dist/runtime/site.d.ts +5 -0
- package/dist/runtime/site.js +1 -1
- package/dist/runtime/site.js.map +1 -1
- package/dist/runtime/siteRuntime.d.ts +144 -0
- package/dist/runtime/siteRuntime.js +175 -0
- package/dist/runtime/siteRuntime.js.map +1 -0
- package/dist/runtime/stringPackHook.d.ts +84 -0
- package/dist/runtime/stringPackHook.js +220 -0
- package/dist/runtime/stringPackHook.js.map +1 -0
- package/dist/runtime/stringPackTranslate.d.ts +59 -0
- package/dist/runtime/stringPackTranslate.js +264 -0
- package/dist/runtime/stringPackTranslate.js.map +1 -0
- package/dist/runtime/stringPacks.d.ts +200 -0
- package/dist/runtime/stringPacks.js +474 -0
- package/dist/runtime/stringPacks.js.map +1 -0
- package/dist/runtime/styles.d.ts +15 -0
- package/dist/runtime/styles.js +81 -0
- package/dist/runtime/styles.js.map +1 -0
- package/dist/runtime/textNet.d.ts +15 -0
- package/dist/runtime/textNet.js +131 -0
- package/dist/runtime/textNet.js.map +1 -0
- package/dist/runtime/themeApi.d.ts +121 -0
- package/dist/runtime/themeApi.js +220 -0
- package/dist/runtime/themeApi.js.map +1 -0
- package/dist/runtime/themeChoice.d.ts +52 -0
- package/dist/runtime/themeChoice.js +69 -0
- package/dist/runtime/themeChoice.js.map +1 -0
- package/dist/runtime/themeComponents.d.ts +435 -0
- package/dist/runtime/themeComponents.js +463 -0
- package/dist/runtime/themeComponents.js.map +1 -0
- package/dist/runtime/themeDecor.d.ts +73 -0
- package/dist/runtime/themeDecor.js +131 -0
- package/dist/runtime/themeDecor.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +11 -0
- package/dist/runtime/themeDoctor.js +51 -0
- package/dist/runtime/themeDoctor.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +130 -0
- package/dist/runtime/themeIcons.js +263 -0
- package/dist/runtime/themeIcons.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +100 -0
- package/dist/runtime/themeRuntime.js +497 -0
- package/dist/runtime/themeRuntime.js.map +1 -0
- package/dist/runtime/themeSchema.d.ts +10 -0
- package/dist/runtime/themeSchema.js +150 -0
- package/dist/runtime/themeSchema.js.map +1 -0
- package/dist/runtime/themeSpec.d.ts +259 -0
- package/dist/runtime/themeSpec.js +439 -0
- package/dist/runtime/themeSpec.js.map +1 -0
- package/dist/runtime/themeTokens.d.ts +12 -0
- package/dist/runtime/themeTokens.js +14 -6
- package/dist/runtime/themeTokens.js.map +1 -1
- package/dist/runtime/themeVariants.d.ts +30 -0
- package/dist/runtime/themeVariants.js +53 -0
- package/dist/runtime/themeVariants.js.map +1 -0
- package/dist/runtime/ui.d.ts +192 -0
- package/dist/runtime/ui.js +926 -0
- package/dist/runtime/ui.js.map +1 -0
- package/dist/shell/InstallDialog.d.ts +40 -0
- package/dist/shell/InstallDialog.js +170 -0
- package/dist/shell/InstallDialog.js.map +1 -0
- package/dist/shell/StoreView.d.ts +66 -0
- package/dist/shell/StoreView.js +103 -0
- package/dist/shell/StoreView.js.map +1 -0
- package/dist/shell/addressModel.js.map +1 -1
- package/dist/shell/chrome.js.map +1 -1
- package/dist/shell/deckModel.d.ts +117 -0
- package/dist/shell/deckModel.js +267 -0
- package/dist/shell/deckModel.js.map +1 -0
- package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
- package/dist/shell/frame/AccountSwitcher.js +243 -0
- package/dist/shell/frame/AccountSwitcher.js.map +1 -0
- package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
- package/dist/shell/frame/AddColumnDialog.js +81 -0
- package/dist/shell/frame/AddColumnDialog.js.map +1 -0
- package/dist/shell/frame/AppMenu.d.ts +21 -0
- package/dist/shell/frame/AppMenu.js +642 -0
- package/dist/shell/frame/AppMenu.js.map +1 -0
- package/dist/shell/frame/CommandPalette.d.ts +7 -0
- package/dist/shell/frame/CommandPalette.js +118 -0
- package/dist/shell/frame/CommandPalette.js.map +1 -0
- package/dist/shell/frame/DeckView.d.ts +13 -0
- package/dist/shell/frame/DeckView.js +287 -0
- package/dist/shell/frame/DeckView.js.map +1 -0
- package/dist/shell/frame/FindBar.d.ts +10 -0
- package/dist/shell/frame/FindBar.js +108 -0
- package/dist/shell/frame/FindBar.js.map +1 -0
- package/dist/shell/frame/MediaPanel.d.ts +8 -0
- package/dist/shell/frame/MediaPanel.js +76 -0
- package/dist/shell/frame/MediaPanel.js.map +1 -0
- package/dist/shell/frame/NewTabPage.d.ts +9 -0
- package/dist/shell/frame/NewTabPage.js +71 -0
- package/dist/shell/frame/NewTabPage.js.map +1 -0
- package/dist/shell/frame/PaneTheme.d.ts +16 -0
- package/dist/shell/frame/PaneTheme.js +67 -0
- package/dist/shell/frame/PaneTheme.js.map +1 -0
- package/dist/shell/frame/ReportDialog.d.ts +3 -0
- package/dist/shell/frame/ReportDialog.js +95 -0
- package/dist/shell/frame/ReportDialog.js.map +1 -0
- package/dist/shell/frame/Shell.d.ts +8 -0
- package/dist/shell/frame/Shell.js +1131 -0
- package/dist/shell/frame/Shell.js.map +1 -0
- package/dist/shell/frame/Titlebar.d.ts +16 -0
- package/dist/shell/frame/Titlebar.js +77 -0
- package/dist/shell/frame/Titlebar.js.map +1 -0
- package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
- package/dist/shell/frame/TitlebarExtras.js +202 -0
- package/dist/shell/frame/TitlebarExtras.js.map +1 -0
- package/dist/shell/frame/WebPanel.d.ts +4 -0
- package/dist/shell/frame/WebPanel.js +182 -0
- package/dist/shell/frame/WebPanel.js.map +1 -0
- package/dist/shell/frame/accountModel.d.ts +49 -0
- package/dist/shell/frame/accountModel.js +67 -0
- package/dist/shell/frame/accountModel.js.map +1 -0
- package/dist/shell/frame/accountSwitcher.css +91 -0
- package/dist/shell/frame/appI18n.d.ts +44 -0
- package/dist/shell/frame/appI18n.js +64 -0
- package/dist/shell/frame/appI18n.js.map +1 -0
- package/dist/shell/frame/appMenu.css +121 -0
- package/dist/shell/frame/backupModel.d.ts +38 -0
- package/dist/shell/frame/backupModel.js +192 -0
- package/dist/shell/frame/backupModel.js.map +1 -0
- package/dist/shell/frame/boot.d.ts +8 -0
- package/dist/shell/frame/boot.js +35 -0
- package/dist/shell/frame/boot.js.map +1 -0
- package/dist/shell/frame/brand.d.ts +1 -0
- package/dist/shell/frame/brand.js +4 -0
- package/dist/shell/frame/brand.js.map +1 -0
- package/dist/shell/frame/bridge.d.ts +35 -0
- package/dist/shell/frame/bridge.js +70 -0
- package/dist/shell/frame/bridge.js.map +1 -0
- package/dist/shell/frame/chromeTheme.d.ts +29 -0
- package/dist/shell/frame/chromeTheme.js +81 -0
- package/dist/shell/frame/chromeTheme.js.map +1 -0
- package/dist/shell/frame/deck.css +209 -0
- package/dist/shell/frame/deckStore.d.ts +89 -0
- package/dist/shell/frame/deckStore.js +239 -0
- package/dist/shell/frame/deckStore.js.map +1 -0
- package/dist/shell/frame/devHost.d.ts +35 -0
- package/dist/shell/frame/devHost.js +80 -0
- package/dist/shell/frame/devHost.js.map +1 -0
- package/dist/shell/frame/devModel.d.ts +7 -0
- package/dist/shell/frame/devModel.js +17 -0
- package/dist/shell/frame/devModel.js.map +1 -0
- package/dist/shell/frame/diag.d.ts +7 -0
- package/dist/shell/frame/diag.js +39 -0
- package/dist/shell/frame/diag.js.map +1 -0
- package/dist/shell/frame/findBar.css +14 -0
- package/dist/shell/frame/frameMessages.d.ts +248 -0
- package/dist/shell/frame/frameMessages.js +252 -0
- package/dist/shell/frame/frameMessages.js.map +1 -0
- package/dist/shell/frame/hooks.d.ts +39 -0
- package/dist/shell/frame/hooks.js +97 -0
- package/dist/shell/frame/hooks.js.map +1 -0
- package/dist/shell/frame/i18n.d.ts +27 -0
- package/dist/shell/frame/i18n.js +66 -0
- package/dist/shell/frame/i18n.js.map +1 -0
- package/dist/shell/frame/iconPack.d.ts +11 -0
- package/dist/shell/frame/iconPack.js +45 -0
- package/dist/shell/frame/iconPack.js.map +1 -0
- package/dist/shell/frame/icons.d.ts +71 -0
- package/dist/shell/frame/icons.js +75 -0
- package/dist/shell/frame/icons.js.map +1 -0
- package/dist/shell/frame/index.d.ts +34 -0
- package/dist/shell/frame/index.js +43 -0
- package/dist/shell/frame/index.js.map +1 -0
- package/dist/shell/frame/language.d.ts +58 -0
- package/dist/shell/frame/language.js +165 -0
- package/dist/shell/frame/language.js.map +1 -0
- package/dist/shell/frame/mediaModel.d.ts +34 -0
- package/dist/shell/frame/mediaModel.js +53 -0
- package/dist/shell/frame/mediaModel.js.map +1 -0
- package/dist/shell/frame/menuMessages.en.json +54 -0
- package/dist/shell/frame/menuModel.d.ts +277 -0
- package/dist/shell/frame/menuModel.js +293 -0
- package/dist/shell/frame/menuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.d.ts +139 -0
- package/dist/shell/frame/paletteModel.js +112 -0
- package/dist/shell/frame/paletteModel.js.map +1 -0
- package/dist/shell/frame/paneTheme.css +9 -0
- package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
- package/dist/shell/frame/pluginCommandStore.js +70 -0
- package/dist/shell/frame/pluginCommandStore.js.map +1 -0
- package/dist/shell/frame/reportModel.d.ts +52 -0
- package/dist/shell/frame/reportModel.js +105 -0
- package/dist/shell/frame/reportModel.js.map +1 -0
- package/dist/shell/frame/safeStore.d.ts +7 -0
- package/dist/shell/frame/safeStore.js +40 -0
- package/dist/shell/frame/safeStore.js.map +1 -0
- package/dist/shell/frame/searchInput.d.ts +2 -0
- package/dist/shell/frame/searchInput.js +11 -0
- package/dist/shell/frame/searchInput.js.map +1 -0
- package/dist/shell/frame/shell.css +629 -0
- package/dist/shell/frame/site.d.ts +206 -0
- package/dist/shell/frame/site.js +22 -0
- package/dist/shell/frame/site.js.map +1 -0
- package/dist/shell/frame/state.d.ts +99 -0
- package/dist/shell/frame/state.js +284 -0
- package/dist/shell/frame/state.js.map +1 -0
- package/dist/shell/frame/syncGate.d.ts +10 -0
- package/dist/shell/frame/syncGate.js +36 -0
- package/dist/shell/frame/syncGate.js.map +1 -0
- package/dist/shell/frame/syncHost.d.ts +35 -0
- package/dist/shell/frame/syncHost.js +85 -0
- package/dist/shell/frame/syncHost.js.map +1 -0
- package/dist/shell/frame/tabStill.d.ts +2 -0
- package/dist/shell/frame/tabStill.js +62 -0
- package/dist/shell/frame/tabStill.js.map +1 -0
- package/dist/shell/frame/themeScopes.d.ts +29 -0
- package/dist/shell/frame/themeScopes.js +61 -0
- package/dist/shell/frame/themeScopes.js.map +1 -0
- package/dist/shell/frame/themeStore.d.ts +99 -0
- package/dist/shell/frame/themeStore.js +252 -0
- package/dist/shell/frame/themeStore.js.map +1 -0
- package/dist/shell/frame/windowBinding.d.ts +2 -0
- package/dist/shell/frame/windowBinding.js +7 -0
- package/dist/shell/frame/windowBinding.js.map +1 -0
- package/dist/shell/frame/workspaceModel.d.ts +82 -0
- package/dist/shell/frame/workspaceModel.js +250 -0
- package/dist/shell/frame/workspaceModel.js.map +1 -0
- package/dist/shell/frame/workspaces.css +84 -0
- package/dist/shell/frame/workspaces.d.ts +22 -0
- package/dist/shell/frame/workspaces.js +125 -0
- package/dist/shell/frame/workspaces.js.map +1 -0
- package/dist/shell/frame/zoomStore.d.ts +10 -0
- package/dist/shell/frame/zoomStore.js +65 -0
- package/dist/shell/frame/zoomStore.js.map +1 -0
- package/dist/shell/installController.d.ts +122 -0
- package/dist/shell/installController.js +146 -0
- package/dist/shell/installController.js.map +1 -0
- package/dist/shell/installerMessages.d.ts +30 -0
- package/dist/shell/installerMessages.js +36 -0
- package/dist/shell/installerMessages.js.map +1 -0
- package/dist/shell/linkDrop.js.map +1 -1
- package/dist/shell/messages.d.ts +16 -0
- package/dist/shell/messages.js +27 -0
- package/dist/shell/messages.js.map +1 -0
- package/dist/shell/palette.js.map +1 -1
- package/dist/shell/paneModel.d.ts +22 -0
- package/dist/shell/paneModel.js +24 -1
- package/dist/shell/paneModel.js.map +1 -1
- package/dist/shell/panel/Appearance.d.ts +8 -0
- package/dist/shell/panel/Appearance.js +256 -0
- package/dist/shell/panel/Appearance.js.map +1 -0
- package/dist/shell/panel/BackupPanel.d.ts +5 -0
- package/dist/shell/panel/BackupPanel.js +198 -0
- package/dist/shell/panel/BackupPanel.js.map +1 -0
- package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
- package/dist/shell/panel/DeveloperPanel.js +51 -0
- package/dist/shell/panel/DeveloperPanel.js.map +1 -0
- package/dist/shell/panel/FeatureToggles.d.ts +13 -0
- package/dist/shell/panel/FeatureToggles.js +42 -0
- package/dist/shell/panel/FeatureToggles.js.map +1 -0
- package/dist/shell/panel/Home.d.ts +3 -0
- package/dist/shell/panel/Home.js +23 -0
- package/dist/shell/panel/Home.js.map +1 -0
- package/dist/shell/panel/IconPackInstall.d.ts +15 -0
- package/dist/shell/panel/IconPackInstall.js +41 -0
- package/dist/shell/panel/IconPackInstall.js.map +1 -0
- package/dist/shell/panel/LanguageSettings.d.ts +1 -0
- package/dist/shell/panel/LanguageSettings.js +54 -0
- package/dist/shell/panel/LanguageSettings.js.map +1 -0
- package/dist/shell/panel/MakePanel.d.ts +3 -0
- package/dist/shell/panel/MakePanel.js +237 -0
- package/dist/shell/panel/MakePanel.js.map +1 -0
- package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
- package/dist/shell/panel/MarkdownDoc.js +35 -0
- package/dist/shell/panel/MarkdownDoc.js.map +1 -0
- package/dist/shell/panel/Modes.d.ts +40 -0
- package/dist/shell/panel/Modes.js +270 -0
- package/dist/shell/panel/Modes.js.map +1 -0
- package/dist/shell/panel/NavIcon.d.ts +4 -0
- package/dist/shell/panel/NavIcon.js +6 -0
- package/dist/shell/panel/NavIcon.js.map +1 -0
- package/dist/shell/panel/Panel.d.ts +7 -0
- package/dist/shell/panel/Panel.js +139 -0
- package/dist/shell/panel/Panel.js.map +1 -0
- package/dist/shell/panel/PluginFeatures.d.ts +24 -0
- package/dist/shell/panel/PluginFeatures.js +165 -0
- package/dist/shell/panel/PluginFeatures.js.map +1 -0
- package/dist/shell/panel/Plugins.d.ts +33 -0
- package/dist/shell/panel/Plugins.js +112 -0
- package/dist/shell/panel/Plugins.js.map +1 -0
- package/dist/shell/panel/PowerSettings.d.ts +4 -0
- package/dist/shell/panel/PowerSettings.js +52 -0
- package/dist/shell/panel/PowerSettings.js.map +1 -0
- package/dist/shell/panel/Settings.d.ts +23 -0
- package/dist/shell/panel/Settings.js +116 -0
- package/dist/shell/panel/Settings.js.map +1 -0
- package/dist/shell/panel/ShareSetup.d.ts +8 -0
- package/dist/shell/panel/ShareSetup.js +130 -0
- package/dist/shell/panel/ShareSetup.js.map +1 -0
- package/dist/shell/panel/StoreSection.d.ts +6 -0
- package/dist/shell/panel/StoreSection.js +48 -0
- package/dist/shell/panel/StoreSection.js.map +1 -0
- package/dist/shell/panel/StringPacks.d.ts +11 -0
- package/dist/shell/panel/StringPacks.js +106 -0
- package/dist/shell/panel/StringPacks.js.map +1 -0
- package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
- package/dist/shell/panel/ThemeBuilder.js +205 -0
- package/dist/shell/panel/ThemeBuilder.js.map +1 -0
- package/dist/shell/panel/backup.css +34 -0
- package/dist/shell/panel/builder.css +232 -0
- package/dist/shell/panel/builderModel.d.ts +55 -0
- package/dist/shell/panel/builderModel.js +95 -0
- package/dist/shell/panel/builderModel.js.map +1 -0
- package/dist/shell/panel/compare.d.ts +10 -0
- package/dist/shell/panel/compare.js +51 -0
- package/dist/shell/panel/compare.js.map +1 -0
- package/dist/shell/panel/controls.d.ts +135 -0
- package/dist/shell/panel/controls.js +213 -0
- package/dist/shell/panel/controls.js.map +1 -0
- package/dist/shell/panel/featureModel.d.ts +69 -0
- package/dist/shell/panel/featureModel.js +79 -0
- package/dist/shell/panel/featureModel.js.map +1 -0
- package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
- package/dist/shell/panel/fonts/FontBrowser.js +189 -0
- package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
- package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
- package/dist/shell/panel/fonts/FontRoles.js +77 -0
- package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
- package/dist/shell/panel/fonts/catalog.d.ts +37 -0
- package/dist/shell/panel/fonts/catalog.js +68 -0
- package/dist/shell/panel/fonts/catalog.js.map +1 -0
- package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
- package/dist/shell/panel/index.d.ts +20 -0
- package/dist/shell/panel/index.js +34 -0
- package/dist/shell/panel/index.js.map +1 -0
- package/dist/shell/panel/languageModel.d.ts +5 -0
- package/dist/shell/panel/languageModel.js +7 -0
- package/dist/shell/panel/languageModel.js.map +1 -0
- package/dist/shell/panel/make.css +72 -0
- package/dist/shell/panel/makeModel.d.ts +32 -0
- package/dist/shell/panel/makeModel.js +84 -0
- package/dist/shell/panel/makeModel.js.map +1 -0
- package/dist/shell/panel/markdown.d.ts +46 -0
- package/dist/shell/panel/markdown.js +100 -0
- package/dist/shell/panel/markdown.js.map +1 -0
- package/dist/shell/panel/nav.d.ts +12 -0
- package/dist/shell/panel/nav.js +50 -0
- package/dist/shell/panel/nav.js.map +1 -0
- package/dist/shell/panel/panel.css +401 -0
- package/dist/shell/panel/panelMessages.d.ts +763 -0
- package/dist/shell/panel/panelMessages.js +767 -0
- package/dist/shell/panel/panelMessages.js.map +1 -0
- package/dist/shell/panel/plugins.css +59 -0
- package/dist/shell/panel/setupModel.d.ts +87 -0
- package/dist/shell/panel/setupModel.js +152 -0
- package/dist/shell/panel/setupModel.js.map +1 -0
- package/dist/shell/panel/site.d.ts +259 -0
- package/dist/shell/panel/site.js +25 -0
- package/dist/shell/panel/site.js.map +1 -0
- package/dist/shell/panel/strings.css +7 -0
- package/dist/shell/panel/themes.d.ts +10 -0
- package/dist/shell/panel/themes.js +8 -0
- package/dist/shell/panel/themes.js.map +1 -0
- package/dist/shell/profileModel.d.ts +3 -2
- package/dist/shell/profileModel.js +7 -5
- package/dist/shell/profileModel.js.map +1 -1
- package/dist/shell/store.css +230 -0
- package/dist/shell/storeMessages.d.ts +169 -0
- package/dist/shell/storeMessages.js +172 -0
- package/dist/shell/storeMessages.js.map +1 -0
- package/dist/shell/storeModel.d.ts +181 -0
- package/dist/shell/storeModel.js +133 -0
- package/dist/shell/storeModel.js.map +1 -0
- package/dist/shell/stringPacksModel.d.ts +44 -0
- package/dist/shell/stringPacksModel.js +94 -0
- package/dist/shell/stringPacksModel.js.map +1 -0
- package/dist/shell/updateModel.d.ts +2 -1
- package/dist/shell/updateModel.js +5 -4
- package/dist/shell/updateModel.js.map +1 -1
- package/dist/shell/windowControls.d.ts +4 -0
- package/dist/shell/windowControls.js +5 -0
- package/dist/shell/windowControls.js.map +1 -1
- package/i18n-config.schema.json +29 -0
- package/i18n-meta.schema.json +26 -0
- package/i18n.schema.json +42 -0
- package/icons.schema.json +646 -0
- package/languages.schema.json +23 -0
- package/locales/ar-x-fm.json +11 -0
- package/locales/ar.json +1281 -0
- package/locales/bg.json +1280 -0
- package/locales/bn.json +1280 -0
- package/locales/ca.json +1280 -0
- package/locales/cs.json +1280 -0
- package/locales/da.json +1280 -0
- package/locales/de.json +1280 -0
- package/locales/el.json +1280 -0
- package/locales/en-GB.json +27 -0
- package/locales/en.json +1280 -0
- package/locales/en.meta.json +51 -0
- package/locales/es.json +1280 -0
- package/locales/eu.json +1280 -0
- package/locales/fa.json +1281 -0
- package/locales/fi.json +1280 -0
- package/locales/fil.json +1280 -0
- package/locales/fr.json +1280 -0
- package/locales/ga.json +1280 -0
- package/locales/gl.json +1280 -0
- package/locales/gu.json +1280 -0
- package/locales/ha.json +1280 -0
- package/locales/he.json +1281 -0
- package/locales/hi.json +1280 -0
- package/locales/hr.json +1280 -0
- package/locales/hu.json +1279 -0
- package/locales/id.json +1280 -0
- package/locales/ig.json +1280 -0
- package/locales/it.json +1280 -0
- package/locales/ja.json +1280 -0
- package/locales/kn.json +1280 -0
- package/locales/ko.json +1280 -0
- package/locales/mr.json +1280 -0
- package/locales/ms.json +1280 -0
- package/locales/nb.json +1280 -0
- package/locales/nl.json +1280 -0
- package/locales/pl.json +1280 -0
- package/locales/pt.json +1280 -0
- package/locales/ro.json +1280 -0
- package/locales/ru.json +1280 -0
- package/locales/sk.json +1280 -0
- package/locales/sr.json +1280 -0
- package/locales/sv.json +1280 -0
- package/locales/ta.json +1280 -0
- package/locales/th.json +1280 -0
- package/locales/tr.json +1280 -0
- package/locales/uk.json +1280 -0
- package/locales/ur.json +1281 -0
- package/locales/vi.json +1280 -0
- package/locales/yo.json +1280 -0
- package/locales/zh-Hans.json +1280 -0
- package/locales/zh-Hant.json +1280 -0
- package/package.json +148 -6
- package/store-catalog.schema.json +65 -0
- package/theme.schema.json +4659 -0
- package/windows/installer.nsi +926 -0
- package/windows/languages/Basque.nsh +28 -0
- package/windows/languages/Catalan.nsh +28 -0
- package/windows/languages/Croatian.nsh +28 -0
- package/windows/languages/Czech.nsh +28 -0
- package/windows/languages/Danish.nsh +28 -0
- package/windows/languages/Finnish.nsh +28 -0
- package/windows/languages/Galician.nsh +28 -0
- package/windows/languages/Greek.nsh +28 -0
- package/windows/languages/Hungarian.nsh +28 -0
- package/windows/languages/Indonesian.nsh +28 -0
- package/windows/languages/Irish.nsh +28 -0
- package/windows/languages/Malay.nsh +28 -0
- package/windows/languages/Polish.nsh +28 -0
- package/windows/languages/Romanian.nsh +28 -0
- package/windows/languages/Serbian.nsh +28 -0
- package/windows/languages/Slovak.nsh +28 -0
- package/windows/languages/Thai.nsh +28 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Settings → Backup & sync: export everything into one `.waybetter` file, import one with a preview
|
|
3
|
+
// and a checkbox per section, and the optional encrypted sync through a folder the owner already
|
|
4
|
+
// syncs (OneDrive, iCloud Drive, Dropbox...). Files, crypto and the key stay native
|
|
5
|
+
// (waybetter-host backup.rs and sync.rs behind the app's `backup_*` and `sync_*` commands); nothing
|
|
6
|
+
// here talks to a server. The sync part shows only with the frame's `sync` feature.
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
|
+
import { ago, diffSections, pickSections } from "../frame/backupModel.js";
|
|
9
|
+
import { invoke } from "../frame/bridge.js";
|
|
10
|
+
import { replaceDecks } from "../frame/deckStore.js";
|
|
11
|
+
import { useSync, useT } from "../frame/hooks.js";
|
|
12
|
+
import { formatDate } from "../frame/i18n.js";
|
|
13
|
+
import { hasFeature } from "../frame/site.js";
|
|
14
|
+
import { setProfiles } from "../frame/state.js";
|
|
15
|
+
import { checkNewer, clearNewer, pushNow, refreshSync, setSyncStatus, shellSections } from "../frame/syncHost.js";
|
|
16
|
+
import { loadWorkspaces } from "../frame/workspaces.js";
|
|
17
|
+
import { Badge, Button, InputRow, Row, Section, Toggle } from "./controls.js";
|
|
18
|
+
import { panelSite } from "./site.js";
|
|
19
|
+
import './backup.css';
|
|
20
|
+
const getError = (error) => (error instanceof Error ? error.message : String(error)).replace(/^(BACKUP|SYNC|VALIDATION): /, '');
|
|
21
|
+
/** Tells the rest of the shell that settings changed under it (import, pull). */
|
|
22
|
+
async function refreshAfterImport() {
|
|
23
|
+
await Promise.allSettled([
|
|
24
|
+
panelSite().themes?.store.loadThemes(),
|
|
25
|
+
invoke('profiles_get').then(setProfiles),
|
|
26
|
+
hasFeature('workspaces') ? loadWorkspaces() : undefined,
|
|
27
|
+
]);
|
|
28
|
+
window.dispatchEvent(new CustomEvent('bt-settings-imported'));
|
|
29
|
+
}
|
|
30
|
+
export function BackupPanel({ notify }) {
|
|
31
|
+
const t = useT();
|
|
32
|
+
const [preview, setPreview] = useState(null);
|
|
33
|
+
const sync = useSync();
|
|
34
|
+
// The titlebar chip "Settings from <computer>" opens this section and asks to review that snapshot.
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const onReview = (event) => { const name = event.detail; if (name)
|
|
37
|
+
void review(name); };
|
|
38
|
+
window.addEventListener('bt-sync-review', onReview);
|
|
39
|
+
return () => window.removeEventListener('bt-sync-review', onReview);
|
|
40
|
+
}, []);
|
|
41
|
+
async function review(name) {
|
|
42
|
+
try {
|
|
43
|
+
const sections = await invoke('sync_open', { name });
|
|
44
|
+
const info = syncStateSnapshot(name);
|
|
45
|
+
setPreview({ title: t('wb.backup.fromDevice', { device: info?.deviceName ?? t('wb.backup.anotherComputer') }), subtitle: info ? t('wb.backup.syncedAgo', { when: ago(info.createdAt) }) : t('wb.backup.encryptedSnapshot'), sections, snapshot: name });
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
notify(getError(error), true);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const syncStateSnapshot = (name) => sync.status?.snapshots.find(item => item.name === name) ?? (sync.newer?.name === name ? sync.newer : null);
|
|
52
|
+
if (preview) {
|
|
53
|
+
return _jsx(ImportPreview, { ...preview, notify: notify, onCancel: async () => {
|
|
54
|
+
if (preview.snapshot) {
|
|
55
|
+
await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => { });
|
|
56
|
+
clearNewer();
|
|
57
|
+
}
|
|
58
|
+
setPreview(null);
|
|
59
|
+
}, onDone: async () => {
|
|
60
|
+
if (preview.snapshot) {
|
|
61
|
+
await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => { });
|
|
62
|
+
clearNewer();
|
|
63
|
+
void refreshSync();
|
|
64
|
+
}
|
|
65
|
+
setPreview(null);
|
|
66
|
+
} });
|
|
67
|
+
}
|
|
68
|
+
return _jsxs(_Fragment, { children: [_jsx(ExportSection, { notify: notify, onOpen: (title, subtitle, sections) => setPreview({ title, subtitle, sections }) }), hasFeature('sync') && _jsx(SyncSection, { notify: notify, onReview: review })] });
|
|
69
|
+
}
|
|
70
|
+
function ExportSection({ notify, onOpen }) {
|
|
71
|
+
const t = useT();
|
|
72
|
+
const [drafts, setDrafts] = useState(false);
|
|
73
|
+
const [busy, setBusy] = useState(false);
|
|
74
|
+
async function exportFile() {
|
|
75
|
+
setBusy(true);
|
|
76
|
+
try {
|
|
77
|
+
const path = await invoke('backup_export_file', { includeDrafts: drafts, extra: shellSections() });
|
|
78
|
+
if (path)
|
|
79
|
+
notify(t('wb.backup.saved', { file: path.split(/[\\/]/).pop() ?? path }));
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
notify(getError(error), true);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
setBusy(false);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function importFile() {
|
|
89
|
+
try {
|
|
90
|
+
const opened = await invoke('backup_open_file');
|
|
91
|
+
if (!opened)
|
|
92
|
+
return;
|
|
93
|
+
const when = opened.createdAt ? formatDate(opened.createdAt, { dateStyle: 'medium', timeStyle: 'short' }) : t('wb.backup.unknownDate');
|
|
94
|
+
onOpen(t('wb.backup.importFile', { file: opened.file }), `${t('wb.backup.exportedAt', { when })}${opened.appVersion ? ` · ${panelSite().brand.name} ${opened.appVersion}` : ''}`, opened.sections);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
notify(getError(error), true);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return _jsxs(Section, { title: t('wb.backup.title'), hint: t('wb.backup.hint'), children: [_jsx(Row, { label: t('wb.backup.export'), hint: t('wb.backup.exportHint'), keywords: "backup export save file move computer", wide: true, children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { tone: "primary", disabled: busy, onClick: () => void exportFile(), children: busy ? t('wb.backup.exporting') : t('wb.backup.exportButton') }), _jsxs("label", { className: "btb-check", children: [_jsx("input", { type: "checkbox", checked: drafts, onChange: event => setDrafts(event.target.checked) }), t('wb.backup.includeDrafts')] })] }) }), _jsx(Row, { label: t('wb.backup.import'), hint: t('wb.backup.importHint'), keywords: "restore import load file", children: _jsx(Button, { onClick: () => void importFile(), children: t('wb.backup.importButton') }) })] });
|
|
101
|
+
}
|
|
102
|
+
function ImportPreview({ title, subtitle, sections, notify, onCancel, onDone }) {
|
|
103
|
+
const t = useT();
|
|
104
|
+
const [rows, setRows] = useState(null);
|
|
105
|
+
const [chosen, setChosen] = useState(new Set());
|
|
106
|
+
const [busy, setBusy] = useState(false);
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
let alive = true;
|
|
109
|
+
invoke('backup_collect', { includeDrafts: false })
|
|
110
|
+
.catch(() => ({}))
|
|
111
|
+
.then(current => {
|
|
112
|
+
if (!alive)
|
|
113
|
+
return;
|
|
114
|
+
const next = diffSections({ ...current, ...shellSections() }, sections);
|
|
115
|
+
setRows(next);
|
|
116
|
+
setChosen(new Set(next.filter(row => row.checked).map(row => row.section)));
|
|
117
|
+
});
|
|
118
|
+
return () => { alive = false; };
|
|
119
|
+
}, [sections]);
|
|
120
|
+
async function apply() {
|
|
121
|
+
const { native, local } = pickSections(sections, chosen);
|
|
122
|
+
setBusy(true);
|
|
123
|
+
try {
|
|
124
|
+
const result = Object.keys(native).length ? await invoke('backup_apply', { sections: native }) : { applied: [], notes: [] };
|
|
125
|
+
const decks = local.decks;
|
|
126
|
+
if (decks)
|
|
127
|
+
replaceDecks(decks.decks, decks.settings);
|
|
128
|
+
await refreshAfterImport();
|
|
129
|
+
const count = result.applied.length + (decks ? 1 : 0);
|
|
130
|
+
notify([t('wb.backup.applied', { count }), ...result.notes].join(' '));
|
|
131
|
+
onDone();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
notify(getError(error), true);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
setBusy(false);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const toggle = (section, on) => setChosen(previous => { const next = new Set(previous); if (on)
|
|
141
|
+
next.add(section);
|
|
142
|
+
else
|
|
143
|
+
next.delete(section); return next; });
|
|
144
|
+
return _jsxs(Section, { title: title, hint: subtitle, action: _jsx(Button, { tone: "ghost", size: "sm", onClick: onCancel, children: t('wb.common.cancel') }), children: [!rows && _jsx("div", { className: "btb-loading", children: t('wb.backup.comparing') }), rows && rows.length === 0 && _jsx("div", { className: "btb-loading", children: t('wb.backup.noKnown') }), rows && rows.map(row => _jsxs("label", { className: `btb-row is-${row.status}`, children: [_jsx("input", { type: "checkbox", checked: chosen.has(row.section), onChange: event => toggle(row.section, event.target.checked), "aria-label": t('wb.backup.applySection', { section: row.label }) }), _jsxs("span", { className: "btb-row-body", children: [_jsxs("span", { className: "btb-row-title", children: [row.label, row.status === 'same' ? _jsx(Badge, { children: t('wb.backup.status.same') }) : row.status === 'new' ? _jsx(Badge, { tone: "accent", children: t('wb.backup.status.new') }) : _jsx(Badge, { tone: "warn", children: t('wb.backup.status.changes') })] }), row.details.map((line, index) => _jsx("span", { className: "btb-row-line", children: line }, index))] })] }, row.section)), rows && rows.length > 0 && _jsxs("div", { className: "btb-actions", children: [_jsx("span", { className: "btb-actions-note", children: t('wb.backup.chosen', { count: chosen.size, total: rows.length }) }), _jsx(Button, { tone: "primary", disabled: busy || chosen.size === 0, onClick: () => void apply(), children: busy ? t('wb.backup.applying') : t('wb.backup.applySelected') })] })] });
|
|
145
|
+
}
|
|
146
|
+
function SyncSection({ notify, onReview }) {
|
|
147
|
+
const t = useT();
|
|
148
|
+
const sync = useSync();
|
|
149
|
+
const status = sync.status;
|
|
150
|
+
const [passphrase, setPassphrase] = useState('');
|
|
151
|
+
const [confirm, setConfirm] = useState('');
|
|
152
|
+
const [remember, setRemember] = useState(true);
|
|
153
|
+
const [busy, setBusy] = useState(null);
|
|
154
|
+
const [deviceName, setDeviceName] = useState('');
|
|
155
|
+
useEffect(() => { if (!status)
|
|
156
|
+
void refreshSync(); }, []);
|
|
157
|
+
useEffect(() => { if (status)
|
|
158
|
+
setDeviceName(status.deviceName); }, [status?.deviceName]);
|
|
159
|
+
async function act(label, action, done) {
|
|
160
|
+
setBusy(label);
|
|
161
|
+
try {
|
|
162
|
+
const result = await action();
|
|
163
|
+
if (result && typeof result === 'object' && 'device' in result)
|
|
164
|
+
setSyncStatus(result);
|
|
165
|
+
if (done)
|
|
166
|
+
notify(done);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
notify(getError(error), true);
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
setBusy(null);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const hint = t('wb.sync.hint');
|
|
176
|
+
const title = t('wb.sync.title');
|
|
177
|
+
if (!status)
|
|
178
|
+
return _jsx(Section, { title: title, hint: hint, children: _jsx("div", { className: "btb-loading", children: t('wb.common.loading') }) });
|
|
179
|
+
if (!status.folder) {
|
|
180
|
+
return _jsx(Section, { title: title, hint: hint, children: _jsx(Row, { label: t('wb.sync.folder'), hint: t('wb.sync.folderHint'), keywords: "sync cloud onedrive icloud dropbox folder encrypted", children: _jsx(Button, { tone: "primary", onClick: () => void act('folder', () => invoke('sync_choose_folder')), children: t('wb.sync.chooseFolder') }) }) });
|
|
181
|
+
}
|
|
182
|
+
const folderRow = _jsx(Row, { label: t('wb.sync.folder'), hint: _jsx("span", { className: "btb-path", title: status.folder, children: status.folder }), keywords: "sync folder change stop", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => void act('folder', () => invoke('sync_choose_folder')), children: t('wb.sync.change') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void act('disable', () => invoke('sync_disable'), t('wb.sync.stopped')), children: t('wb.sync.stop') })] }) });
|
|
183
|
+
if (!status.unlocked) {
|
|
184
|
+
const creating = !status.initialized;
|
|
185
|
+
const mismatch = creating && confirm.length > 0 && confirm !== passphrase;
|
|
186
|
+
const ready = passphrase.length >= 8 && (!creating || confirm === passphrase);
|
|
187
|
+
return _jsxs(Section, { title: title, hint: hint, children: [folderRow, status.error && _jsx(Row, { label: t('wb.sync.problem'), hint: status.error }), _jsx(Row, { label: creating ? t('wb.sync.choosePass') : t('wb.sync.unlockPass'), hint: creating ? t('wb.sync.choosePassHint') : t('wb.sync.unlockPassHint'), keywords: "passphrase password unlock encrypt", wide: true, children: _jsxs("form", { className: "btb-pass", onSubmit: event => { event.preventDefault(); if (ready)
|
|
188
|
+
void act('unlock', () => invoke('sync_unlock', { passphrase, remember }).then(result => { setPassphrase(''); setConfirm(''); return result; }), creating ? t('wb.sync.setUpDone') : t('wb.sync.unlocked')); }, children: [_jsx("input", { className: "bt-input", type: "password", autoComplete: "new-password", placeholder: t('wb.sync.passphrase'), "aria-label": t('wb.sync.passphraseLabel'), value: passphrase, onChange: event => setPassphrase(event.target.value) }), creating && _jsx("input", { className: "bt-input", type: "password", autoComplete: "new-password", placeholder: t('wb.sync.repeat'), "aria-label": t('wb.sync.repeatLabel'), value: confirm, onChange: event => setConfirm(event.target.value) }), _jsxs("label", { className: "btb-check", children: [_jsx("input", { type: "checkbox", checked: remember, onChange: event => setRemember(event.target.checked) }), t('wb.sync.remember')] }), _jsx(Button, { tone: "primary", type: "submit", disabled: !ready || busy === 'unlock', children: busy === 'unlock' ? t('wb.sync.deriving') : creating ? t('wb.sync.setUp') : t('wb.sync.unlock') }), mismatch && _jsx("span", { className: "btb-error", children: t('wb.sync.differ') })] }) })] });
|
|
189
|
+
}
|
|
190
|
+
const others = status.snapshots.filter(snapshot => snapshot.device !== status.device);
|
|
191
|
+
const mine = status.snapshots.filter(snapshot => snapshot.device === status.device);
|
|
192
|
+
return _jsxs(Section, { title: title, hint: hint, action: _jsx(Badge, { tone: "ok", children: t('wb.sync.on') }), children: [folderRow, _jsx(Row, { label: t('wb.sync.thisComputer'), hint: t('wb.sync.thisComputerHint'), keywords: "device name computer", children: _jsx(InputRow, { label: t('wb.sync.computerName'), value: deviceName, onChange: setDeviceName, button: t('wb.sync.rename'), disabled: !deviceName.trim() || deviceName === status.deviceName, onSubmit: () => void act('name', () => invoke('sync_configure', { autoPush: status.autoPush, deviceName })) }) }), _jsx(Row, { label: t('wb.sync.auto'), hint: t('wb.sync.autoHint'), keywords: "auto push automatic", children: _jsx(Toggle, { label: t('wb.sync.auto'), checked: status.autoPush, onChange: next => void act('auto', () => invoke('sync_configure', { autoPush: next, deviceName: status.deviceName })) }) }), _jsx(Row, { label: t('wb.sync.last'), hint: status.lastPushedAt ? t('wb.sync.lastHint', { when: ago(status.lastPushedAt), count: mine.length }) : t('wb.sync.notYet'), keywords: "sync now push", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", disabled: busy === 'push', onClick: () => void act('push', () => pushNow(true), t('wb.sync.written')), children: busy === 'push' ? t('wb.sync.syncing') : t('wb.sync.now') }), _jsx(Button, { size: "sm", tone: "ghost", disabled: busy === 'check', onClick: () => void act('check', async () => { const newer = await checkNewer(); notify(newer ? t('wb.sync.newerFrom', { device: newer.deviceName }) : t('wb.sync.nothingNewer')); }), children: t('wb.sync.check') })] }) }), _jsx(Row, { label: t('wb.sync.others'), hint: others.length ? t('wb.sync.othersHint') : t('wb.sync.othersEmpty'), keywords: "pull snapshots other computer", wide: true, children: others.length > 0 && _jsx("div", { className: "btb-snapshots", children: others.slice(0, 6).map(snapshot => _jsx(SnapshotRow, { snapshot: snapshot, fresh: snapshot.createdAt > status.lastPulled, onReview: () => onReview(snapshot.name) }, snapshot.name)) }) }), _jsx(Row, { label: t('wb.sync.lock'), hint: status.remembered ? t('wb.sync.lockRemembered') : t('wb.sync.lockSession'), keywords: "lock forget key passphrase", children: _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void act('lock', () => invoke('sync_lock'), t('wb.sync.locked')), children: t('wb.sync.lock') }) })] });
|
|
193
|
+
}
|
|
194
|
+
function SnapshotRow({ snapshot, fresh, onReview }) {
|
|
195
|
+
const t = useT();
|
|
196
|
+
return _jsxs("div", { className: `btb-snapshot${fresh ? ' is-fresh' : ''}`, children: [_jsx("span", { className: "btb-snapshot-device", children: snapshot.deviceName }), _jsxs("span", { className: "btb-snapshot-when", children: [ago(snapshot.createdAt), fresh ? ` · ${t('wb.sync.new')}` : ''] }), _jsx(Button, { size: "sm", tone: fresh ? 'primary' : 'plain', onClick: onReview, children: t('wb.sync.review') })] });
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=BackupPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackupPanel.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/BackupPanel.tsx"],"names":[],"mappings":";AAAA,oGAAoG;AACpG,iGAAiG;AACjG,oFAAoF;AACpF,oGAAoG;AACpG,oFAAoF;AAEpF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAsC,MAAM,sBAAsB,CAAC;AACtJ,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAgB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAe,MAAM,WAAW,CAAC;AACnD,OAAO,cAAc,CAAC;AAGtB,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;AAEzI,iFAAiF;AACjF,KAAK,UAAU,kBAAkB;IAC/B,MAAM,OAAO,CAAC,UAAU,CAAC;QACvB,SAAS,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE;QACtC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;QACxC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS;KACxD,CAAC,CAAC;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,MAAM,EAAsB;IACxD,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgF,IAAI,CAAC,CAAC;IAC5H,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,oGAAoG;IACpG,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,EAAE,GAAG,MAAM,IAAI,GAAI,KAAyC,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpI,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IACtE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,KAAK,UAAU,MAAM,CAAC,IAAY;QAChC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAO,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACrC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,CAAC,2BAA2B,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1P,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;IACpD,CAAC;IACD,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEvJ,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,KAAC,aAAa,OAAK,OAAO,EAAE,MAAM,EAAE,MAAM,EAC/C,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;oBAAC,MAAM,MAAM,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBAAC,UAAU,EAAE,CAAC;gBAAC,CAAC;gBACrH,UAAU,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC,EACD,MAAM,EAAE,KAAK,IAAI,EAAE;gBACjB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;oBAAC,MAAM,MAAM,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBAAC,UAAU,EAAE,CAAC;oBAAC,KAAK,WAAW,EAAE,CAAC;gBAAC,CAAC;gBACzI,UAAU,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC,GAAG,CAAC;IACT,CAAC;IACD,OAAO,8BACL,KAAC,aAAa,IAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,GAAG,EACjH,UAAU,CAAC,MAAM,CAAC,IAAI,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IACtE,CAAC;AACN,CAAC;AAED,SAAS,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAqF;IAC1H,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,KAAK,UAAU,UAAU;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAgB,oBAAoB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;YAClH,IAAI,IAAI;gBAAE,MAAM,CAAC,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;IAChF,CAAC;IACD,KAAK,UAAU,UAAU;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAmF,kBAAkB,CAAC,CAAC;YAClI,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC;YACvI,MAAM,CAAC,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrM,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;IACpD,CAAC;IACD,OAAO,MAAC,OAAO,IAAC,KAAK,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,gBAAgB,CAAC,aACpE,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAC,uCAAuC,EAAC,IAAI,kBACvH,eAAK,SAAS,EAAC,WAAW,aACxB,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,UAAU,EAAE,YAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,GAAU,EACjJ,iBAAO,SAAS,EAAC,WAAW,aAAC,gBAAO,IAAI,EAAC,UAAU,EAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAC,CAAC,CAAC,yBAAyB,CAAC,IAAS,IAC5J,GACF,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAC,0BAA0B,YACrG,KAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,UAAU,EAAE,YAAG,CAAC,CAAC,wBAAwB,CAAC,GAAU,GAC5E,IACE,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAyG;IACnL,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAsB,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IAC7D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,MAAM,CAAO,gBAAgB,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;aACrD,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACjB,IAAI,CAAC,OAAO,CAAC,EAAE;YACd,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,aAAa,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,SAAS,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,KAAK,UAAU,KAAK;QAClB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAyC,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YACpK,MAAM,KAAK,GAAG,KAAK,CAAC,KAA4D,CAAC;YACjF,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACrD,MAAM,kBAAkB,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACvE,MAAM,EAAE,CAAC;QACX,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;IAChF,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,EAAW,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,GAAG,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;;QAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/K,OAAO,MAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,QAAQ,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAU,aACrI,CAAC,IAAI,IAAI,cAAK,SAAS,EAAC,aAAa,YAAE,CAAC,CAAC,qBAAqB,CAAC,GAAO,EACtE,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,cAAK,SAAS,EAAC,aAAa,YAAE,CAAC,CAAC,mBAAmB,CAAC,GAAO,EACxF,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAyB,SAAS,EAAE,cAAc,GAAG,CAAC,MAAM,EAAE,aACrF,gBAAO,IAAI,EAAC,UAAU,EAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAc,CAAC,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,EACzL,gBAAM,SAAS,EAAC,cAAc,aAC5B,gBAAM,SAAS,EAAC,eAAe,aAAE,GAAG,CAAC,KAAK,EACvC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAC,KAAK,cAAE,CAAC,CAAC,uBAAuB,CAAC,GAAS,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,YAAE,CAAC,CAAC,sBAAsB,CAAC,GAAS,CAAC,CAAC,CAAC,KAAC,KAAK,IAAC,IAAI,EAAC,MAAM,YAAE,CAAC,CAAC,0BAA0B,CAAC,GAAS,IAC9M,EACN,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,eAAkB,SAAS,EAAC,cAAc,YAAE,IAAI,IAArC,KAAK,CAAwC,CAAC,IACtF,KAP4B,GAAG,CAAC,OAAO,CAQxC,CAAC,EACR,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,eAAK,SAAS,EAAC,aAAa,aACtD,eAAM,SAAS,EAAC,kBAAkB,YAAE,CAAC,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,GAAQ,EAC7G,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,QAAQ,EAAE,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE,YAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAU,IAC7J,IACE,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAoD;IACzF,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;QAAE,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1D,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,MAAM;QAAE,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAEzF,KAAK,UAAU,GAAG,CAAC,KAAa,EAAE,MAA2C,EAAE,IAAa;QAC1F,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;YAC9B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,QAAQ,IAAK,MAAiB;gBAAE,aAAa,CAAC,MAAoB,CAAC,CAAC;YAChH,IAAI,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;IAC/E,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,YAAE,cAAK,SAAS,EAAC,aAAa,YAAE,CAAC,CAAC,mBAAmB,CAAC,GAAO,GAAU,CAAC;IAC7H,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,YACtC,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,oBAAoB,CAAC,EAAE,QAAQ,EAAC,qDAAqD,YAC5H,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,YAAG,CAAC,CAAC,sBAAsB,CAAC,GAAU,GAC9H,GACE,CAAC;IACb,CAAC;IACD,MAAM,SAAS,GAAG,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,eAAM,SAAS,EAAC,UAAU,EAAC,KAAK,EAAE,MAAM,CAAC,MAAM,YAAG,MAAM,CAAC,MAAM,GAAQ,EAAE,QAAQ,EAAC,yBAAyB,YAClK,eAAK,SAAS,EAAC,WAAW,aACxB,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,YAAG,CAAC,CAAC,gBAAgB,CAAC,GAAU,EACvH,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,YAAG,CAAC,CAAC,cAAc,CAAC,GAAU,IAC/I,GACF,CAAC;IAEP,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;QACrC,MAAM,QAAQ,GAAG,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,UAAU,CAAC;QAC1E,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC;QAC9E,OAAO,MAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,aACrC,SAAS,EACT,MAAM,CAAC,KAAK,IAAI,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,GAAG,EACxE,KAAC,GAAG,IAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,EACtE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,EAC1E,QAAQ,EAAC,oCAAoC,EAAC,IAAI,kBAClD,gBAAM,SAAS,EAAC,UAAU,EAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,KAAK;4BAAE,KAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,aAC9R,gBAAO,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,UAAU,EAAC,YAAY,EAAC,cAAc,EAAC,WAAW,EAAE,CAAC,CAAC,oBAAoB,CAAC,gBAAc,CAAC,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EACjO,QAAQ,IAAI,gBAAO,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,UAAU,EAAC,YAAY,EAAC,cAAc,EAAC,WAAW,EAAE,CAAC,CAAC,gBAAgB,CAAC,gBAAc,CAAC,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EACjO,iBAAO,SAAS,EAAC,WAAW,aAAC,gBAAO,IAAI,EAAC,UAAU,EAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAC,CAAC,CAAC,kBAAkB,CAAC,IAAS,EAC7J,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,IAAI,KAAK,QAAQ,YAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAU,EACrL,QAAQ,IAAI,eAAM,SAAS,EAAC,WAAW,YAAE,CAAC,CAAC,gBAAgB,CAAC,GAAQ,IAChE,GACH,IACE,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;IACpF,OAAO,MAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAC,KAAK,IAAC,IAAI,EAAC,IAAI,YAAE,CAAC,CAAC,YAAY,CAAC,GAAS,aACzF,SAAS,EACV,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,0BAA0B,CAAC,EAAE,QAAQ,EAAC,sBAAsB,YACzG,KAAC,QAAQ,IAAC,KAAK,EAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,UAAU,KAAK,MAAM,CAAC,UAAU,EACnL,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,GAAG,GAC5G,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAAE,QAAQ,EAAC,qBAAqB,YACxF,KAAC,MAAM,IAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,GAChL,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,QAAQ,EAAC,eAAe,YACtL,eAAK,SAAS,EAAC,WAAW,aACxB,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,QAAQ,EAAE,IAAI,KAAK,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,YAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAU,EAC7L,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAG,CAAC,CAAC,eAAe,CAAC,GAAU,IAC3Q,GACF,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,QAAQ,EAAC,+BAA+B,EAAC,IAAI,kBACrJ,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,cAAK,SAAS,EAAC,eAAe,YACjD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAC,WAAW,IAAqB,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAzH,QAAQ,CAAC,IAAI,CAA+G,CAAC,GAC/K,GACF,EACN,KAAC,GAAG,IAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,QAAQ,EAAC,4BAA4B,YACpJ,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,YAAG,CAAC,CAAC,cAAc,CAAC,GAAU,GACxI,IACE,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAgE;IAC9G,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,OAAO,eAAK,SAAS,EAAE,eAAe,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,aAC9D,eAAM,SAAS,EAAC,qBAAqB,YAAE,QAAQ,CAAC,UAAU,GAAQ,EAClE,gBAAM,SAAS,EAAC,mBAAmB,aAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAQ,EAC3G,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,YAAG,CAAC,CAAC,gBAAgB,CAAC,GAAU,IAClG,CAAC;AACT,CAAC","sourcesContent":["// Settings → Backup & sync: export everything into one `.waybetter` file, import one with a preview\n// and a checkbox per section, and the optional encrypted sync through a folder the owner already\n// syncs (OneDrive, iCloud Drive, Dropbox...). Files, crypto and the key stay native\n// (waybetter-host backup.rs and sync.rs behind the app's `backup_*` and `sync_*` commands); nothing\n// here talks to a server. The sync part shows only with the frame's `sync` feature.\n\nimport { useEffect, useState } from 'react';\nimport { ago, diffSections, pickSections, type SectionRow } from '../frame/backupModel.ts';\nimport { invoke } from '../frame/bridge.ts';\nimport { replaceDecks } from '../frame/deckStore.ts';\nimport { useSync, useT } from '../frame/hooks.ts';\nimport { formatDate } from '../frame/i18n.ts';\nimport { hasFeature } from '../frame/site.ts';\nimport { setProfiles } from '../frame/state.ts';\nimport { checkNewer, clearNewer, pushNow, refreshSync, setSyncStatus, shellSections, type SnapshotInfo, type SyncStatus } from '../frame/syncHost.ts';\nimport { loadWorkspaces } from '../frame/workspaces.ts';\nimport { Badge, Button, InputRow, Row, Section, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\nimport './backup.css';\n\ntype Json = Record<string, unknown>;\nconst getError = (error: unknown) => (error instanceof Error ? error.message : String(error)).replace(/^(BACKUP|SYNC|VALIDATION): /, '');\n\n/** Tells the rest of the shell that settings changed under it (import, pull). */\nasync function refreshAfterImport() {\n await Promise.allSettled([\n panelSite().themes?.store.loadThemes(),\n invoke('profiles_get').then(setProfiles),\n hasFeature('workspaces') ? loadWorkspaces() : undefined,\n ]);\n window.dispatchEvent(new CustomEvent('bt-settings-imported'));\n}\n\nexport function BackupPanel({ notify }: { notify: Notify }) {\n const t = useT();\n const [preview, setPreview] = useState<{ title: string; subtitle: string; sections: Json; snapshot?: string } | null>(null);\n const sync = useSync();\n\n // The titlebar chip \"Settings from <computer>\" opens this section and asks to review that snapshot.\n useEffect(() => {\n const onReview = (event: Event) => { const name = (event as CustomEvent<string | undefined>).detail; if (name) void review(name); };\n window.addEventListener('bt-sync-review', onReview);\n return () => window.removeEventListener('bt-sync-review', onReview);\n }, []);\n\n async function review(name: string) {\n try {\n const sections = await invoke<Json>('sync_open', { name });\n const info = syncStateSnapshot(name);\n setPreview({ title: t('wb.backup.fromDevice', { device: info?.deviceName ?? t('wb.backup.anotherComputer') }), subtitle: info ? t('wb.backup.syncedAgo', { when: ago(info.createdAt) }) : t('wb.backup.encryptedSnapshot'), sections, snapshot: name });\n } catch (error) { notify(getError(error), true); }\n }\n const syncStateSnapshot = (name: string) => sync.status?.snapshots.find(item => item.name === name) ?? (sync.newer?.name === name ? sync.newer : null);\n\n if (preview) {\n return <ImportPreview {...preview} notify={notify}\n onCancel={async () => {\n if (preview.snapshot) { await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => {}); clearNewer(); }\n setPreview(null);\n }}\n onDone={async () => {\n if (preview.snapshot) { await invoke('sync_mark_pulled', { name: preview.snapshot }).catch(() => {}); clearNewer(); void refreshSync(); }\n setPreview(null);\n }}/>;\n }\n return <>\n <ExportSection notify={notify} onOpen={(title, subtitle, sections) => setPreview({ title, subtitle, sections })}/>\n {hasFeature('sync') && <SyncSection notify={notify} onReview={review}/>}\n </>;\n}\n\nfunction ExportSection({ notify, onOpen }: { notify: Notify; onOpen(title: string, subtitle: string, sections: Json): void }) {\n const t = useT();\n const [drafts, setDrafts] = useState(false);\n const [busy, setBusy] = useState(false);\n async function exportFile() {\n setBusy(true);\n try {\n const path = await invoke<string | null>('backup_export_file', { includeDrafts: drafts, extra: shellSections() });\n if (path) notify(t('wb.backup.saved', { file: path.split(/[\\\\/]/).pop() ?? path }));\n } catch (error) { notify(getError(error), true); } finally { setBusy(false); }\n }\n async function importFile() {\n try {\n const opened = await invoke<{ file: string; createdAt?: string; appVersion?: string; sections: Json } | null>('backup_open_file');\n if (!opened) return;\n const when = opened.createdAt ? formatDate(opened.createdAt, { dateStyle: 'medium', timeStyle: 'short' }) : t('wb.backup.unknownDate');\n onOpen(t('wb.backup.importFile', { file: opened.file }), `${t('wb.backup.exportedAt', { when })}${opened.appVersion ? ` · ${panelSite().brand.name} ${opened.appVersion}` : ''}`, opened.sections);\n } catch (error) { notify(getError(error), true); }\n }\n return <Section title={t('wb.backup.title')} hint={t('wb.backup.hint')}>\n <Row label={t('wb.backup.export')} hint={t('wb.backup.exportHint')} keywords=\"backup export save file move computer\" wide>\n <div className=\"bt-inline\">\n <Button tone=\"primary\" disabled={busy} onClick={() => void exportFile()}>{busy ? t('wb.backup.exporting') : t('wb.backup.exportButton')}</Button>\n <label className=\"btb-check\"><input type=\"checkbox\" checked={drafts} onChange={event => setDrafts(event.target.checked)}/>{t('wb.backup.includeDrafts')}</label>\n </div>\n </Row>\n <Row label={t('wb.backup.import')} hint={t('wb.backup.importHint')} keywords=\"restore import load file\" >\n <Button onClick={() => void importFile()}>{t('wb.backup.importButton')}</Button>\n </Row>\n </Section>;\n}\n\nfunction ImportPreview({ title, subtitle, sections, notify, onCancel, onDone }: { title: string; subtitle: string; sections: Json; notify: Notify; onCancel(): void; onDone(): void }) {\n const t = useT();\n const [rows, setRows] = useState<SectionRow[] | null>(null);\n const [chosen, setChosen] = useState<Set<string>>(new Set());\n const [busy, setBusy] = useState(false);\n useEffect(() => {\n let alive = true;\n invoke<Json>('backup_collect', { includeDrafts: false })\n .catch(() => ({}))\n .then(current => {\n if (!alive) return;\n const next = diffSections({ ...current, ...shellSections() }, sections);\n setRows(next);\n setChosen(new Set(next.filter(row => row.checked).map(row => row.section)));\n });\n return () => { alive = false; };\n }, [sections]);\n\n async function apply() {\n const { native, local } = pickSections(sections, chosen);\n setBusy(true);\n try {\n const result = Object.keys(native).length ? await invoke<{ applied: string[]; notes: string[] }>('backup_apply', { sections: native }) : { applied: [], notes: [] };\n const decks = local.decks as { decks?: unknown; settings?: unknown } | undefined;\n if (decks) replaceDecks(decks.decks, decks.settings);\n await refreshAfterImport();\n const count = result.applied.length + (decks ? 1 : 0);\n notify([t('wb.backup.applied', { count }), ...result.notes].join(' '));\n onDone();\n } catch (error) { notify(getError(error), true); } finally { setBusy(false); }\n }\n\n const toggle = (section: string, on: boolean) => setChosen(previous => { const next = new Set(previous); if (on) next.add(section); else next.delete(section); return next; });\n return <Section title={title} hint={subtitle} action={<Button tone=\"ghost\" size=\"sm\" onClick={onCancel}>{t('wb.common.cancel')}</Button>}>\n {!rows && <div className=\"btb-loading\">{t('wb.backup.comparing')}</div>}\n {rows && rows.length === 0 && <div className=\"btb-loading\">{t('wb.backup.noKnown')}</div>}\n {rows && rows.map(row => <label key={row.section} className={`btb-row is-${row.status}`}>\n <input type=\"checkbox\" checked={chosen.has(row.section)} onChange={event => toggle(row.section, event.target.checked)} aria-label={t('wb.backup.applySection', { section: row.label })}/>\n <span className=\"btb-row-body\">\n <span className=\"btb-row-title\">{row.label}\n {row.status === 'same' ? <Badge>{t('wb.backup.status.same')}</Badge> : row.status === 'new' ? <Badge tone=\"accent\">{t('wb.backup.status.new')}</Badge> : <Badge tone=\"warn\">{t('wb.backup.status.changes')}</Badge>}\n </span>\n {row.details.map((line, index) => <span key={index} className=\"btb-row-line\">{line}</span>)}\n </span>\n </label>)}\n {rows && rows.length > 0 && <div className=\"btb-actions\">\n <span className=\"btb-actions-note\">{t('wb.backup.chosen', { count: chosen.size, total: rows.length })}</span>\n <Button tone=\"primary\" disabled={busy || chosen.size === 0} onClick={() => void apply()}>{busy ? t('wb.backup.applying') : t('wb.backup.applySelected')}</Button>\n </div>}\n </Section>;\n}\n\nfunction SyncSection({ notify, onReview }: { notify: Notify; onReview(name: string): void }) {\n const t = useT();\n const sync = useSync();\n const status = sync.status;\n const [passphrase, setPassphrase] = useState('');\n const [confirm, setConfirm] = useState('');\n const [remember, setRemember] = useState(true);\n const [busy, setBusy] = useState<string | null>(null);\n const [deviceName, setDeviceName] = useState('');\n useEffect(() => { if (!status) void refreshSync(); }, []);\n useEffect(() => { if (status) setDeviceName(status.deviceName); }, [status?.deviceName]);\n\n async function act(label: string, action: () => Promise<SyncStatus | unknown>, done?: string) {\n setBusy(label);\n try {\n const result = await action();\n if (result && typeof result === 'object' && 'device' in (result as object)) setSyncStatus(result as SyncStatus);\n if (done) notify(done);\n } catch (error) { notify(getError(error), true); } finally { setBusy(null); }\n }\n\n const hint = t('wb.sync.hint');\n const title = t('wb.sync.title');\n if (!status) return <Section title={title} hint={hint}><div className=\"btb-loading\">{t('wb.common.loading')}</div></Section>;\n if (!status.folder) {\n return <Section title={title} hint={hint}>\n <Row label={t('wb.sync.folder')} hint={t('wb.sync.folderHint')} keywords=\"sync cloud onedrive icloud dropbox folder encrypted\">\n <Button tone=\"primary\" onClick={() => void act('folder', () => invoke('sync_choose_folder'))}>{t('wb.sync.chooseFolder')}</Button>\n </Row>\n </Section>;\n }\n const folderRow = <Row label={t('wb.sync.folder')} hint={<span className=\"btb-path\" title={status.folder}>{status.folder}</span>} keywords=\"sync folder change stop\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => void act('folder', () => invoke('sync_choose_folder'))}>{t('wb.sync.change')}</Button>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void act('disable', () => invoke('sync_disable'), t('wb.sync.stopped'))}>{t('wb.sync.stop')}</Button>\n </div>\n </Row>;\n\n if (!status.unlocked) {\n const creating = !status.initialized;\n const mismatch = creating && confirm.length > 0 && confirm !== passphrase;\n const ready = passphrase.length >= 8 && (!creating || confirm === passphrase);\n return <Section title={title} hint={hint}>\n {folderRow}\n {status.error && <Row label={t('wb.sync.problem')} hint={status.error}/>}\n <Row label={creating ? t('wb.sync.choosePass') : t('wb.sync.unlockPass')}\n hint={creating ? t('wb.sync.choosePassHint') : t('wb.sync.unlockPassHint')}\n keywords=\"passphrase password unlock encrypt\" wide>\n <form className=\"btb-pass\" onSubmit={event => { event.preventDefault(); if (ready) void act('unlock', () => invoke('sync_unlock', { passphrase, remember }).then(result => { setPassphrase(''); setConfirm(''); return result; }), creating ? t('wb.sync.setUpDone') : t('wb.sync.unlocked')); }}>\n <input className=\"bt-input\" type=\"password\" autoComplete=\"new-password\" placeholder={t('wb.sync.passphrase')} aria-label={t('wb.sync.passphraseLabel')} value={passphrase} onChange={event => setPassphrase(event.target.value)}/>\n {creating && <input className=\"bt-input\" type=\"password\" autoComplete=\"new-password\" placeholder={t('wb.sync.repeat')} aria-label={t('wb.sync.repeatLabel')} value={confirm} onChange={event => setConfirm(event.target.value)}/>}\n <label className=\"btb-check\"><input type=\"checkbox\" checked={remember} onChange={event => setRemember(event.target.checked)}/>{t('wb.sync.remember')}</label>\n <Button tone=\"primary\" type=\"submit\" disabled={!ready || busy === 'unlock'}>{busy === 'unlock' ? t('wb.sync.deriving') : creating ? t('wb.sync.setUp') : t('wb.sync.unlock')}</Button>\n {mismatch && <span className=\"btb-error\">{t('wb.sync.differ')}</span>}\n </form>\n </Row>\n </Section>;\n }\n\n const others = status.snapshots.filter(snapshot => snapshot.device !== status.device);\n const mine = status.snapshots.filter(snapshot => snapshot.device === status.device);\n return <Section title={title} hint={hint} action={<Badge tone=\"ok\">{t('wb.sync.on')}</Badge>}>\n {folderRow}\n <Row label={t('wb.sync.thisComputer')} hint={t('wb.sync.thisComputerHint')} keywords=\"device name computer\">\n <InputRow label={t('wb.sync.computerName')} value={deviceName} onChange={setDeviceName} button={t('wb.sync.rename')} disabled={!deviceName.trim() || deviceName === status.deviceName}\n onSubmit={() => void act('name', () => invoke('sync_configure', { autoPush: status.autoPush, deviceName }))}/>\n </Row>\n <Row label={t('wb.sync.auto')} hint={t('wb.sync.autoHint')} keywords=\"auto push automatic\">\n <Toggle label={t('wb.sync.auto')} checked={status.autoPush} onChange={next => void act('auto', () => invoke('sync_configure', { autoPush: next, deviceName: status.deviceName }))}/>\n </Row>\n <Row label={t('wb.sync.last')} hint={status.lastPushedAt ? t('wb.sync.lastHint', { when: ago(status.lastPushedAt), count: mine.length }) : t('wb.sync.notYet')} keywords=\"sync now push\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" disabled={busy === 'push'} onClick={() => void act('push', () => pushNow(true), t('wb.sync.written'))}>{busy === 'push' ? t('wb.sync.syncing') : t('wb.sync.now')}</Button>\n <Button size=\"sm\" tone=\"ghost\" disabled={busy === 'check'} onClick={() => void act('check', async () => { const newer = await checkNewer(); notify(newer ? t('wb.sync.newerFrom', { device: newer.deviceName }) : t('wb.sync.nothingNewer')); })}>{t('wb.sync.check')}</Button>\n </div>\n </Row>\n <Row label={t('wb.sync.others')} hint={others.length ? t('wb.sync.othersHint') : t('wb.sync.othersEmpty')} keywords=\"pull snapshots other computer\" wide>\n {others.length > 0 && <div className=\"btb-snapshots\">\n {others.slice(0, 6).map(snapshot => <SnapshotRow key={snapshot.name} snapshot={snapshot} fresh={snapshot.createdAt > status.lastPulled} onReview={() => onReview(snapshot.name)}/>)}\n </div>}\n </Row>\n <Row label={t('wb.sync.lock')} hint={status.remembered ? t('wb.sync.lockRemembered') : t('wb.sync.lockSession')} keywords=\"lock forget key passphrase\">\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void act('lock', () => invoke('sync_lock'), t('wb.sync.locked'))}>{t('wb.sync.lock')}</Button>\n </Row>\n </Section>;\n}\n\nfunction SnapshotRow({ snapshot, fresh, onReview }: { snapshot: SnapshotInfo; fresh: boolean; onReview(): void }) {\n const t = useT();\n return <div className={`btb-snapshot${fresh ? ' is-fresh' : ''}`}>\n <span className=\"btb-snapshot-device\">{snapshot.deviceName}</span>\n <span className=\"btb-snapshot-when\">{ago(snapshot.createdAt)}{fresh ? ` · ${t('wb.sync.new')}` : ''}</span>\n <Button size=\"sm\" tone={fresh ? 'primary' : 'plain'} onClick={onReview}>{t('wb.sync.review')}</Button>\n </div>;\n}\n\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Settings → Developer: the live-reload developer mode (off by default). Native code watches the
|
|
3
|
+
// plugins folder, custom.css and one theme file (waybetter-host devmode.rs); a saved change reloads
|
|
4
|
+
// in every site tab at once: theme, then custom CSS, then plugins (the old version stopped before
|
|
5
|
+
// the new one starts). Syntax errors are caught here before anything reloads; errors show with
|
|
6
|
+
// file, line and column (this list, the titlebar chip and a toast in the site's tabs).
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
|
+
import { invoke } from "../frame/bridge.js";
|
|
9
|
+
import { setDevEnabled, setDevErrors } from "../frame/devHost.js";
|
|
10
|
+
import { useDev, useT } from "../frame/hooks.js";
|
|
11
|
+
import { Badge, Button, Row, Section, Toggle } from "./controls.js";
|
|
12
|
+
import { panelSite } from "./site.js";
|
|
13
|
+
const getError = (error) => (error instanceof Error ? error.message : String(error)).replace(/^(DEV|VALIDATION): /, '');
|
|
14
|
+
const where = (error) => `${error.file}${error.line ? `:${error.line}${error.column ? `:${error.column}` : ''}` : ''}`;
|
|
15
|
+
export function DeveloperPanel({ notify }) {
|
|
16
|
+
const t = useT();
|
|
17
|
+
const dev = useDev();
|
|
18
|
+
const [status, setStatus] = useState(null);
|
|
19
|
+
const [events, setEvents] = useState([]);
|
|
20
|
+
const apply = (next) => { setStatus(next); setDevEnabled(next.enabled); setDevErrors(next.errors); };
|
|
21
|
+
useEffect(() => { invoke('dev_get').then(apply).catch(() => setStatus(null)); }, []);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const onEvent = (event) => {
|
|
24
|
+
const detail = event.detail;
|
|
25
|
+
if (detail.kind !== 'reloaded')
|
|
26
|
+
return;
|
|
27
|
+
setEvents(previous => [{ text: t('wb.dev.reloaded', { file: detail.file ?? detail.target ?? '' }), at: Date.now() }, ...previous].slice(0, 6));
|
|
28
|
+
};
|
|
29
|
+
window.addEventListener('bt-dev-event', onEvent);
|
|
30
|
+
return () => window.removeEventListener('bt-dev-event', onEvent);
|
|
31
|
+
}, []);
|
|
32
|
+
async function run(action, message) {
|
|
33
|
+
try {
|
|
34
|
+
apply(await action());
|
|
35
|
+
if (message)
|
|
36
|
+
notify(message);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
notify(getError(error), true);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!status)
|
|
43
|
+
return _jsx(Section, { title: t('wb.dev.title'), hint: t('wb.dev.desktopOnly'), children: _jsx("div", { className: "btb-loading", children: t('wb.dev.notAvailable') }) });
|
|
44
|
+
const errors = dev.errors;
|
|
45
|
+
return _jsxs(_Fragment, { children: [_jsxs(Section, { title: t('wb.dev.title'), hint: t('wb.dev.hint'), action: status.enabled ? _jsx(Badge, { tone: "ok", children: t('wb.dev.watching') }) : undefined, children: [_jsx(Row, { label: t('wb.dev.mode'), hint: t('wb.dev.modeHint'), keywords: "developer dev mode live reload hot reload watch", children: _jsx(Toggle, { label: t('wb.dev.mode'), checked: status.enabled, onChange: next => void run(() => invoke('dev_set', { enabled: next }), next ? t('wb.dev.on') : t('wb.dev.off')) }) }), _jsx(Row, { label: t('wb.dev.pluginsFolder'), hint: _jsx("span", { className: "btb-path", title: status.pluginsFolder, children: status.pluginsFolder }), keywords: "plugins folder open", children: _jsx(Button, { size: "sm", onClick: () => void invoke('plugins_open_folder').catch(error => notify(getError(error), true)), children: t('wb.plugins.openFolder') }) }), panelSite().themes && _jsx(Row, { label: t('wb.dev.themeFile'), hint: status.themeFile
|
|
46
|
+
? _jsx("span", { className: "btb-path", title: status.themeFile, children: status.themeFile })
|
|
47
|
+
: t('wb.dev.themeFileHint'), keywords: "theme json file watch preview", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => void run(() => invoke('dev_pick_theme')), children: status.themeFile ? t('wb.sync.change') : t('wb.dev.chooseTheme') }), status.themeFile && _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void run(() => invoke('dev_clear_theme'), t('wb.dev.stoppedTheme')), children: t('wb.dev.stopWatching') })] }) })] }), _jsx(Section, { title: t('wb.dev.errors'), hint: t('wb.dev.errorsHint'), action: errors.length ? _jsx(Badge, { tone: "warn", children: errors.length }) : undefined, children: errors.length === 0
|
|
48
|
+
? _jsx(Row, { label: t('wb.dev.noErrors'), hint: events.length ? events.map(event => event.text).slice(0, 3).join(' · ') : status.enabled ? t('wb.dev.saveToReload') : t('wb.dev.turnOn') })
|
|
49
|
+
: errors.map((error, index) => _jsxs("div", { className: "btd-error", children: [_jsx("code", { className: "btd-where", children: where(error) }), _jsx("span", { className: "btd-message", children: error.message })] }, `${error.file}-${index}`)) })] });
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=DeveloperPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeveloperPanel.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/DeveloperPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings → Developer: the live-reload developer mode (off by default). Native code watches the\n// plugins folder, custom.css and one theme file (waybetter-host devmode.rs); a saved change reloads\n// in every site tab at once: theme, then custom CSS, then plugins (the old version stopped before\n// the new one starts). Syntax errors are caught here before anything reloads; errors show with\n// file, line and column (this list, the titlebar chip and a toast in the site's tabs).\n\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { setDevEnabled, setDevErrors, type DevErrorInfo } from '../frame/devHost.ts';\nimport { useDev, useT } from '../frame/hooks.ts';\nimport { Badge, Button, Row, Section, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\ntype DevStatus = { enabled: boolean; themeFile: string | null; pluginsFolder: string; errors: DevErrorInfo[] };\nconst getError = (error: unknown) => (error instanceof Error ? error.message : String(error)).replace(/^(DEV|VALIDATION): /, '');\nconst where = (error: DevErrorInfo) => `${error.file}${error.line ? `:${error.line}${error.column ? `:${error.column}` : ''}` : ''}`;\n\nexport function DeveloperPanel({ notify }: { notify: Notify }) {\n const t = useT();\n const dev = useDev();\n const [status, setStatus] = useState<DevStatus | null>(null);\n const [events, setEvents] = useState<Array<{ text: string; at: number }>>([]);\n\n const apply = (next: DevStatus) => { setStatus(next); setDevEnabled(next.enabled); setDevErrors(next.errors); };\n useEffect(() => { invoke<DevStatus>('dev_get').then(apply).catch(() => setStatus(null)); }, []);\n useEffect(() => {\n const onEvent = (event: Event) => {\n const detail = (event as CustomEvent<{ kind: string; target?: string; file?: string | null }>).detail;\n if (detail.kind !== 'reloaded') return;\n setEvents(previous => [{ text: t('wb.dev.reloaded', { file: detail.file ?? detail.target ?? '' }), at: Date.now() }, ...previous].slice(0, 6));\n };\n window.addEventListener('bt-dev-event', onEvent);\n return () => window.removeEventListener('bt-dev-event', onEvent);\n }, []);\n\n async function run(action: () => Promise<DevStatus>, message?: string) {\n try { apply(await action()); if (message) notify(message); } catch (error) { notify(getError(error), true); }\n }\n\n if (!status) return <Section title={t('wb.dev.title')} hint={t('wb.dev.desktopOnly')}><div className=\"btb-loading\">{t('wb.dev.notAvailable')}</div></Section>;\n const errors = dev.errors;\n return <>\n <Section title={t('wb.dev.title')} hint={t('wb.dev.hint')}\n action={status.enabled ? <Badge tone=\"ok\">{t('wb.dev.watching')}</Badge> : undefined}>\n <Row label={t('wb.dev.mode')} hint={t('wb.dev.modeHint')} keywords=\"developer dev mode live reload hot reload watch\">\n <Toggle label={t('wb.dev.mode')} checked={status.enabled}\n onChange={next => void run(() => invoke<DevStatus>('dev_set', { enabled: next }), next ? t('wb.dev.on') : t('wb.dev.off'))}/>\n </Row>\n <Row label={t('wb.dev.pluginsFolder')} hint={<span className=\"btb-path\" title={status.pluginsFolder}>{status.pluginsFolder}</span>} keywords=\"plugins folder open\">\n <Button size=\"sm\" onClick={() => void invoke('plugins_open_folder').catch(error => notify(getError(error), true))}>{t('wb.plugins.openFolder')}</Button>\n </Row>\n {panelSite().themes && <Row label={t('wb.dev.themeFile')} hint={status.themeFile\n ? <span className=\"btb-path\" title={status.themeFile}>{status.themeFile}</span>\n : t('wb.dev.themeFileHint')} keywords=\"theme json file watch preview\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => void run(() => invoke<DevStatus>('dev_pick_theme'))}>{status.themeFile ? t('wb.sync.change') : t('wb.dev.chooseTheme')}</Button>\n {status.themeFile && <Button size=\"sm\" tone=\"ghost\" onClick={() => void run(() => invoke<DevStatus>('dev_clear_theme'), t('wb.dev.stoppedTheme'))}>{t('wb.dev.stopWatching')}</Button>}\n </div>\n </Row>}\n </Section>\n <Section title={t('wb.dev.errors')} hint={t('wb.dev.errorsHint')}\n action={errors.length ? <Badge tone=\"warn\">{errors.length}</Badge> : undefined}>\n {errors.length === 0\n ? <Row label={t('wb.dev.noErrors')} hint={events.length ? events.map(event => event.text).slice(0, 3).join(' · ') : status.enabled ? t('wb.dev.saveToReload') : t('wb.dev.turnOn')}/>\n : errors.map((error, index) => <div key={`${error.file}-${index}`} className=\"btd-error\">\n <code className=\"btd-where\">{where(error)}</code>\n <span className=\"btd-message\">{error.message}</span>\n </div>)}\n </Section>\n </>;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FeatureGroup, Notify } from './site.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The saved flags (normalized by the app) and a setter that shows a change at once, saves it and
|
|
4
|
+
* reverts when native code refuses it. Null until loaded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useFeatures<Config extends Record<string, boolean>>(normalize: (value: unknown) => Config, notify: Notify): [Config | null, (patch: Partial<Config>) => Promise<void>];
|
|
7
|
+
/** One section per group, one toggle per flag; flags that are on by default carry a badge. */
|
|
8
|
+
export declare function FeatureGroups<Config extends Record<string, boolean>>({ groups, defaults, features, choose }: {
|
|
9
|
+
groups: readonly FeatureGroup[];
|
|
10
|
+
defaults: Config;
|
|
11
|
+
features: Config;
|
|
12
|
+
choose(patch: Partial<Config>): void | Promise<void>;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Page tweaks as on/off rows: the app's feature flags (booleans the page runtime applies live in
|
|
3
|
+
// every site tab), stored natively (waybetter-host `features_get/set`). The mechanism is the
|
|
4
|
+
// framework's; which flags exist, their groups and their words are the app's: the catalog has
|
|
5
|
+
// `features.group.<group>`, `features.<flag>.label` and `features.<flag>.description`.
|
|
6
|
+
//
|
|
7
|
+
// const [features, choose] = useFeatures(normalizeFeatures, notify);
|
|
8
|
+
// return features && <FeatureGroups groups={FEATURE_GROUPS} defaults={FEATURE_DEFAULTS} features={features} choose={choose}/>;
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
|
+
import { invoke } from "../frame/bridge.js";
|
|
11
|
+
import { useT } from "../frame/hooks.js";
|
|
12
|
+
import { tx } from "../frame/i18n.js";
|
|
13
|
+
import { Badge, Row, Section, Toggle } from "./controls.js";
|
|
14
|
+
const getError = (error) => error instanceof Error ? error.message : String(error);
|
|
15
|
+
/**
|
|
16
|
+
* The saved flags (normalized by the app) and a setter that shows a change at once, saves it and
|
|
17
|
+
* reverts when native code refuses it. Null until loaded.
|
|
18
|
+
*/
|
|
19
|
+
export function useFeatures(normalize, notify) {
|
|
20
|
+
const [features, setFeatures] = useState(null);
|
|
21
|
+
useEffect(() => { invoke('features_get').then(value => setFeatures(normalize(value))).catch(err => notify(getError(err), true)); }, []);
|
|
22
|
+
async function choose(patch) {
|
|
23
|
+
if (!features)
|
|
24
|
+
return;
|
|
25
|
+
const next = { ...features, ...patch };
|
|
26
|
+
setFeatures(next);
|
|
27
|
+
try {
|
|
28
|
+
await invoke('features_set', { features: next });
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
setFeatures(features);
|
|
32
|
+
notify(getError(err), true);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return [features, choose];
|
|
36
|
+
}
|
|
37
|
+
/** One section per group, one toggle per flag; flags that are on by default carry a badge. */
|
|
38
|
+
export function FeatureGroups({ groups, defaults, features, choose }) {
|
|
39
|
+
const t = useT();
|
|
40
|
+
return _jsx(_Fragment, { children: groups.map(group => _jsx(Section, { title: tx(`features.group.${group.id}`), children: group.features.map(feature => _jsx(Row, { label: tx(`features.${feature}.label`), hint: tx(`features.${feature}.description`), keywords: feature, badge: defaults[feature] ? _jsx(Badge, { children: t('wb.features.default') }) : undefined, children: _jsx(Toggle, { label: tx(`features.${feature}.label`), checked: !!features[feature], onChange: next => void choose({ [feature]: next }) }) }, feature)) }, group.id)) });
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=FeatureToggles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureToggles.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/FeatureToggles.tsx"],"names":[],"mappings":"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","sourcesContent":["// Page tweaks as on/off rows: the app's feature flags (booleans the page runtime applies live in\n// every site tab), stored natively (waybetter-host `features_get/set`). The mechanism is the\n// framework's; which flags exist, their groups and their words are the app's: the catalog has\n// `features.group.<group>`, `features.<flag>.label` and `features.<flag>.description`.\n//\n// const [features, choose] = useFeatures(normalizeFeatures, notify);\n// return features && <FeatureGroups groups={FEATURE_GROUPS} defaults={FEATURE_DEFAULTS} features={features} choose={choose}/>;\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { tx } from '../frame/i18n.ts';\nimport { Badge, Row, Section, Toggle } from './controls.tsx';\nimport type { FeatureGroup, Notify } from './site.ts';\n\nconst getError = (error: unknown) => error instanceof Error ? error.message : String(error);\n\n/**\n * The saved flags (normalized by the app) and a setter that shows a change at once, saves it and\n * reverts when native code refuses it. Null until loaded.\n */\nexport function useFeatures<Config extends Record<string, boolean>>(normalize: (value: unknown) => Config, notify: Notify): [Config | null, (patch: Partial<Config>) => Promise<void>] {\n const [features, setFeatures] = useState<Config | null>(null);\n useEffect(() => { invoke<unknown>('features_get').then(value => setFeatures(normalize(value))).catch(err => notify(getError(err), true)); }, []);\n async function choose(patch: Partial<Config>) {\n if (!features) return;\n const next = { ...features, ...patch };\n setFeatures(next);\n try { await invoke('features_set', { features: next }); }\n catch (err) { setFeatures(features); notify(getError(err), true); }\n }\n return [features, choose];\n}\n\n/** One section per group, one toggle per flag; flags that are on by default carry a badge. */\nexport function FeatureGroups<Config extends Record<string, boolean>>({ groups, defaults, features, choose }: {\n groups: readonly FeatureGroup[];\n defaults: Config;\n features: Config;\n choose(patch: Partial<Config>): void | Promise<void>;\n}) {\n const t = useT();\n return <>\n {groups.map(group => <Section key={group.id} title={tx(`features.group.${group.id}`)}>\n {group.features.map(feature => <Row key={feature} label={tx(`features.${feature}.label`)} hint={tx(`features.${feature}.description`)} keywords={feature} badge={defaults[feature] ? <Badge>{t('wb.features.default')}</Badge> : undefined}>\n <Toggle label={tx(`features.${feature}.label`)} checked={!!features[feature]} onChange={next => void choose({ [feature]: next } as Partial<Config>)}/>\n </Row>)}\n </Section>)}\n </>;\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// The panel's home page: the hero (logo, title, version and license chips, two actions), highlight
|
|
3
|
+
// cards that open sections and the About block. The layout is the framework's; the words are the
|
|
4
|
+
// app's (`PanelSite.home`).
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
import { invoke } from "../frame/bridge.js";
|
|
7
|
+
import { useT } from "../frame/hooks.js";
|
|
8
|
+
import { NAV_ICONS, navEntries } from "./nav.js";
|
|
9
|
+
import { NavIcon } from "./NavIcon.js";
|
|
10
|
+
import { panelSite } from "./site.js";
|
|
11
|
+
export function Home({ go }) {
|
|
12
|
+
useT();
|
|
13
|
+
const panel = panelSite();
|
|
14
|
+
const { home, brand } = panel;
|
|
15
|
+
const [version, setVersion] = useState('');
|
|
16
|
+
useEffect(() => { panel.version?.().then(setVersion).catch(() => { }); }, []);
|
|
17
|
+
const entries = navEntries(panel);
|
|
18
|
+
const icon = (section) => entries.find(entry => entry.id === section)?.icon ?? NAV_ICONS[section] ?? NAV_ICONS.home;
|
|
19
|
+
const [before, emphasis, after] = home.title();
|
|
20
|
+
const foot = home.about?.foot;
|
|
21
|
+
return _jsxs("div", { className: "btp-home", children: [_jsxs("section", { className: "btp-hero", children: [_jsx("div", { className: "btp-hero-glow", "aria-hidden": "true" }), _jsx("div", { className: "btp-hero-mark", children: _jsx("img", { src: brand.logo, alt: "", width: 64, height: 64 }) }), _jsxs("p", { className: "btp-hero-kicker", children: [_jsx("span", { className: "btp-hero-name", children: home.kicker.name }), home.kicker.rest] }), _jsxs("h1", { className: "btp-hero-title", children: [before, _jsx("em", { children: emphasis }), after] }), _jsx("p", { className: "btp-hero-lede", children: home.lede() }), _jsxs("div", { className: "btp-hero-chips", children: [version && _jsxs("span", { className: "btp-chip", children: ["v", version] }), (home.chips?.() ?? []).map(chip => _jsx("span", { className: "btp-chip", children: chip }, chip))] }), home.actions && home.actions.length > 0 && _jsx("div", { className: "btp-hero-actions", children: home.actions.map((action, index) => _jsx("button", { className: `btp-btn${index === 0 ? ' is-primary' : ''}`, onClick: () => go(action.section), children: action.label() }, action.section)) })] }), home.highlights && home.highlights.length > 0 && _jsx("div", { className: "btp-highlights", children: home.highlights.map(item => _jsxs("button", { className: "btp-highlight", onClick: () => go(item.section), children: [_jsx(NavIcon, { d: icon(item.section) }), _jsx("strong", { children: item.title() }), _jsx("span", { children: item.text() })] }, item.section)) }), home.about && _jsxs("section", { className: "btp-about", children: [_jsxs("div", { className: "btp-group-head", children: [_jsx("h2", { children: home.about.title() }), _jsx("p", { children: home.about.text() })] }), home.about.layers && _jsx("ol", { className: "btp-layers", children: home.about.layers.map((layer, index) => _jsxs("li", { children: [_jsx("span", { className: "btp-layer-n", children: String(index + 1).padStart(2, '0') }), _jsxs("div", { children: [_jsx("strong", { children: layer.name() }), _jsx("span", { children: layer.text() })] })] }, index)) }), foot && _jsxs("p", { className: "btp-about-foot", children: [foot.text(), " ", _jsx("b", { children: foot.by }), foot.link && _jsxs(_Fragment, { children: [" \u00B7 ", _jsx("button", { className: "btp-link", onClick: () => { invoke('open_external_url', { url: foot.link.url }).catch(() => { }); }, children: foot.link.label })] })] })] })] });
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=Home.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Home.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/Home.tsx"],"names":[],"mappings":"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","sourcesContent":["// The panel's home page: the hero (logo, title, version and license chips, two actions), highlight\n// cards that open sections and the About block. The layout is the framework's; the words are the\n// app's (`PanelSite.home`).\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { NAV_ICONS, navEntries } from './nav.ts';\nimport { NavIcon } from './NavIcon.tsx';\nimport { panelSite, type BuiltinSection } from './site.ts';\n\nexport function Home({ go }: { go(section: string): void }) {\n useT();\n const panel = panelSite();\n const { home, brand } = panel;\n const [version, setVersion] = useState('');\n useEffect(() => { panel.version?.().then(setVersion).catch(() => {}); }, []);\n const entries = navEntries(panel);\n const icon = (section: string) => entries.find(entry => entry.id === section)?.icon ?? NAV_ICONS[section as BuiltinSection] ?? NAV_ICONS.home;\n const [before, emphasis, after] = home.title();\n const foot = home.about?.foot;\n return <div className=\"btp-home\">\n <section className=\"btp-hero\">\n <div className=\"btp-hero-glow\" aria-hidden=\"true\"/>\n <div className=\"btp-hero-mark\"><img src={brand.logo} alt=\"\" width={64} height={64}/></div>\n <p className=\"btp-hero-kicker\"><span className=\"btp-hero-name\">{home.kicker.name}</span>{home.kicker.rest}</p>\n <h1 className=\"btp-hero-title\">{before}<em>{emphasis}</em>{after}</h1>\n <p className=\"btp-hero-lede\">{home.lede()}</p>\n <div className=\"btp-hero-chips\">\n {version && <span className=\"btp-chip\">v{version}</span>}\n {(home.chips?.() ?? []).map(chip => <span key={chip} className=\"btp-chip\">{chip}</span>)}\n </div>\n {home.actions && home.actions.length > 0 && <div className=\"btp-hero-actions\">\n {home.actions.map((action, index) => <button key={action.section} className={`btp-btn${index === 0 ? ' is-primary' : ''}`} onClick={() => go(action.section)}>{action.label()}</button>)}\n </div>}\n </section>\n {home.highlights && home.highlights.length > 0 && <div className=\"btp-highlights\">\n {home.highlights.map(item => <button key={item.section} className=\"btp-highlight\" onClick={() => go(item.section)}>\n <NavIcon d={icon(item.section)}/><strong>{item.title()}</strong><span>{item.text()}</span>\n </button>)}\n </div>}\n {home.about && <section className=\"btp-about\">\n <div className=\"btp-group-head\"><h2>{home.about.title()}</h2>\n <p>{home.about.text()}</p></div>\n {home.about.layers && <ol className=\"btp-layers\">\n {home.about.layers.map((layer, index) => <li key={index}><span className=\"btp-layer-n\">{String(index + 1).padStart(2, '0')}</span><div><strong>{layer.name()}</strong><span>{layer.text()}</span></div></li>)}\n </ol>}\n {foot && <p className=\"btp-about-foot\">{foot.text()} <b>{foot.by}</b>{foot.link && <> · <button className=\"btp-link\" onClick={() => { invoke('open_external_url', { url: foot.link!.url }).catch(() => {}); }}>{foot.link.label}</button></>}</p>}\n </section>}\n </div>;\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type IconPack } from '../../runtime/themeIcons.ts';
|
|
2
|
+
/** The install screen for one parsed pack. */
|
|
3
|
+
export declare function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }: {
|
|
4
|
+
pack: IconPack;
|
|
5
|
+
warnings: string[];
|
|
6
|
+
bytes: number;
|
|
7
|
+
replaces: boolean;
|
|
8
|
+
onInstall(): void;
|
|
9
|
+
onCancel(): void;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
/** The "Import icon pack…" button: reads a picked file and hands the parsed pack (or an error) back. */
|
|
12
|
+
export declare function IconPackImport({ onParsed, onError }: {
|
|
13
|
+
onParsed(pack: IconPack, warnings: string[], bytes: number): void;
|
|
14
|
+
onError(message: string): void;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Importing an icon pack (a `*.icons.json` document) in Appearance: pick or drop the file, see what
|
|
3
|
+
// it is (name, author, licence, source, credits, every glyph, size, "data only") and install it into
|
|
4
|
+
// the theme choice, from where it reaches every site tab and the Icons picker. Nothing installs
|
|
5
|
+
// without this screen; a pack is data (path data, colored layers, small PNGs), never code.
|
|
6
|
+
import { useRef, useState } from 'react';
|
|
7
|
+
import { parseIconPackJson } from "../../runtime/themeIcons.js";
|
|
8
|
+
import { GlyphPaths } from "../frame/iconPack.js";
|
|
9
|
+
import { t } from "../frame/i18n.js";
|
|
10
|
+
import { Button } from "./controls.js";
|
|
11
|
+
const kb = (bytes) => `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
|
12
|
+
/** The install screen for one parsed pack. */
|
|
13
|
+
export function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }) {
|
|
14
|
+
const names = Object.keys(pack.glyphs);
|
|
15
|
+
return _jsx("div", { className: "bt-import wb-ask wb-pack-review", role: "alertdialog", "aria-label": t('wb.appearance.icons.review', { name: pack.name }), children: _jsxs("div", { className: "bt-import-drop", children: [_jsx("strong", { children: t('wb.appearance.icons.review', { name: pack.name }) }), _jsxs("dl", { className: "wb-pack-facts", children: [_jsx("dt", { children: t('wb.appearance.icons.author') }), _jsx("dd", { children: pack.author || '—' }), _jsx("dt", { children: t('wb.appearance.icons.license') }), _jsx("dd", { children: pack.license }), pack.source && _jsxs(_Fragment, { children: [_jsx("dt", { children: t('wb.appearance.icons.source') }), _jsx("dd", { children: pack.source })] }), pack.credits && _jsxs(_Fragment, { children: [_jsx("dt", { children: t('wb.appearance.icons.credits') }), _jsx("dd", { children: pack.credits })] }), _jsx("dt", { children: t('wb.appearance.icons.size') }), _jsx("dd", { children: t('wb.appearance.icons.sizeValue', { count: names.length, size: kb(bytes) }) })] }), _jsx("p", { children: t('wb.appearance.icons.dataOnly') }), _jsx("div", { className: "wb-pack-grid", "aria-hidden": "true", children: names.map(name => _jsx("span", { title: name, children: _jsx("svg", { className: "bt-glyph", viewBox: "0 0 24 24", children: _jsx(GlyphPaths, { glyph: pack.glyphs[name], pack: pack }) }) }, name)) }), warnings.map(warning => _jsx("p", { className: "wb-pack-warning", children: warning }, warning)), replaces && _jsx("p", { children: t('wb.appearance.icons.replaces', { name: pack.name }) }), _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", tone: "primary", onClick: onInstall, children: t('wb.appearance.icons.install') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: onCancel, children: t('wb.common.cancel') })] })] }) });
|
|
16
|
+
}
|
|
17
|
+
/** The "Import icon pack…" button: reads a picked file and hands the parsed pack (or an error) back. */
|
|
18
|
+
export function IconPackImport({ onParsed, onError }) {
|
|
19
|
+
const input = useRef(null);
|
|
20
|
+
const [busy, setBusy] = useState(false);
|
|
21
|
+
async function read(file) {
|
|
22
|
+
if (!file)
|
|
23
|
+
return;
|
|
24
|
+
setBusy(true);
|
|
25
|
+
try {
|
|
26
|
+
const text = await file.text();
|
|
27
|
+
const parsed = parseIconPackJson(text);
|
|
28
|
+
if ('error' in parsed)
|
|
29
|
+
onError(parsed.error);
|
|
30
|
+
else
|
|
31
|
+
onParsed(parsed.pack, parsed.warnings, text.length);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
setBusy(false);
|
|
35
|
+
if (input.current)
|
|
36
|
+
input.current.value = '';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return _jsxs(_Fragment, { children: [_jsx("input", { ref: input, type: "file", accept: ".json,application/json", hidden: true, onChange: event => void read(event.target.files?.[0]) }), _jsx(Button, { size: "sm", tone: "ghost", disabled: busy, onClick: () => input.current?.click(), children: t('wb.appearance.icons.import') })] });
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=IconPackInstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconPackInstall.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/IconPackInstall.tsx"],"names":[],"mappings":"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","sourcesContent":["// Importing an icon pack (a `*.icons.json` document) in Appearance: pick or drop the file, see what\n// it is (name, author, licence, source, credits, every glyph, size, \"data only\") and install it into\n// the theme choice, from where it reaches every site tab and the Icons picker. Nothing installs\n// without this screen; a pack is data (path data, colored layers, small PNGs), never code.\n\nimport { useRef, useState } from 'react';\nimport { parseIconPackJson, type IconPack } from '../../../runtime/src/themeIcons.ts';\nimport { GlyphPaths } from '../frame/iconPack.tsx';\nimport { t } from '../frame/i18n.ts';\nimport { Button } from './controls.tsx';\n\nconst kb = (bytes: number) => `${Math.max(1, Math.round(bytes / 1024))} KB`;\n\n/** The install screen for one parsed pack. */\nexport function IconPackReview({ pack, warnings, bytes, replaces, onInstall, onCancel }: { pack: IconPack; warnings: string[]; bytes: number; replaces: boolean; onInstall(): void; onCancel(): void }) {\n const names = Object.keys(pack.glyphs) as Array<keyof IconPack['glyphs']>;\n return <div className=\"bt-import wb-ask wb-pack-review\" role=\"alertdialog\" aria-label={t('wb.appearance.icons.review', { name: pack.name })}>\n <div className=\"bt-import-drop\">\n <strong>{t('wb.appearance.icons.review', { name: pack.name })}</strong>\n <dl className=\"wb-pack-facts\">\n <dt>{t('wb.appearance.icons.author')}</dt><dd>{pack.author || '—'}</dd>\n <dt>{t('wb.appearance.icons.license')}</dt><dd>{pack.license}</dd>\n {pack.source && <><dt>{t('wb.appearance.icons.source')}</dt><dd>{pack.source}</dd></>}\n {pack.credits && <><dt>{t('wb.appearance.icons.credits')}</dt><dd>{pack.credits}</dd></>}\n <dt>{t('wb.appearance.icons.size')}</dt><dd>{t('wb.appearance.icons.sizeValue', { count: names.length, size: kb(bytes) })}</dd>\n </dl>\n <p>{t('wb.appearance.icons.dataOnly')}</p>\n <div className=\"wb-pack-grid\" aria-hidden=\"true\">\n {names.map(name => <span key={name} title={name}><svg className=\"bt-glyph\" viewBox=\"0 0 24 24\"><GlyphPaths glyph={pack.glyphs[name]!} pack={pack}/></svg></span>)}\n </div>\n {warnings.map(warning => <p key={warning} className=\"wb-pack-warning\">{warning}</p>)}\n {replaces && <p>{t('wb.appearance.icons.replaces', { name: pack.name })}</p>}\n <div className=\"bt-inline\"><Button size=\"sm\" tone=\"primary\" onClick={onInstall}>{t('wb.appearance.icons.install')}</Button><Button size=\"sm\" tone=\"ghost\" onClick={onCancel}>{t('wb.common.cancel')}</Button></div>\n </div>\n </div>;\n}\n\n/** The \"Import icon pack…\" button: reads a picked file and hands the parsed pack (or an error) back. */\nexport function IconPackImport({ onParsed, onError }: { onParsed(pack: IconPack, warnings: string[], bytes: number): void; onError(message: string): void }) {\n const input = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n async function read(file: File | undefined) {\n if (!file) return;\n setBusy(true);\n try {\n const text = await file.text();\n const parsed = parseIconPackJson(text);\n if ('error' in parsed) onError(parsed.error);\n else onParsed(parsed.pack, parsed.warnings, text.length);\n } finally { setBusy(false); if (input.current) input.current.value = ''; }\n }\n return <>\n <input ref={input} type=\"file\" accept=\".json,application/json\" hidden onChange={event => void read(event.target.files?.[0])}/>\n <Button size=\"sm\" tone=\"ghost\" disabled={busy} onClick={() => input.current?.click()}>{t('wb.appearance.icons.import')}</Button>\n </>;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function LanguageSettings(): import("react").JSX.Element;
|