waybetter 0.1.1 → 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.
Files changed (515) hide show
  1. package/README.md +140 -6
  2. package/bin/waybetter.mjs +46 -0
  3. package/build/runtime.mjs +105 -0
  4. package/cli/buildenv.mjs +130 -0
  5. package/cli/dev.mjs +97 -0
  6. package/cli/i18n.mjs +382 -0
  7. package/cli/manifests.mjs +383 -0
  8. package/cli/privacy.mjs +768 -0
  9. package/cli/release.mjs +444 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +326 -0
  12. package/cli/strings.mjs +121 -0
  13. package/dist/runtime/column.d.ts +93 -0
  14. package/dist/runtime/column.js +451 -0
  15. package/dist/runtime/column.js.map +1 -0
  16. package/dist/runtime/commandReport.d.ts +19 -0
  17. package/dist/runtime/commandReport.js +47 -0
  18. package/dist/runtime/commandReport.js.map +1 -0
  19. package/dist/runtime/commands.d.ts +72 -0
  20. package/dist/runtime/commands.js +214 -0
  21. package/dist/runtime/commands.js.map +1 -0
  22. package/dist/runtime/devErrors.d.ts +16 -0
  23. package/dist/runtime/devErrors.js +30 -0
  24. package/dist/runtime/devErrors.js.map +1 -0
  25. package/dist/runtime/domHub.d.ts +21 -0
  26. package/dist/runtime/domHub.js +139 -4
  27. package/dist/runtime/domHub.js.map +1 -1
  28. package/dist/runtime/featureModules.d.ts +157 -0
  29. package/dist/runtime/featureModules.js +484 -0
  30. package/dist/runtime/featureModules.js.map +1 -0
  31. package/dist/runtime/featureTable.d.ts +144 -0
  32. package/dist/runtime/featureTable.js +223 -0
  33. package/dist/runtime/featureTable.js.map +1 -0
  34. package/dist/runtime/fonts.d.ts +22 -0
  35. package/dist/runtime/fonts.js +72 -0
  36. package/dist/runtime/fonts.js.map +1 -0
  37. package/dist/runtime/i18n.d.ts +138 -0
  38. package/dist/runtime/i18n.js +614 -0
  39. package/dist/runtime/i18n.js.map +1 -0
  40. package/dist/runtime/i18nCheck.d.ts +30 -0
  41. package/dist/runtime/i18nCheck.js +224 -0
  42. package/dist/runtime/i18nCheck.js.map +1 -0
  43. package/dist/runtime/pageLang.d.ts +8 -0
  44. package/dist/runtime/pageLang.js +64 -0
  45. package/dist/runtime/pageLang.js.map +1 -0
  46. package/dist/runtime/pageStrings.d.ts +35 -0
  47. package/dist/runtime/pageStrings.js +76 -0
  48. package/dist/runtime/pageStrings.js.map +1 -0
  49. package/dist/runtime/panelButton.d.ts +33 -0
  50. package/dist/runtime/panelButton.js +83 -0
  51. package/dist/runtime/panelButton.js.map +1 -0
  52. package/dist/runtime/permissions.d.ts +47 -0
  53. package/dist/runtime/permissions.js +141 -0
  54. package/dist/runtime/permissions.js.map +1 -0
  55. package/dist/runtime/pluginApi.d.ts +51 -2
  56. package/dist/runtime/pluginApi.js +137 -22
  57. package/dist/runtime/pluginApi.js.map +1 -1
  58. package/dist/runtime/pluginI18n.d.ts +29 -0
  59. package/dist/runtime/pluginI18n.js +119 -0
  60. package/dist/runtime/pluginI18n.js.map +1 -0
  61. package/dist/runtime/settingsForm.d.ts +66 -0
  62. package/dist/runtime/settingsForm.js +114 -0
  63. package/dist/runtime/settingsForm.js.map +1 -0
  64. package/dist/runtime/site.d.ts +5 -0
  65. package/dist/runtime/site.js +1 -1
  66. package/dist/runtime/site.js.map +1 -1
  67. package/dist/runtime/siteRuntime.d.ts +144 -0
  68. package/dist/runtime/siteRuntime.js +175 -0
  69. package/dist/runtime/siteRuntime.js.map +1 -0
  70. package/dist/runtime/stringPackHook.d.ts +84 -0
  71. package/dist/runtime/stringPackHook.js +220 -0
  72. package/dist/runtime/stringPackHook.js.map +1 -0
  73. package/dist/runtime/stringPackTranslate.d.ts +59 -0
  74. package/dist/runtime/stringPackTranslate.js +264 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +200 -0
  77. package/dist/runtime/stringPacks.js +474 -0
  78. package/dist/runtime/stringPacks.js.map +1 -0
  79. package/dist/runtime/styles.d.ts +15 -0
  80. package/dist/runtime/styles.js +81 -0
  81. package/dist/runtime/styles.js.map +1 -0
  82. package/dist/runtime/textNet.d.ts +15 -0
  83. package/dist/runtime/textNet.js +131 -0
  84. package/dist/runtime/textNet.js.map +1 -0
  85. package/dist/runtime/themeApi.d.ts +121 -0
  86. package/dist/runtime/themeApi.js +220 -0
  87. package/dist/runtime/themeApi.js.map +1 -0
  88. package/dist/runtime/themeChoice.d.ts +52 -0
  89. package/dist/runtime/themeChoice.js +69 -0
  90. package/dist/runtime/themeChoice.js.map +1 -0
  91. package/dist/runtime/themeComponents.d.ts +435 -0
  92. package/dist/runtime/themeComponents.js +463 -0
  93. package/dist/runtime/themeComponents.js.map +1 -0
  94. package/dist/runtime/themeDecor.d.ts +73 -0
  95. package/dist/runtime/themeDecor.js +131 -0
  96. package/dist/runtime/themeDecor.js.map +1 -0
  97. package/dist/runtime/themeDoctor.d.ts +11 -0
  98. package/dist/runtime/themeDoctor.js +51 -0
  99. package/dist/runtime/themeDoctor.js.map +1 -0
  100. package/dist/runtime/themeIcons.d.ts +130 -0
  101. package/dist/runtime/themeIcons.js +263 -0
  102. package/dist/runtime/themeIcons.js.map +1 -0
  103. package/dist/runtime/themeRuntime.d.ts +100 -0
  104. package/dist/runtime/themeRuntime.js +497 -0
  105. package/dist/runtime/themeRuntime.js.map +1 -0
  106. package/dist/runtime/themeSchema.d.ts +10 -0
  107. package/dist/runtime/themeSchema.js +150 -0
  108. package/dist/runtime/themeSchema.js.map +1 -0
  109. package/dist/runtime/themeSpec.d.ts +259 -0
  110. package/dist/runtime/themeSpec.js +439 -0
  111. package/dist/runtime/themeSpec.js.map +1 -0
  112. package/dist/runtime/themeTokens.d.ts +12 -0
  113. package/dist/runtime/themeTokens.js +14 -6
  114. package/dist/runtime/themeTokens.js.map +1 -1
  115. package/dist/runtime/themeVariants.d.ts +30 -0
  116. package/dist/runtime/themeVariants.js +53 -0
  117. package/dist/runtime/themeVariants.js.map +1 -0
  118. package/dist/runtime/ui.d.ts +192 -0
  119. package/dist/runtime/ui.js +926 -0
  120. package/dist/runtime/ui.js.map +1 -0
  121. package/dist/shell/InstallDialog.d.ts +40 -0
  122. package/dist/shell/InstallDialog.js +170 -0
  123. package/dist/shell/InstallDialog.js.map +1 -0
  124. package/dist/shell/StoreView.d.ts +66 -0
  125. package/dist/shell/StoreView.js +103 -0
  126. package/dist/shell/StoreView.js.map +1 -0
  127. package/dist/shell/addressModel.js.map +1 -1
  128. package/dist/shell/chrome.js.map +1 -1
  129. package/dist/shell/deckModel.d.ts +117 -0
  130. package/dist/shell/deckModel.js +267 -0
  131. package/dist/shell/deckModel.js.map +1 -0
  132. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  133. package/dist/shell/frame/AccountSwitcher.js +243 -0
  134. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  135. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  136. package/dist/shell/frame/AddColumnDialog.js +81 -0
  137. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  138. package/dist/shell/frame/AppMenu.d.ts +21 -0
  139. package/dist/shell/frame/AppMenu.js +642 -0
  140. package/dist/shell/frame/AppMenu.js.map +1 -0
  141. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  142. package/dist/shell/frame/CommandPalette.js +118 -0
  143. package/dist/shell/frame/CommandPalette.js.map +1 -0
  144. package/dist/shell/frame/DeckView.d.ts +13 -0
  145. package/dist/shell/frame/DeckView.js +287 -0
  146. package/dist/shell/frame/DeckView.js.map +1 -0
  147. package/dist/shell/frame/FindBar.d.ts +10 -0
  148. package/dist/shell/frame/FindBar.js +108 -0
  149. package/dist/shell/frame/FindBar.js.map +1 -0
  150. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  151. package/dist/shell/frame/MediaPanel.js +76 -0
  152. package/dist/shell/frame/MediaPanel.js.map +1 -0
  153. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  154. package/dist/shell/frame/NewTabPage.js +71 -0
  155. package/dist/shell/frame/NewTabPage.js.map +1 -0
  156. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  157. package/dist/shell/frame/PaneTheme.js +67 -0
  158. package/dist/shell/frame/PaneTheme.js.map +1 -0
  159. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  160. package/dist/shell/frame/ReportDialog.js +95 -0
  161. package/dist/shell/frame/ReportDialog.js.map +1 -0
  162. package/dist/shell/frame/Shell.d.ts +8 -0
  163. package/dist/shell/frame/Shell.js +1131 -0
  164. package/dist/shell/frame/Shell.js.map +1 -0
  165. package/dist/shell/frame/Titlebar.d.ts +16 -0
  166. package/dist/shell/frame/Titlebar.js +77 -0
  167. package/dist/shell/frame/Titlebar.js.map +1 -0
  168. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  169. package/dist/shell/frame/TitlebarExtras.js +202 -0
  170. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  171. package/dist/shell/frame/WebPanel.d.ts +4 -0
  172. package/dist/shell/frame/WebPanel.js +182 -0
  173. package/dist/shell/frame/WebPanel.js.map +1 -0
  174. package/dist/shell/frame/accountModel.d.ts +49 -0
  175. package/dist/shell/frame/accountModel.js +67 -0
  176. package/dist/shell/frame/accountModel.js.map +1 -0
  177. package/dist/shell/frame/accountSwitcher.css +91 -0
  178. package/dist/shell/frame/appI18n.d.ts +44 -0
  179. package/dist/shell/frame/appI18n.js +64 -0
  180. package/dist/shell/frame/appI18n.js.map +1 -0
  181. package/dist/shell/frame/appMenu.css +121 -0
  182. package/dist/shell/frame/backupModel.d.ts +38 -0
  183. package/dist/shell/frame/backupModel.js +192 -0
  184. package/dist/shell/frame/backupModel.js.map +1 -0
  185. package/dist/shell/frame/boot.d.ts +8 -0
  186. package/dist/shell/frame/boot.js +35 -0
  187. package/dist/shell/frame/boot.js.map +1 -0
  188. package/dist/shell/frame/brand.d.ts +1 -0
  189. package/dist/shell/frame/brand.js +4 -0
  190. package/dist/shell/frame/brand.js.map +1 -0
  191. package/dist/shell/frame/bridge.d.ts +35 -0
  192. package/dist/shell/frame/bridge.js +70 -0
  193. package/dist/shell/frame/bridge.js.map +1 -0
  194. package/dist/shell/frame/chromeTheme.d.ts +29 -0
  195. package/dist/shell/frame/chromeTheme.js +81 -0
  196. package/dist/shell/frame/chromeTheme.js.map +1 -0
  197. package/dist/shell/frame/deck.css +209 -0
  198. package/dist/shell/frame/deckStore.d.ts +89 -0
  199. package/dist/shell/frame/deckStore.js +239 -0
  200. package/dist/shell/frame/deckStore.js.map +1 -0
  201. package/dist/shell/frame/devHost.d.ts +35 -0
  202. package/dist/shell/frame/devHost.js +80 -0
  203. package/dist/shell/frame/devHost.js.map +1 -0
  204. package/dist/shell/frame/devModel.d.ts +7 -0
  205. package/dist/shell/frame/devModel.js +17 -0
  206. package/dist/shell/frame/devModel.js.map +1 -0
  207. package/dist/shell/frame/diag.d.ts +7 -0
  208. package/dist/shell/frame/diag.js +39 -0
  209. package/dist/shell/frame/diag.js.map +1 -0
  210. package/dist/shell/frame/findBar.css +14 -0
  211. package/dist/shell/frame/frameMessages.d.ts +248 -0
  212. package/dist/shell/frame/frameMessages.js +252 -0
  213. package/dist/shell/frame/frameMessages.js.map +1 -0
  214. package/dist/shell/frame/hooks.d.ts +39 -0
  215. package/dist/shell/frame/hooks.js +97 -0
  216. package/dist/shell/frame/hooks.js.map +1 -0
  217. package/dist/shell/frame/i18n.d.ts +27 -0
  218. package/dist/shell/frame/i18n.js +66 -0
  219. package/dist/shell/frame/i18n.js.map +1 -0
  220. package/dist/shell/frame/iconPack.d.ts +11 -0
  221. package/dist/shell/frame/iconPack.js +45 -0
  222. package/dist/shell/frame/iconPack.js.map +1 -0
  223. package/dist/shell/frame/icons.d.ts +71 -0
  224. package/dist/shell/frame/icons.js +75 -0
  225. package/dist/shell/frame/icons.js.map +1 -0
  226. package/dist/shell/frame/index.d.ts +34 -0
  227. package/dist/shell/frame/index.js +43 -0
  228. package/dist/shell/frame/index.js.map +1 -0
  229. package/dist/shell/frame/language.d.ts +58 -0
  230. package/dist/shell/frame/language.js +165 -0
  231. package/dist/shell/frame/language.js.map +1 -0
  232. package/dist/shell/frame/mediaModel.d.ts +34 -0
  233. package/dist/shell/frame/mediaModel.js +53 -0
  234. package/dist/shell/frame/mediaModel.js.map +1 -0
  235. package/dist/shell/frame/menuMessages.en.json +54 -0
  236. package/dist/shell/frame/menuModel.d.ts +277 -0
  237. package/dist/shell/frame/menuModel.js +293 -0
  238. package/dist/shell/frame/menuModel.js.map +1 -0
  239. package/dist/shell/frame/paletteModel.d.ts +139 -0
  240. package/dist/shell/frame/paletteModel.js +112 -0
  241. package/dist/shell/frame/paletteModel.js.map +1 -0
  242. package/dist/shell/frame/paneTheme.css +9 -0
  243. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  244. package/dist/shell/frame/pluginCommandStore.js +70 -0
  245. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  246. package/dist/shell/frame/reportModel.d.ts +52 -0
  247. package/dist/shell/frame/reportModel.js +105 -0
  248. package/dist/shell/frame/reportModel.js.map +1 -0
  249. package/dist/shell/frame/safeStore.d.ts +7 -0
  250. package/dist/shell/frame/safeStore.js +40 -0
  251. package/dist/shell/frame/safeStore.js.map +1 -0
  252. package/dist/shell/frame/searchInput.d.ts +2 -0
  253. package/dist/shell/frame/searchInput.js +11 -0
  254. package/dist/shell/frame/searchInput.js.map +1 -0
  255. package/dist/shell/frame/shell.css +629 -0
  256. package/dist/shell/frame/site.d.ts +206 -0
  257. package/dist/shell/frame/site.js +22 -0
  258. package/dist/shell/frame/site.js.map +1 -0
  259. package/dist/shell/frame/state.d.ts +99 -0
  260. package/dist/shell/frame/state.js +284 -0
  261. package/dist/shell/frame/state.js.map +1 -0
  262. package/dist/shell/frame/syncGate.d.ts +10 -0
  263. package/dist/shell/frame/syncGate.js +36 -0
  264. package/dist/shell/frame/syncGate.js.map +1 -0
  265. package/dist/shell/frame/syncHost.d.ts +35 -0
  266. package/dist/shell/frame/syncHost.js +85 -0
  267. package/dist/shell/frame/syncHost.js.map +1 -0
  268. package/dist/shell/frame/tabStill.d.ts +2 -0
  269. package/dist/shell/frame/tabStill.js +62 -0
  270. package/dist/shell/frame/tabStill.js.map +1 -0
  271. package/dist/shell/frame/themeScopes.d.ts +29 -0
  272. package/dist/shell/frame/themeScopes.js +61 -0
  273. package/dist/shell/frame/themeScopes.js.map +1 -0
  274. package/dist/shell/frame/themeStore.d.ts +99 -0
  275. package/dist/shell/frame/themeStore.js +252 -0
  276. package/dist/shell/frame/themeStore.js.map +1 -0
  277. package/dist/shell/frame/windowBinding.d.ts +2 -0
  278. package/dist/shell/frame/windowBinding.js +7 -0
  279. package/dist/shell/frame/windowBinding.js.map +1 -0
  280. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  281. package/dist/shell/frame/workspaceModel.js +250 -0
  282. package/dist/shell/frame/workspaceModel.js.map +1 -0
  283. package/dist/shell/frame/workspaces.css +84 -0
  284. package/dist/shell/frame/workspaces.d.ts +22 -0
  285. package/dist/shell/frame/workspaces.js +125 -0
  286. package/dist/shell/frame/workspaces.js.map +1 -0
  287. package/dist/shell/frame/zoomStore.d.ts +10 -0
  288. package/dist/shell/frame/zoomStore.js +65 -0
  289. package/dist/shell/frame/zoomStore.js.map +1 -0
  290. package/dist/shell/installController.d.ts +122 -0
  291. package/dist/shell/installController.js +146 -0
  292. package/dist/shell/installController.js.map +1 -0
  293. package/dist/shell/installerMessages.d.ts +30 -0
  294. package/dist/shell/installerMessages.js +36 -0
  295. package/dist/shell/installerMessages.js.map +1 -0
  296. package/dist/shell/linkDrop.js.map +1 -1
  297. package/dist/shell/messages.d.ts +16 -0
  298. package/dist/shell/messages.js +27 -0
  299. package/dist/shell/messages.js.map +1 -0
  300. package/dist/shell/palette.js.map +1 -1
  301. package/dist/shell/paneModel.d.ts +22 -0
  302. package/dist/shell/paneModel.js +24 -1
  303. package/dist/shell/paneModel.js.map +1 -1
  304. package/dist/shell/panel/Appearance.d.ts +8 -0
  305. package/dist/shell/panel/Appearance.js +256 -0
  306. package/dist/shell/panel/Appearance.js.map +1 -0
  307. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  308. package/dist/shell/panel/BackupPanel.js +198 -0
  309. package/dist/shell/panel/BackupPanel.js.map +1 -0
  310. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  311. package/dist/shell/panel/DeveloperPanel.js +51 -0
  312. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  313. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  314. package/dist/shell/panel/FeatureToggles.js +42 -0
  315. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  316. package/dist/shell/panel/Home.d.ts +3 -0
  317. package/dist/shell/panel/Home.js +23 -0
  318. package/dist/shell/panel/Home.js.map +1 -0
  319. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  320. package/dist/shell/panel/IconPackInstall.js +41 -0
  321. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  322. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  323. package/dist/shell/panel/LanguageSettings.js +54 -0
  324. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  325. package/dist/shell/panel/MakePanel.d.ts +3 -0
  326. package/dist/shell/panel/MakePanel.js +237 -0
  327. package/dist/shell/panel/MakePanel.js.map +1 -0
  328. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  329. package/dist/shell/panel/MarkdownDoc.js +35 -0
  330. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  331. package/dist/shell/panel/Modes.d.ts +40 -0
  332. package/dist/shell/panel/Modes.js +270 -0
  333. package/dist/shell/panel/Modes.js.map +1 -0
  334. package/dist/shell/panel/NavIcon.d.ts +4 -0
  335. package/dist/shell/panel/NavIcon.js +6 -0
  336. package/dist/shell/panel/NavIcon.js.map +1 -0
  337. package/dist/shell/panel/Panel.d.ts +7 -0
  338. package/dist/shell/panel/Panel.js +139 -0
  339. package/dist/shell/panel/Panel.js.map +1 -0
  340. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  341. package/dist/shell/panel/PluginFeatures.js +165 -0
  342. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  343. package/dist/shell/panel/Plugins.d.ts +33 -0
  344. package/dist/shell/panel/Plugins.js +112 -0
  345. package/dist/shell/panel/Plugins.js.map +1 -0
  346. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  347. package/dist/shell/panel/PowerSettings.js +52 -0
  348. package/dist/shell/panel/PowerSettings.js.map +1 -0
  349. package/dist/shell/panel/Settings.d.ts +23 -0
  350. package/dist/shell/panel/Settings.js +116 -0
  351. package/dist/shell/panel/Settings.js.map +1 -0
  352. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  353. package/dist/shell/panel/ShareSetup.js +130 -0
  354. package/dist/shell/panel/ShareSetup.js.map +1 -0
  355. package/dist/shell/panel/StoreSection.d.ts +6 -0
  356. package/dist/shell/panel/StoreSection.js +48 -0
  357. package/dist/shell/panel/StoreSection.js.map +1 -0
  358. package/dist/shell/panel/StringPacks.d.ts +11 -0
  359. package/dist/shell/panel/StringPacks.js +106 -0
  360. package/dist/shell/panel/StringPacks.js.map +1 -0
  361. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  362. package/dist/shell/panel/ThemeBuilder.js +205 -0
  363. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  364. package/dist/shell/panel/backup.css +34 -0
  365. package/dist/shell/panel/builder.css +232 -0
  366. package/dist/shell/panel/builderModel.d.ts +55 -0
  367. package/dist/shell/panel/builderModel.js +95 -0
  368. package/dist/shell/panel/builderModel.js.map +1 -0
  369. package/dist/shell/panel/compare.d.ts +10 -0
  370. package/dist/shell/panel/compare.js +51 -0
  371. package/dist/shell/panel/compare.js.map +1 -0
  372. package/dist/shell/panel/controls.d.ts +135 -0
  373. package/dist/shell/panel/controls.js +213 -0
  374. package/dist/shell/panel/controls.js.map +1 -0
  375. package/dist/shell/panel/featureModel.d.ts +69 -0
  376. package/dist/shell/panel/featureModel.js +79 -0
  377. package/dist/shell/panel/featureModel.js.map +1 -0
  378. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  379. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  380. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  381. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  382. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  383. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  384. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  385. package/dist/shell/panel/fonts/catalog.js +68 -0
  386. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  387. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  388. package/dist/shell/panel/index.d.ts +20 -0
  389. package/dist/shell/panel/index.js +34 -0
  390. package/dist/shell/panel/index.js.map +1 -0
  391. package/dist/shell/panel/languageModel.d.ts +5 -0
  392. package/dist/shell/panel/languageModel.js +7 -0
  393. package/dist/shell/panel/languageModel.js.map +1 -0
  394. package/dist/shell/panel/make.css +72 -0
  395. package/dist/shell/panel/makeModel.d.ts +32 -0
  396. package/dist/shell/panel/makeModel.js +84 -0
  397. package/dist/shell/panel/makeModel.js.map +1 -0
  398. package/dist/shell/panel/markdown.d.ts +46 -0
  399. package/dist/shell/panel/markdown.js +100 -0
  400. package/dist/shell/panel/markdown.js.map +1 -0
  401. package/dist/shell/panel/nav.d.ts +12 -0
  402. package/dist/shell/panel/nav.js +50 -0
  403. package/dist/shell/panel/nav.js.map +1 -0
  404. package/dist/shell/panel/panel.css +401 -0
  405. package/dist/shell/panel/panelMessages.d.ts +763 -0
  406. package/dist/shell/panel/panelMessages.js +767 -0
  407. package/dist/shell/panel/panelMessages.js.map +1 -0
  408. package/dist/shell/panel/plugins.css +59 -0
  409. package/dist/shell/panel/setupModel.d.ts +87 -0
  410. package/dist/shell/panel/setupModel.js +152 -0
  411. package/dist/shell/panel/setupModel.js.map +1 -0
  412. package/dist/shell/panel/site.d.ts +259 -0
  413. package/dist/shell/panel/site.js +25 -0
  414. package/dist/shell/panel/site.js.map +1 -0
  415. package/dist/shell/panel/strings.css +7 -0
  416. package/dist/shell/panel/themes.d.ts +10 -0
  417. package/dist/shell/panel/themes.js +8 -0
  418. package/dist/shell/panel/themes.js.map +1 -0
  419. package/dist/shell/profileModel.d.ts +3 -2
  420. package/dist/shell/profileModel.js +7 -5
  421. package/dist/shell/profileModel.js.map +1 -1
  422. package/dist/shell/store.css +230 -0
  423. package/dist/shell/storeMessages.d.ts +169 -0
  424. package/dist/shell/storeMessages.js +172 -0
  425. package/dist/shell/storeMessages.js.map +1 -0
  426. package/dist/shell/storeModel.d.ts +181 -0
  427. package/dist/shell/storeModel.js +133 -0
  428. package/dist/shell/storeModel.js.map +1 -0
  429. package/dist/shell/stringPacksModel.d.ts +44 -0
  430. package/dist/shell/stringPacksModel.js +94 -0
  431. package/dist/shell/stringPacksModel.js.map +1 -0
  432. package/dist/shell/updateModel.d.ts +2 -1
  433. package/dist/shell/updateModel.js +5 -4
  434. package/dist/shell/updateModel.js.map +1 -1
  435. package/dist/shell/windowControls.d.ts +4 -0
  436. package/dist/shell/windowControls.js +5 -0
  437. package/dist/shell/windowControls.js.map +1 -1
  438. package/i18n-config.schema.json +29 -0
  439. package/i18n-meta.schema.json +26 -0
  440. package/i18n.schema.json +42 -0
  441. package/icons.schema.json +646 -0
  442. package/languages.schema.json +23 -0
  443. package/locales/ar-x-fm.json +11 -0
  444. package/locales/ar.json +1281 -0
  445. package/locales/bg.json +1280 -0
  446. package/locales/bn.json +1280 -0
  447. package/locales/ca.json +1280 -0
  448. package/locales/cs.json +1280 -0
  449. package/locales/da.json +1280 -0
  450. package/locales/de.json +1280 -0
  451. package/locales/el.json +1280 -0
  452. package/locales/en-GB.json +27 -0
  453. package/locales/en.json +1280 -0
  454. package/locales/en.meta.json +51 -0
  455. package/locales/es.json +1280 -0
  456. package/locales/eu.json +1280 -0
  457. package/locales/fa.json +1281 -0
  458. package/locales/fi.json +1280 -0
  459. package/locales/fil.json +1280 -0
  460. package/locales/fr.json +1280 -0
  461. package/locales/ga.json +1280 -0
  462. package/locales/gl.json +1280 -0
  463. package/locales/gu.json +1280 -0
  464. package/locales/ha.json +1280 -0
  465. package/locales/he.json +1281 -0
  466. package/locales/hi.json +1280 -0
  467. package/locales/hr.json +1280 -0
  468. package/locales/hu.json +1279 -0
  469. package/locales/id.json +1280 -0
  470. package/locales/ig.json +1280 -0
  471. package/locales/it.json +1280 -0
  472. package/locales/ja.json +1280 -0
  473. package/locales/kn.json +1280 -0
  474. package/locales/ko.json +1280 -0
  475. package/locales/mr.json +1280 -0
  476. package/locales/ms.json +1280 -0
  477. package/locales/nb.json +1280 -0
  478. package/locales/nl.json +1280 -0
  479. package/locales/pl.json +1280 -0
  480. package/locales/pt.json +1280 -0
  481. package/locales/ro.json +1280 -0
  482. package/locales/ru.json +1280 -0
  483. package/locales/sk.json +1280 -0
  484. package/locales/sr.json +1280 -0
  485. package/locales/sv.json +1280 -0
  486. package/locales/ta.json +1280 -0
  487. package/locales/th.json +1280 -0
  488. package/locales/tr.json +1280 -0
  489. package/locales/uk.json +1280 -0
  490. package/locales/ur.json +1281 -0
  491. package/locales/vi.json +1280 -0
  492. package/locales/yo.json +1280 -0
  493. package/locales/zh-Hans.json +1280 -0
  494. package/locales/zh-Hant.json +1280 -0
  495. package/package.json +139 -5
  496. package/store-catalog.schema.json +65 -0
  497. package/theme.schema.json +4659 -0
  498. package/windows/installer.nsi +926 -0
  499. package/windows/languages/Basque.nsh +28 -0
  500. package/windows/languages/Catalan.nsh +28 -0
  501. package/windows/languages/Croatian.nsh +28 -0
  502. package/windows/languages/Czech.nsh +28 -0
  503. package/windows/languages/Danish.nsh +28 -0
  504. package/windows/languages/Finnish.nsh +28 -0
  505. package/windows/languages/Galician.nsh +28 -0
  506. package/windows/languages/Greek.nsh +28 -0
  507. package/windows/languages/Hungarian.nsh +28 -0
  508. package/windows/languages/Indonesian.nsh +28 -0
  509. package/windows/languages/Irish.nsh +28 -0
  510. package/windows/languages/Malay.nsh +28 -0
  511. package/windows/languages/Polish.nsh +28 -0
  512. package/windows/languages/Romanian.nsh +28 -0
  513. package/windows/languages/Serbian.nsh +28 -0
  514. package/windows/languages/Slovak.nsh +28 -0
  515. package/windows/languages/Thai.nsh +28 -0
@@ -0,0 +1,146 @@
1
+ // The install screen's state machine, shared by every wayBetter app. Requests come from
2
+ // `waybetter://install` links (the native `install-link` event, plus links that arrived before the
3
+ // shell listened), files dropped on the window and the Store view. Each request is staged natively
4
+ // (downloaded/validated, hashed) and shown on the install screen; nothing is written until the owner
5
+ // presses Install there. The app supplies how it talks to native code (Tauri `invoke`/`listen`) and
6
+ // how its themes are parsed and saved; plugins need nothing app-specific.
7
+ import { freeThemeId, installedThemeId, kindForFile, MAX_FILE_BYTES, errorText } from "./storeModel.js";
8
+ export function createInstallController(options) {
9
+ const { backend, t, theme: themes } = options;
10
+ let current = null;
11
+ let records = {};
12
+ let started = false;
13
+ const listeners = new Set();
14
+ const set = (next) => { current = next; for (const listener of [...listeners])
15
+ listener(); };
16
+ async function refreshRecords() {
17
+ try {
18
+ records = (await backend.invoke('install_records')).items ?? {};
19
+ }
20
+ catch { /* Keep the last copy. */ }
21
+ }
22
+ /** Parses a staged theme the way the app's import does, and finds the theme it would update. */
23
+ async function prepared(preview) {
24
+ if (preview.kind === 'plugin' || preview.kind === 'strings')
25
+ return { status: 'ready', preview, theme: null, warnings: [], replaces: null };
26
+ const parsed = themes.parse(preview.text);
27
+ if ('error' in parsed)
28
+ return { status: 'error', title: t('wb.install.err.theme'), message: parsed.error };
29
+ const userThemes = await themes.userThemes();
30
+ const replaces = preview.store ? installedThemeId(preview.store, records, userThemes) : null;
31
+ return { status: 'ready', preview, theme: parsed.theme, warnings: parsed.warnings, replaces };
32
+ }
33
+ async function stage(title, detail, run) {
34
+ set({ status: 'loading', title, detail });
35
+ try {
36
+ await Promise.all([themes.userThemes(), refreshRecords()]);
37
+ const preview = await run();
38
+ set(await prepared(preview));
39
+ }
40
+ catch (error) {
41
+ set({ status: 'error', title, message: errorText(error) });
42
+ }
43
+ }
44
+ const controller = {
45
+ current: () => current,
46
+ subscribe(listener) {
47
+ listeners.add(listener);
48
+ return () => { listeners.delete(listener); };
49
+ },
50
+ requestLink(link) {
51
+ let host = link.url;
52
+ try {
53
+ host = new URL(link.url).host;
54
+ }
55
+ catch { /* Shown as is. */ }
56
+ return stage(t('wb.install.stage.link', { kind: link.kind, host }), t('wb.install.stage.linkDetail'), () => backend.invoke('install_stage_link', { kind: link.kind, url: link.url }));
57
+ },
58
+ async requestFile(file) {
59
+ const kind = kindForFile(file.name);
60
+ if (!kind) {
61
+ set({ status: 'error', title: t('wb.install.err.kind', { file: file.name }), message: t('wb.install.err.kindHint', { site: options.site }) });
62
+ return;
63
+ }
64
+ if (file.size > MAX_FILE_BYTES[kind]) {
65
+ set({ status: 'error', title: t('wb.install.err.large', { file: file.name }), message: kind === 'strings' ? t('wb.install.err.stringsLarge') : t('wb.install.err.largeHint', { kind }) });
66
+ return;
67
+ }
68
+ await stage(t('wb.install.stage.named', { name: file.name }), t('wb.install.stage.fileDetail'), async () => backend.invoke('install_stage_file', { name: file.name, text: await file.text() }));
69
+ },
70
+ requestStoreItem(item) {
71
+ return stage(t('wb.install.stage.named', { name: item.name }), t('wb.install.stage.storeDetail'), () => backend.invoke('store_stage', { item: { kind: item.kind, id: item.id } }));
72
+ },
73
+ linkRejected(error) {
74
+ set({ status: 'error', title: t('wb.install.err.link'), message: error.replace(/^LINK: /, '') });
75
+ },
76
+ async cancel() {
77
+ const request = current;
78
+ set(null);
79
+ if (request && request.status === 'ready')
80
+ await backend.invoke('install_cancel', { token: request.preview.token }).catch(() => { });
81
+ },
82
+ close: () => set(null),
83
+ async confirm(enable) {
84
+ const request = current;
85
+ if (!request || request.status !== 'ready')
86
+ return;
87
+ const { preview } = request;
88
+ set({ status: 'installing', preview, theme: request.theme });
89
+ try {
90
+ if (preview.kind === 'plugin') {
91
+ await backend.invoke('install_commit', { token: preview.token, enable, themeId: null });
92
+ options.onPluginsChanged?.();
93
+ set({ status: 'done', kind: 'plugin', name: preview.plugin?.name ?? preview.file ?? 'Plugin', fonts: [], enabled: enable || Boolean(preview.existing?.enabled) });
94
+ return;
95
+ }
96
+ if (preview.kind === 'strings') {
97
+ await backend.invoke('install_commit', { token: preview.token, enable, themeId: null });
98
+ await options.onStringsChanged?.();
99
+ set({ status: 'done', kind: 'strings', name: preview.strings?.name ?? 'String pack', fonts: [], enabled: enable || Boolean(preview.existing?.enabled) });
100
+ return;
101
+ }
102
+ const own = await themes.userThemes();
103
+ const wanted = themes.idOf(request.theme);
104
+ const taken = [...themes.builtinThemes, ...own.filter(id => id !== request.replaces)];
105
+ const id = request.replaces ?? freeThemeId(wanted, taken);
106
+ const outcome = await backend.invoke('install_commit', { token: preview.token, enable, themeId: id });
107
+ // The exact bytes native code staged and hashed; parsed and sanitized again here.
108
+ const parsed = themes.parse(outcome.themeText ?? '');
109
+ if ('error' in parsed)
110
+ throw new Error(parsed.error);
111
+ const saved = await themes.save(parsed.theme, id, { replaces: request.replaces, enable });
112
+ options.onThemesChanged?.();
113
+ set({ status: 'done', kind: 'theme', name: themes.facts(parsed.theme).name, themeId: id, fonts: saved.fonts, enabled: saved.enabled });
114
+ }
115
+ catch (error) {
116
+ set({ status: 'error', title: preview.kind === 'strings' ? t('wb.install.err.stringsNotInstalled') : t('wb.install.err.notInstalled', { kind: preview.kind }), message: errorText(error) });
117
+ }
118
+ },
119
+ start() {
120
+ if (started)
121
+ return () => { };
122
+ started = true;
123
+ const handle = (event) => {
124
+ if (event.setup)
125
+ options.onSetupLink?.(event.setup);
126
+ else if (event.link)
127
+ void controller.requestLink(event.link);
128
+ else if (event.error)
129
+ controller.linkRejected(event.error);
130
+ };
131
+ // Native code queues every link and also emits it; a handled event clears the queue so a
132
+ // reload of the shell does not show it again.
133
+ const unlisten = backend.listen('install-link', event => { handle(event); void backend.invoke('install_pending').catch(() => { }); });
134
+ // Links that arrived before the shell listened (the app was started by one): the newest.
135
+ void unlisten.then(() => backend.invoke('install_pending').then(events => {
136
+ const last = events[events.length - 1];
137
+ if (last && current === null)
138
+ handle(last);
139
+ })).catch(() => { });
140
+ return () => { started = false; void unlisten.then(off => off()).catch(() => { }); };
141
+ },
142
+ facts: theme => themes.facts(theme),
143
+ };
144
+ return controller;
145
+ }
146
+ //# sourceMappingURL=installController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installController.js","sourceRoot":"","sources":["../../../../../shell/src/installController.ts"],"names":[],"mappings":"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","sourcesContent":["// The install screen's state machine, shared by every wayBetter app. Requests come from\n// `waybetter://install` links (the native `install-link` event, plus links that arrived before the\n// shell listened), files dropped on the window and the Store view. Each request is staged natively\n// (downloaded/validated, hashed) and shown on the install screen; nothing is written until the owner\n// presses Install there. The app supplies how it talks to native code (Tauri `invoke`/`listen`) and\n// how its themes are parsed and saved; plugins need nothing app-specific.\n\nimport { freeThemeId, installedThemeId, kindForFile, MAX_FILE_BYTES, errorText, type InstallKind, type InstallPreview, type InstallRecord, type LinkEvent, type StoreItem } from './storeModel.ts';\nimport type { StoreText } from './storeMessages.ts';\n\n/** How the controller reaches native code (the app passes Tauri's `invoke` and `listen`). */\nexport type StoreBackend = {\n invoke<T>(command: string, args?: Record<string, unknown>): Promise<T>;\n /** Subscribes to a shell event; resolves to the unsubscribe function. */\n listen<T>(event: string, handler: (payload: T) => void): Promise<() => void>;\n};\n\n/** What the install screen shows of a theme (the app's theme format stays the app's). */\nexport type ThemeFacts = {\n name: string;\n author?: string;\n description?: string;\n /** Theme CSS, shown as its own code block (it has custom-CSS trust). */\n css?: string;\n /** The theme's own colors for the tile at the top. */\n tile?: { background: string; color: string; border: string };\n};\n\nexport type ThemeAdapter<Theme> = {\n /** Parses (and sanitizes) a theme file the way the app's theme import does. */\n parse(text: string): { theme: Theme; warnings: string[] } | { error: string };\n /** Loads the app's theme state and resolves to the owner's own theme ids. */\n userThemes(): Promise<string[]>;\n /** Theme ids that ship with the app. */\n builtinThemes: readonly string[];\n /** The id a theme asks for (a free one is chosen from it). */\n idOf(theme: Theme): string;\n facts(theme: Theme): ThemeFacts;\n /**\n * Saves the theme the owner confirmed under `id` (replacing the owner's copy `replaces`), and\n * makes it the current theme when `enable`. Resolves to whether it is current now and the font\n * names it uses that are not available yet.\n */\n save(theme: Theme, id: string, options: { replaces: string | null; enable: boolean }): Promise<{ enabled: boolean; fonts: string[] }>;\n};\n\nexport type InstallRequest<Theme> =\n | { status: 'loading'; title: string; detail: string }\n | { status: 'ready'; preview: InstallPreview; theme: Theme | null; warnings: string[]; replaces: string | null }\n | { status: 'installing'; preview: InstallPreview; theme: Theme | null }\n | { status: 'done'; kind: InstallKind; name: string; themeId?: string; fonts: string[]; enabled: boolean }\n | { status: 'error'; title: string; message: string };\n\nexport type InstallControllerOptions<Theme> = {\n backend: StoreBackend;\n /** The app's translator (framework catalogs merged in); called at request time. */\n t: StoreText;\n /** The site's name in messages (\"X\"). */\n site: string;\n theme: ThemeAdapter<Theme>;\n /** A plugin was installed (the app refreshes its plugin list). */\n onPluginsChanged?(): void;\n /** A theme was installed (the app refreshes its store/theme views). */\n onThemesChanged?(): void;\n /** A string pack was installed (the app hands the site tabs the packs that are on). */\n onStringsChanged?(): void | Promise<void>;\n /**\n * A `waybetter://setup` link was opened (its text, shape-checked natively): the app shows its\n * \"Share my setup\" preview (panel/ShareSetup.tsx). Absent: such links are ignored.\n */\n onSetupLink?(text: string): void;\n};\n\nexport type InstallController<Theme> = {\n current(): InstallRequest<Theme> | null;\n subscribe(listener: () => void): () => void;\n /** A validated `waybetter://install` link: download it natively and show the screen. */\n requestLink(link: { kind: InstallKind; url: string }): Promise<void>;\n /** A file dropped on the window. */\n requestFile(file: { name: string; size: number; text(): Promise<string> }): Promise<void>;\n /** A store item: downloaded natively and checked against the signed catalog. */\n requestStoreItem(item: StoreItem): Promise<void>;\n linkRejected(error: string): void;\n /** Closes the screen and drops what was staged. */\n cancel(): Promise<void>;\n close(): void;\n /** The owner pressed Install. `enable`: turn the plugin on / use the theme now. */\n confirm(enable: boolean): Promise<void>;\n /** Listens for install links (once). Returns a disposer. */\n start(): () => void;\n facts(theme: Theme): ThemeFacts;\n};\n\nexport function createInstallController<Theme>(options: InstallControllerOptions<Theme>): InstallController<Theme> {\n const { backend, t, theme: themes } = options;\n let current: InstallRequest<Theme> | null = null;\n let records: Record<string, InstallRecord> = {};\n let started = false;\n const listeners = new Set<() => void>();\n const set = (next: InstallRequest<Theme> | null) => { current = next; for (const listener of [...listeners]) listener(); };\n\n async function refreshRecords() {\n try { records = (await backend.invoke<{ items: Record<string, InstallRecord> }>('install_records')).items ?? {}; } catch { /* Keep the last copy. */ }\n }\n\n /** Parses a staged theme the way the app's import does, and finds the theme it would update. */\n async function prepared(preview: InstallPreview): Promise<InstallRequest<Theme>> {\n if (preview.kind === 'plugin' || preview.kind === 'strings') return { status: 'ready', preview, theme: null, warnings: [], replaces: null };\n const parsed = themes.parse(preview.text);\n if ('error' in parsed) return { status: 'error', title: t('wb.install.err.theme'), message: parsed.error };\n const userThemes = await themes.userThemes();\n const replaces = preview.store ? installedThemeId(preview.store, records, userThemes) : null;\n return { status: 'ready', preview, theme: parsed.theme, warnings: parsed.warnings, replaces };\n }\n\n async function stage(title: string, detail: string, run: () => Promise<InstallPreview>) {\n set({ status: 'loading', title, detail });\n try {\n await Promise.all([themes.userThemes(), refreshRecords()]);\n const preview = await run();\n set(await prepared(preview));\n } catch (error) {\n set({ status: 'error', title, message: errorText(error) });\n }\n }\n\n const controller: InstallController<Theme> = {\n current: () => current,\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n requestLink(link) {\n let host = link.url;\n try { host = new URL(link.url).host; } catch { /* Shown as is. */ }\n return stage(t('wb.install.stage.link', { kind: link.kind, host }), t('wb.install.stage.linkDetail'), () => backend.invoke<InstallPreview>('install_stage_link', { kind: link.kind, url: link.url }));\n },\n async requestFile(file) {\n const kind = kindForFile(file.name);\n if (!kind) {\n set({ status: 'error', title: t('wb.install.err.kind', { file: file.name }), message: t('wb.install.err.kindHint', { site: options.site }) });\n return;\n }\n if (file.size > MAX_FILE_BYTES[kind]) {\n set({ status: 'error', title: t('wb.install.err.large', { file: file.name }), message: kind === 'strings' ? t('wb.install.err.stringsLarge') : t('wb.install.err.largeHint', { kind }) });\n return;\n }\n await stage(t('wb.install.stage.named', { name: file.name }), t('wb.install.stage.fileDetail'), async () => backend.invoke<InstallPreview>('install_stage_file', { name: file.name, text: await file.text() }));\n },\n requestStoreItem(item) {\n return stage(t('wb.install.stage.named', { name: item.name }), t('wb.install.stage.storeDetail'), () => backend.invoke<InstallPreview>('store_stage', { item: { kind: item.kind, id: item.id } }));\n },\n linkRejected(error) {\n set({ status: 'error', title: t('wb.install.err.link'), message: error.replace(/^LINK: /, '') });\n },\n async cancel() {\n const request = current;\n set(null);\n if (request && request.status === 'ready') await backend.invoke('install_cancel', { token: request.preview.token }).catch(() => {});\n },\n close: () => set(null),\n async confirm(enable) {\n const request = current;\n if (!request || request.status !== 'ready') return;\n const { preview } = request;\n set({ status: 'installing', preview, theme: request.theme });\n try {\n if (preview.kind === 'plugin') {\n await backend.invoke('install_commit', { token: preview.token, enable, themeId: null });\n options.onPluginsChanged?.();\n set({ status: 'done', kind: 'plugin', name: preview.plugin?.name ?? preview.file ?? 'Plugin', fonts: [], enabled: enable || Boolean(preview.existing?.enabled) });\n return;\n }\n if (preview.kind === 'strings') {\n await backend.invoke('install_commit', { token: preview.token, enable, themeId: null });\n await options.onStringsChanged?.();\n set({ status: 'done', kind: 'strings', name: preview.strings?.name ?? 'String pack', fonts: [], enabled: enable || Boolean(preview.existing?.enabled) });\n return;\n }\n const own = await themes.userThemes();\n const wanted = themes.idOf(request.theme!);\n const taken = [...themes.builtinThemes, ...own.filter(id => id !== request.replaces)];\n const id = request.replaces ?? freeThemeId(wanted, taken);\n const outcome = await backend.invoke<{ themeText: string | null }>('install_commit', { token: preview.token, enable, themeId: id });\n // The exact bytes native code staged and hashed; parsed and sanitized again here.\n const parsed = themes.parse(outcome.themeText ?? '');\n if ('error' in parsed) throw new Error(parsed.error);\n const saved = await themes.save(parsed.theme, id, { replaces: request.replaces, enable });\n options.onThemesChanged?.();\n set({ status: 'done', kind: 'theme', name: themes.facts(parsed.theme).name, themeId: id, fonts: saved.fonts, enabled: saved.enabled });\n } catch (error) {\n set({ status: 'error', title: preview.kind === 'strings' ? t('wb.install.err.stringsNotInstalled') : t('wb.install.err.notInstalled', { kind: preview.kind }), message: errorText(error) });\n }\n },\n start() {\n if (started) return () => {};\n started = true;\n const handle = (event: LinkEvent) => {\n if (event.setup) options.onSetupLink?.(event.setup);\n else if (event.link) void controller.requestLink(event.link);\n else if (event.error) controller.linkRejected(event.error);\n };\n // Native code queues every link and also emits it; a handled event clears the queue so a\n // reload of the shell does not show it again.\n const unlisten = backend.listen<LinkEvent>('install-link', event => { handle(event); void backend.invoke('install_pending').catch(() => {}); });\n // Links that arrived before the shell listened (the app was started by one): the newest.\n void unlisten.then(() => backend.invoke<LinkEvent[]>('install_pending').then(events => {\n const last = events[events.length - 1];\n if (last && current === null) handle(last);\n })).catch(() => {});\n return () => { started = false; void unlisten.then(off => off()).catch(() => {}); };\n },\n facts: theme => themes.facts(theme),\n };\n return controller;\n}\n"]}
@@ -0,0 +1,30 @@
1
+ export declare const INSTALLER_MESSAGES: {
2
+ readonly 'wb.installer.addOrReinstall': "Add/Reinstall components";
3
+ readonly 'wb.installer.alreadyInstalled': "Already Installed";
4
+ readonly 'wb.installer.alreadyInstalledLong': "{product} {version} is already installed. Select the operation you want to perform and click Next to continue.";
5
+ readonly 'wb.installer.appRunning': "{product} is running! Please close it first then try again.";
6
+ readonly 'wb.installer.appRunningOkKill': "{product} is running!\nClick OK to kill it";
7
+ readonly 'wb.installer.chooseMaintenanceOption': "Choose the maintenance option to perform.";
8
+ readonly 'wb.installer.choowHowToInstall': "Choose how you want to install {product}.";
9
+ readonly 'wb.installer.createDesktop': "Create desktop shortcut";
10
+ readonly 'wb.installer.dontUninstall': "Do not uninstall";
11
+ readonly 'wb.installer.dontUninstallDowngrade': "Do not uninstall (Downgrading without uninstall is disabled for this installer)";
12
+ readonly 'wb.installer.failedToKillApp': "Failed to kill {product}. Please close it first then try again";
13
+ readonly 'wb.installer.installingWebview2': "Installing WebView2...";
14
+ readonly 'wb.installer.newerVersionInstalled': "A newer version of {product} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it's better to uninstall the current version first. Select the operation you want to perform and click Next to continue.";
15
+ readonly 'wb.installer.older': "older";
16
+ readonly 'wb.installer.olderOrUnknownVersionInstalled': "An {installed} version of {product} is installed on your system. It's recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue.";
17
+ readonly 'wb.installer.silentDowngrades': "Downgrades are disabled for this installer, can't proceed with the silent installer, please use the graphical interface installer instead.\n";
18
+ readonly 'wb.installer.unableToUninstall': "Unable to uninstall!";
19
+ readonly 'wb.installer.uninstallApp': "Uninstall {product}";
20
+ readonly 'wb.installer.uninstallBeforeInstalling': "Uninstall before installing";
21
+ readonly 'wb.installer.unknown': "unknown";
22
+ readonly 'wb.installer.webview2AbortError': "Failed to install WebView2! The app can't run without it. Try restarting the installer.";
23
+ readonly 'wb.installer.webview2DownloadError': "Error: Downloading WebView2 Failed - {error}";
24
+ readonly 'wb.installer.webview2DownloadSuccess': "WebView2 bootstrapper downloaded successfully";
25
+ readonly 'wb.installer.webview2Downloading': "Downloading WebView2 bootstrapper...";
26
+ readonly 'wb.installer.webview2InstallError': "Error: Installing WebView2 failed with exit code {code}";
27
+ readonly 'wb.installer.webview2InstallSuccess': "WebView2 installed successfully";
28
+ readonly 'wb.installer.deleteAppData': "Delete the application data";
29
+ };
30
+ export type InstallerKey = keyof typeof INSTALLER_MESSAGES;
@@ -0,0 +1,36 @@
1
+ // The Windows installer's words in English (`wb.installer.*`), the source of the framework
2
+ // catalogs (`waybetter/locales/<bcp47>.json`). They are Tauri's NSIS installer messages for the
3
+ // languages Tauri does not ship itself; `packages/waybetter/scripts/installer-languages.mjs` writes
4
+ // them as `windows/languages/<Language>.nsh`, which an app lists under `customLanguageFiles`.
5
+ // Placeholders: `{product}` the app's name, `{version}` its version, `{installed}` the installed
6
+ // version, `{error}` and `{code}` what the WebView2 setup reported.
7
+ export const INSTALLER_MESSAGES = {
8
+ 'wb.installer.addOrReinstall': 'Add/Reinstall components',
9
+ 'wb.installer.alreadyInstalled': 'Already Installed',
10
+ 'wb.installer.alreadyInstalledLong': '{product} {version} is already installed. Select the operation you want to perform and click Next to continue.',
11
+ 'wb.installer.appRunning': '{product} is running! Please close it first then try again.',
12
+ 'wb.installer.appRunningOkKill': '{product} is running!\nClick OK to kill it',
13
+ 'wb.installer.chooseMaintenanceOption': 'Choose the maintenance option to perform.',
14
+ 'wb.installer.choowHowToInstall': 'Choose how you want to install {product}.',
15
+ 'wb.installer.createDesktop': 'Create desktop shortcut',
16
+ 'wb.installer.dontUninstall': 'Do not uninstall',
17
+ 'wb.installer.dontUninstallDowngrade': 'Do not uninstall (Downgrading without uninstall is disabled for this installer)',
18
+ 'wb.installer.failedToKillApp': 'Failed to kill {product}. Please close it first then try again',
19
+ 'wb.installer.installingWebview2': 'Installing WebView2...',
20
+ 'wb.installer.newerVersionInstalled': 'A newer version of {product} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it\'s better to uninstall the current version first. Select the operation you want to perform and click Next to continue.',
21
+ 'wb.installer.older': 'older',
22
+ 'wb.installer.olderOrUnknownVersionInstalled': 'An {installed} version of {product} is installed on your system. It\'s recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue.',
23
+ 'wb.installer.silentDowngrades': 'Downgrades are disabled for this installer, can\'t proceed with the silent installer, please use the graphical interface installer instead.\n',
24
+ 'wb.installer.unableToUninstall': 'Unable to uninstall!',
25
+ 'wb.installer.uninstallApp': 'Uninstall {product}',
26
+ 'wb.installer.uninstallBeforeInstalling': 'Uninstall before installing',
27
+ 'wb.installer.unknown': 'unknown',
28
+ 'wb.installer.webview2AbortError': 'Failed to install WebView2! The app can\'t run without it. Try restarting the installer.',
29
+ 'wb.installer.webview2DownloadError': 'Error: Downloading WebView2 Failed - {error}',
30
+ 'wb.installer.webview2DownloadSuccess': 'WebView2 bootstrapper downloaded successfully',
31
+ 'wb.installer.webview2Downloading': 'Downloading WebView2 bootstrapper...',
32
+ 'wb.installer.webview2InstallError': 'Error: Installing WebView2 failed with exit code {code}',
33
+ 'wb.installer.webview2InstallSuccess': 'WebView2 installed successfully',
34
+ 'wb.installer.deleteAppData': 'Delete the application data',
35
+ };
36
+ //# sourceMappingURL=installerMessages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installerMessages.js","sourceRoot":"","sources":["../../../../../shell/src/installerMessages.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,gGAAgG;AAChG,oGAAoG;AACpG,8FAA8F;AAC9F,iGAAiG;AACjG,oEAAoE;AAEpE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,6BAA6B,EAAE,0BAA0B;IACzD,+BAA+B,EAAE,mBAAmB;IACpD,mCAAmC,EAAE,gHAAgH;IACrJ,yBAAyB,EAAE,6DAA6D;IACxF,+BAA+B,EAAE,4CAA4C;IAC7E,sCAAsC,EAAE,2CAA2C;IACnF,gCAAgC,EAAE,2CAA2C;IAC7E,4BAA4B,EAAE,yBAAyB;IACvD,4BAA4B,EAAE,kBAAkB;IAChD,qCAAqC,EAAE,iFAAiF;IACxH,8BAA8B,EAAE,gEAAgE;IAChG,iCAAiC,EAAE,wBAAwB;IAC3D,oCAAoC,EAAE,yRAAyR;IAC/T,oBAAoB,EAAE,OAAO;IAC7B,6CAA6C,EAAE,mNAAmN;IAClQ,+BAA+B,EAAE,+IAA+I;IAChL,gCAAgC,EAAE,sBAAsB;IACxD,2BAA2B,EAAE,qBAAqB;IAClD,wCAAwC,EAAE,6BAA6B;IACvE,sBAAsB,EAAE,SAAS;IACjC,iCAAiC,EAAE,0FAA0F;IAC7H,oCAAoC,EAAE,8CAA8C;IACpF,sCAAsC,EAAE,+CAA+C;IACvF,kCAAkC,EAAE,sCAAsC;IAC1E,mCAAmC,EAAE,yDAAyD;IAC9F,qCAAqC,EAAE,iCAAiC;IACxE,4BAA4B,EAAE,6BAA6B;CACnD,CAAC","sourcesContent":["// The Windows installer's words in English (`wb.installer.*`), the source of the framework\n// catalogs (`waybetter/locales/<bcp47>.json`). They are Tauri's NSIS installer messages for the\n// languages Tauri does not ship itself; `packages/waybetter/scripts/installer-languages.mjs` writes\n// them as `windows/languages/<Language>.nsh`, which an app lists under `customLanguageFiles`.\n// Placeholders: `{product}` the app's name, `{version}` its version, `{installed}` the installed\n// version, `{error}` and `{code}` what the WebView2 setup reported.\n\nexport const INSTALLER_MESSAGES = {\n 'wb.installer.addOrReinstall': 'Add/Reinstall components',\n 'wb.installer.alreadyInstalled': 'Already Installed',\n 'wb.installer.alreadyInstalledLong': '{product} {version} is already installed. Select the operation you want to perform and click Next to continue.',\n 'wb.installer.appRunning': '{product} is running! Please close it first then try again.',\n 'wb.installer.appRunningOkKill': '{product} is running!\\nClick OK to kill it',\n 'wb.installer.chooseMaintenanceOption': 'Choose the maintenance option to perform.',\n 'wb.installer.choowHowToInstall': 'Choose how you want to install {product}.',\n 'wb.installer.createDesktop': 'Create desktop shortcut',\n 'wb.installer.dontUninstall': 'Do not uninstall',\n 'wb.installer.dontUninstallDowngrade': 'Do not uninstall (Downgrading without uninstall is disabled for this installer)',\n 'wb.installer.failedToKillApp': 'Failed to kill {product}. Please close it first then try again',\n 'wb.installer.installingWebview2': 'Installing WebView2...',\n 'wb.installer.newerVersionInstalled': 'A newer version of {product} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it\\'s better to uninstall the current version first. Select the operation you want to perform and click Next to continue.',\n 'wb.installer.older': 'older',\n 'wb.installer.olderOrUnknownVersionInstalled': 'An {installed} version of {product} is installed on your system. It\\'s recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue.',\n 'wb.installer.silentDowngrades': 'Downgrades are disabled for this installer, can\\'t proceed with the silent installer, please use the graphical interface installer instead.\\n',\n 'wb.installer.unableToUninstall': 'Unable to uninstall!',\n 'wb.installer.uninstallApp': 'Uninstall {product}',\n 'wb.installer.uninstallBeforeInstalling': 'Uninstall before installing',\n 'wb.installer.unknown': 'unknown',\n 'wb.installer.webview2AbortError': 'Failed to install WebView2! The app can\\'t run without it. Try restarting the installer.',\n 'wb.installer.webview2DownloadError': 'Error: Downloading WebView2 Failed - {error}',\n 'wb.installer.webview2DownloadSuccess': 'WebView2 bootstrapper downloaded successfully',\n 'wb.installer.webview2Downloading': 'Downloading WebView2 bootstrapper...',\n 'wb.installer.webview2InstallError': 'Error: Installing WebView2 failed with exit code {code}',\n 'wb.installer.webview2InstallSuccess': 'WebView2 installed successfully',\n 'wb.installer.deleteAppData': 'Delete the application data',\n} as const;\n\nexport type InstallerKey = keyof typeof INSTALLER_MESSAGES;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"linkDrop.js","sourceRoot":"","sources":["../../../shell/src/linkDrop.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure helpers for dropping a dragged link into the dock as a new tab or split pane.\n// No React, no Tauri, no dockview runtime: the Shell maps dockview drop events through these.\n\nexport const MAX_LINK_LENGTH = 4096;\n\n/** Only plain http(s) links without credentials open as tabs (same rule as the host's `tabs::parse_web_url`). */\nexport function webUrl(value: string | null | undefined): string | null {\n const text = value?.trim();\n if (!text || text.length > MAX_LINK_LENGTH) return null;\n let url: URL;\n try { url = new URL(text); } catch { return null; }\n if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password) return null;\n return url.href;\n}\n\n/**\n * The link carried by a drop: `text/uri-list` (first non-comment line), then `text/x-moz-url`,\n * then the first line of `text/plain`; else the URL the source tab reported on dragstart.\n */\nexport function dropUrl(getData: (type: string) => string, reported?: string | null): string | null {\n const read = (type: string) => { try { return getData(type) || ''; } catch { return ''; } };\n const firstLine = (text: string, skipComments: boolean) =>\n text.split(/\\r?\\n/).map(line => line.trim()).find(line => line && !(skipComments && line.startsWith('#'))) ?? '';\n return webUrl(firstLine(read('text/uri-list'), true))\n ?? webUrl(firstLine(read('text/x-moz-url'), false))\n ?? webUrl(firstLine(read('text/plain'), false))\n ?? webUrl(reported);\n}\n\n/** Drag types that may carry a link. File drags are left to the page (e.g. a composer). */\nexport function carriesLink(types: readonly string[]): boolean {\n if (types.includes('Files')) return false;\n return types.includes('text/uri-list') || types.includes('text/x-moz-url');\n}\n\nexport type DropPosition = 'top' | 'bottom' | 'left' | 'right' | 'center';\nexport type DropDirection = 'left' | 'right' | 'above' | 'below';\nexport type Placement =\n | { referenceGroup: string; direction: 'within' | DropDirection; index?: number }\n | { direction: DropDirection };\n\nconst DIRECTIONS: Record<Exclude<DropPosition, 'center'>, DropDirection> = { top: 'above', bottom: 'below', left: 'left', right: 'right' };\n\n/**\n * Where a dropped link opens. `groupId`: the group under the pointer (missing for the dock's outer\n * edges). `tabIndex`: the tab dropped on, if any. `undefined`: the default (active group, or a new\n * group in an empty dock).\n */\nexport function placementFor(target: { position: DropPosition; groupId?: string; tabIndex?: number }): Placement | undefined {\n const { position, groupId, tabIndex } = target;\n if (!groupId) return position === 'center' ? undefined : { direction: DIRECTIONS[position] };\n if (position === 'center') return tabIndex === undefined ? { referenceGroup: groupId, direction: 'within' } : { referenceGroup: groupId, direction: 'within', index: tabIndex };\n return { referenceGroup: groupId, direction: DIRECTIONS[position] };\n}\n"]}
1
+ {"version":3,"file":"linkDrop.js","sourceRoot":"","sources":["../../../../../shell/src/linkDrop.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure helpers for dropping a dragged link into the dock as a new tab or split pane.\n// No React, no Tauri, no dockview runtime: the Shell maps dockview drop events through these.\n\nexport const MAX_LINK_LENGTH = 4096;\n\n/** Only plain http(s) links without credentials open as tabs (same rule as the host's `tabs::parse_web_url`). */\nexport function webUrl(value: string | null | undefined): string | null {\n const text = value?.trim();\n if (!text || text.length > MAX_LINK_LENGTH) return null;\n let url: URL;\n try { url = new URL(text); } catch { return null; }\n if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password) return null;\n return url.href;\n}\n\n/**\n * The link carried by a drop: `text/uri-list` (first non-comment line), then `text/x-moz-url`,\n * then the first line of `text/plain`; else the URL the source tab reported on dragstart.\n */\nexport function dropUrl(getData: (type: string) => string, reported?: string | null): string | null {\n const read = (type: string) => { try { return getData(type) || ''; } catch { return ''; } };\n const firstLine = (text: string, skipComments: boolean) =>\n text.split(/\\r?\\n/).map(line => line.trim()).find(line => line && !(skipComments && line.startsWith('#'))) ?? '';\n return webUrl(firstLine(read('text/uri-list'), true))\n ?? webUrl(firstLine(read('text/x-moz-url'), false))\n ?? webUrl(firstLine(read('text/plain'), false))\n ?? webUrl(reported);\n}\n\n/** Drag types that may carry a link. File drags are left to the page (e.g. a composer). */\nexport function carriesLink(types: readonly string[]): boolean {\n if (types.includes('Files')) return false;\n return types.includes('text/uri-list') || types.includes('text/x-moz-url');\n}\n\nexport type DropPosition = 'top' | 'bottom' | 'left' | 'right' | 'center';\nexport type DropDirection = 'left' | 'right' | 'above' | 'below';\nexport type Placement =\n | { referenceGroup: string; direction: 'within' | DropDirection; index?: number }\n | { direction: DropDirection };\n\nconst DIRECTIONS: Record<Exclude<DropPosition, 'center'>, DropDirection> = { top: 'above', bottom: 'below', left: 'left', right: 'right' };\n\n/**\n * Where a dropped link opens. `groupId`: the group under the pointer (missing for the dock's outer\n * edges). `tabIndex`: the tab dropped on, if any. `undefined`: the default (active group, or a new\n * group in an empty dock).\n */\nexport function placementFor(target: { position: DropPosition; groupId?: string; tabIndex?: number }): Placement | undefined {\n const { position, groupId, tabIndex } = target;\n if (!groupId) return position === 'center' ? undefined : { direction: DIRECTIONS[position] };\n if (position === 'center') return tabIndex === undefined ? { referenceGroup: groupId, direction: 'within' } : { referenceGroup: groupId, direction: 'within', index: tabIndex };\n return { referenceGroup: groupId, direction: DIRECTIONS[position] };\n}\n"]}
@@ -0,0 +1,16 @@
1
+ export declare const SHELL_MESSAGES: {
2
+ readonly 'wb.account.notSignedIn': "Not signed in yet";
3
+ readonly 'wb.account.signedOut': "{handle} · signed out";
4
+ readonly 'wb.account.newName': "New account";
5
+ readonly 'wb.update.readyLabel': "Update ready · restart";
6
+ readonly 'wb.update.readyTitle': "Restart to update to {product} {version}. Tabs are restored.";
7
+ readonly 'wb.update.installingLabel': "Updating…";
8
+ readonly 'wb.update.installingTitle': "Installing {product} {version}";
9
+ readonly 'wb.update.problemLabel': "Update problem";
10
+ readonly 'wb.update.problemTitle': "The last update did not start correctly. Download the current version.";
11
+ };
12
+ export type ShellKey = keyof typeof SHELL_MESSAGES;
13
+ /** A translator for the shell models: the message for `key` (unformatted) or undefined for English. */
14
+ export type ShellText = (key: ShellKey) => string | undefined;
15
+ /** The message for `key` with `{name}` placeholders filled in (values inserted as text). */
16
+ export declare function shellText(key: ShellKey, params?: Record<string, string>, text?: ShellText): string;
@@ -0,0 +1,27 @@
1
+ // The shell models' own words (account labels, the update chip) in English, with `{name}`
2
+ // placeholders. They live in the framework catalogs (`waybetter/locales/<bcp47>.json`, `wb.*`), so
3
+ // every wayBetter app shows them in its language: pass a `text(key)` translator to the models; it
4
+ // returns the translated message (placeholders not yet filled) or undefined for English.
5
+ export const SHELL_MESSAGES = {
6
+ 'wb.account.notSignedIn': 'Not signed in yet',
7
+ 'wb.account.signedOut': '{handle} · signed out',
8
+ 'wb.account.newName': 'New account',
9
+ 'wb.update.readyLabel': 'Update ready · restart',
10
+ 'wb.update.readyTitle': 'Restart to update to {product} {version}. Tabs are restored.',
11
+ 'wb.update.installingLabel': 'Updating…',
12
+ 'wb.update.installingTitle': 'Installing {product} {version}',
13
+ 'wb.update.problemLabel': 'Update problem',
14
+ 'wb.update.problemTitle': 'The last update did not start correctly. Download the current version.',
15
+ };
16
+ /** The message for `key` with `{name}` placeholders filled in (values inserted as text). */
17
+ export function shellText(key, params = {}, text) {
18
+ let message = SHELL_MESSAGES[key];
19
+ try {
20
+ const translated = text?.(key);
21
+ if (typeof translated === 'string' && translated)
22
+ message = translated;
23
+ }
24
+ catch { /* English */ }
25
+ return message.replace(/\{(\w+)\}/g, (whole, name) => (name in params ? params[name] : whole));
26
+ }
27
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../../shell/src/messages.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,mGAAmG;AACnG,kGAAkG;AAClG,yFAAyF;AAEzF,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,wBAAwB,EAAE,mBAAmB;IAC7C,sBAAsB,EAAE,uBAAuB;IAC/C,oBAAoB,EAAE,aAAa;IACnC,sBAAsB,EAAE,wBAAwB;IAChD,sBAAsB,EAAE,8DAA8D;IACtF,2BAA2B,EAAE,WAAW;IACxC,2BAA2B,EAAE,gCAAgC;IAC7D,wBAAwB,EAAE,gBAAgB;IAC1C,wBAAwB,EAAE,wEAAwE;CAC1F,CAAC;AAKX,4FAA4F;AAC5F,MAAM,UAAU,SAAS,CAAC,GAAa,EAAE,SAAiC,EAAE,EAAE,IAAgB;IAC5F,IAAI,OAAO,GAAW,cAAc,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU;YAAE,OAAO,GAAG,UAAU,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;IACzB,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1G,CAAC","sourcesContent":["// The shell models' own words (account labels, the update chip) in English, with `{name}`\n// placeholders. They live in the framework catalogs (`waybetter/locales/<bcp47>.json`, `wb.*`), so\n// every wayBetter app shows them in its language: pass a `text(key)` translator to the models; it\n// returns the translated message (placeholders not yet filled) or undefined for English.\n\nexport const SHELL_MESSAGES = {\n 'wb.account.notSignedIn': 'Not signed in yet',\n 'wb.account.signedOut': '{handle} · signed out',\n 'wb.account.newName': 'New account',\n 'wb.update.readyLabel': 'Update ready · restart',\n 'wb.update.readyTitle': 'Restart to update to {product} {version}. Tabs are restored.',\n 'wb.update.installingLabel': 'Updating…',\n 'wb.update.installingTitle': 'Installing {product} {version}',\n 'wb.update.problemLabel': 'Update problem',\n 'wb.update.problemTitle': 'The last update did not start correctly. Download the current version.',\n} as const;\nexport type ShellKey = keyof typeof SHELL_MESSAGES;\n/** A translator for the shell models: the message for `key` (unformatted) or undefined for English. */\nexport type ShellText = (key: ShellKey) => string | undefined;\n\n/** The message for `key` with `{name}` placeholders filled in (values inserted as text). */\nexport function shellText(key: ShellKey, params: Record<string, string> = {}, text?: ShellText): string {\n let message: string = SHELL_MESSAGES[key];\n try {\n const translated = text?.(key);\n if (typeof translated === 'string' && translated) message = translated;\n } catch { /* English */ }\n return message.replace(/\\{(\\w+)\\}/g, (whole, name: string) => (name in params ? params[name]! : whole));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"palette.js","sourceRoot":"","sources":["../../../shell/src/palette.ts"],"names":[],"mappings":"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","sourcesContent":["// Command palette core: fuzzy scoring, ranking and selection movement. The app builds its own\n// items (tabs, profiles, settings sections, site destinations); every item is navigation only.\n\nexport type RankedItem = { label: string; keywords?: string; group: string };\n\n/** Subsequence match, case-insensitive. 0 = no match; prefix/word-start/consecutive hits score higher. */\nexport function fuzzyScore(target: string, query: string): number {\n const t = target.toLowerCase();\n const q = query.toLowerCase().replace(/\\s+/g, ' ').trim();\n if (!q) return 1;\n if (!t) return 0;\n if (t.startsWith(q)) return 1000 - t.length;\n const at = t.indexOf(q);\n if (at >= 0) return 600 - at - t.length / 10 + (/[\\s/_-]/.test(t[at - 1] ?? ' ') ? 100 : 0);\n let score = 0;\n let ti = 0;\n let previous = -2;\n for (const char of q) {\n if (char === ' ') continue;\n const found = t.indexOf(char, ti);\n if (found < 0) return 0;\n score += 10;\n if (found === previous + 1) score += 15;\n if (found === 0 || /[\\s/_-]/.test(t[found - 1]!)) score += 20;\n previous = found;\n ti = found + 1;\n }\n return Math.max(1, score - t.length / 10);\n}\n\n/** An item's score: its label, or half of its keywords/group match. */\nexport function scoreItem(item: RankedItem, query: string): number {\n const label = fuzzyScore(item.label, query);\n const extra = Math.max(fuzzyScore(item.keywords ?? '', query), fuzzyScore(item.group, query)) * 0.5;\n return Math.max(label, extra);\n}\n\n/** Matching items, best first; equal scores keep their original order. `skip` items never match. */\nexport function rankItems<T extends RankedItem>(items: readonly T[], query: string, skip: (item: T) => boolean = () => false): T[] {\n return items\n .map((item, index) => ({ item, index, score: skip(item) ? 0 : scoreItem(item, query) }))\n .filter(entry => entry.score > 0)\n .sort((a, b) => b.score - a.score || a.index - b.index)\n .map(entry => entry.item);\n}\n\n/** Wraps selection movement within the list. */\nexport const moveSelection = (index: number, step: number, length: number) =>\n length === 0 ? 0 : (index + step + length) % length;\n"]}
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../../../../../shell/src/palette.ts"],"names":[],"mappings":"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","sourcesContent":["// Command palette core: fuzzy scoring, ranking and selection movement. The app builds its own\n// items (tabs, profiles, settings sections, site destinations); every item is navigation only.\n\nexport type RankedItem = { label: string; keywords?: string; group: string };\n\n/** Subsequence match, case-insensitive. 0 = no match; prefix/word-start/consecutive hits score higher. */\nexport function fuzzyScore(target: string, query: string): number {\n const t = target.toLowerCase();\n const q = query.toLowerCase().replace(/\\s+/g, ' ').trim();\n if (!q) return 1;\n if (!t) return 0;\n if (t.startsWith(q)) return 1000 - t.length;\n const at = t.indexOf(q);\n if (at >= 0) return 600 - at - t.length / 10 + (/[\\s/_-]/.test(t[at - 1] ?? ' ') ? 100 : 0);\n let score = 0;\n let ti = 0;\n let previous = -2;\n for (const char of q) {\n if (char === ' ') continue;\n const found = t.indexOf(char, ti);\n if (found < 0) return 0;\n score += 10;\n if (found === previous + 1) score += 15;\n if (found === 0 || /[\\s/_-]/.test(t[found - 1]!)) score += 20;\n previous = found;\n ti = found + 1;\n }\n return Math.max(1, score - t.length / 10);\n}\n\n/** An item's score: its label, or half of its keywords/group match. */\nexport function scoreItem(item: RankedItem, query: string): number {\n const label = fuzzyScore(item.label, query);\n const extra = Math.max(fuzzyScore(item.keywords ?? '', query), fuzzyScore(item.group, query)) * 0.5;\n return Math.max(label, extra);\n}\n\n/** Matching items, best first; equal scores keep their original order. `skip` items never match. */\nexport function rankItems<T extends RankedItem>(items: readonly T[], query: string, skip: (item: T) => boolean = () => false): T[] {\n return items\n .map((item, index) => ({ item, index, score: skip(item) ? 0 : scoreItem(item, query) }))\n .filter(entry => entry.score > 0)\n .sort((a, b) => b.score - a.score || a.index - b.index)\n .map(entry => entry.item);\n}\n\n/** Wraps selection movement within the list. */\nexport const moveSelection = (index: number, step: number, length: number) =>\n length === 0 ? 0 : (index + step + length) % length;\n"]}
@@ -1,3 +1,5 @@
1
+ /** `role`: 'column' boxes are deck columns (Power User Mode); they hide the site's chrome themselves
2
+ * and never take part in the rail rules. Missing = an ordinary pane. */
1
3
  export type PaneBox = {
2
4
  id: string;
3
5
  url: string;
@@ -5,6 +7,7 @@ export type PaneBox = {
5
7
  x: number;
6
8
  y: number;
7
9
  visible: boolean;
10
+ role?: 'pane' | 'column';
8
11
  };
9
12
  /** `besideOf`: the source group ids whose "beside" links this group's tabs were opened for. */
10
13
  export type GroupBox = {
@@ -31,3 +34,22 @@ export declare function redundantNavPanes(panes: readonly PaneBox[], isSiteUrl:
31
34
  export declare function withNavRedundant<T extends PaneBox>(boxes: readonly T[], isSiteUrl: (url: string) => boolean, memory: Map<string, boolean>): Array<T & {
32
35
  navRedundant: boolean;
33
36
  }>;
37
+ /**
38
+ * A tab webview's `visible`/`parked` for `tabs_sync`. `shown`: its pane is on screen in the shell;
39
+ * `overlay`: shell overlays open (menus, dialogs, palette, drags); `raiseSupported`: the shell can
40
+ * be raised above the tab webviews for them (`shell_raise`), so panes stay visible under
41
+ * the overlay. Where it cannot, an overlay hides every tab (the shell would draw under them). An
42
+ * overlay never parks (drops to low memory) a tab: only a pane that is not shown is parked.
43
+ */
44
+ export declare function paneVisibility(pane: {
45
+ shown: boolean;
46
+ overlay: number;
47
+ raiseSupported: boolean;
48
+ }): {
49
+ visible: boolean;
50
+ parked: boolean;
51
+ };
52
+ /** `shell_raise`'s startup probe (`probe`: its answer) unless the developer switch turned raising off. */
53
+ export declare function raiseSupported(probe: unknown, devOff: boolean): boolean;
54
+ /** `[r, g, b]` of a computed CSS color (`rgb(...)`/`rgba(...)`), or null (unparsable or fully transparent). */
55
+ export declare function cssRgb(color: string): [number, number, number] | null;
@@ -26,7 +26,7 @@ export function redundantNavPanes(panes, isSiteUrl) {
26
26
  const lead = new Map();
27
27
  const redundant = new Set();
28
28
  const ordered = panes
29
- .filter(pane => pane.visible && isSiteUrl(pane.url))
29
+ .filter(pane => pane.visible && pane.role !== 'column' && isSiteUrl(pane.url))
30
30
  .sort((a, b) => a.x - b.x || a.y - b.y || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
31
31
  for (const pane of ordered) {
32
32
  if (lead.has(pane.profile))
@@ -53,4 +53,27 @@ export function withNavRedundant(boxes, isSiteUrl, memory) {
53
53
  memory.delete(id);
54
54
  return items;
55
55
  }
56
+ /**
57
+ * A tab webview's `visible`/`parked` for `tabs_sync`. `shown`: its pane is on screen in the shell;
58
+ * `overlay`: shell overlays open (menus, dialogs, palette, drags); `raiseSupported`: the shell can
59
+ * be raised above the tab webviews for them (`shell_raise`), so panes stay visible under
60
+ * the overlay. Where it cannot, an overlay hides every tab (the shell would draw under them). An
61
+ * overlay never parks (drops to low memory) a tab: only a pane that is not shown is parked.
62
+ */
63
+ export function paneVisibility(pane) {
64
+ return { visible: pane.shown && (pane.raiseSupported || pane.overlay === 0), parked: !pane.shown };
65
+ }
66
+ /** `shell_raise`'s startup probe (`probe`: its answer) unless the developer switch turned raising off. */
67
+ export function raiseSupported(probe, devOff) {
68
+ return probe === true && !devOff;
69
+ }
70
+ /** `[r, g, b]` of a computed CSS color (`rgb(...)`/`rgba(...)`), or null (unparsable or fully transparent). */
71
+ export function cssRgb(color) {
72
+ const parts = /^rgba?\(([^)]+)\)$/.exec(color.trim())?.[1]?.split(/[\s,/]+/).filter(Boolean).map(Number);
73
+ if (!parts || parts.length < 3 || parts.slice(0, 3).some(n => !Number.isFinite(n)))
74
+ return null;
75
+ if (parts.length > 3 && parts[3] === 0)
76
+ return null;
77
+ return [0, 1, 2].map(i => Math.max(0, Math.min(255, Math.round(parts[i]))));
78
+ }
56
79
  //# sourceMappingURL=paneModel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paneModel.js","sourceRoot":"","sources":["../../../shell/src/paneModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pane geometry rules for the dock: where a link opened \"beside\" a pane goes, and which site panes\n// repeat a navigation rail already on screen. Two site panes of the same account side by side (or\n// stacked) both draw the site's rail; only the leftmost (then topmost) one needs it. Panes of\n// different accounts keep theirs: the rail's account button is the only in-page sign of which\n// account a pane is.\n\nexport type PaneBox = { id: string; url: string; profile: string; x: number; y: number; visible: boolean };\n\n/** `besideOf`: the source group ids whose \"beside\" links this group's tabs were opened for. */\nexport type GroupBox = { id: string; left: number; top: number; right: number; bottom: number; besideOf?: readonly string[] };\n\n/**\n * Where a link opened \"beside\" a pane goes: the side pane this source opened before (so repeated\n * links reuse one), when it is still to its right and shares some of its height; else null to split\n * a new one. A group the user opened themselves (another feed, another account) is never taken over.\n */\nexport function besideGroup(source: GroupBox, groups: readonly GroupBox[]): string | null {\n let best: GroupBox | null = null;\n for (const group of groups) {\n if (group.id === source.id || !group.besideOf?.includes(source.id)) continue;\n const overlap = Math.min(group.bottom, source.bottom) - Math.max(group.top, source.top);\n if (group.left < source.right - 4 || overlap <= 0) continue;\n if (!best || group.left < best.left || (group.left === best.left && group.top < best.top)) best = group;\n }\n return best?.id ?? null;\n}\n\n/** Ids of visible site panes whose navigation duplicates the leftmost site pane of the same account. */\nexport function redundantNavPanes(panes: readonly PaneBox[], isSiteUrl: (url: string) => boolean): Set<string> {\n const lead = new Map<string, PaneBox>();\n const redundant = new Set<string>();\n const ordered = panes\n .filter(pane => pane.visible && isSiteUrl(pane.url))\n .sort((a, b) => a.x - b.x || a.y - b.y || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n for (const pane of ordered) {\n if (lead.has(pane.profile)) redundant.add(pane.id);\n else lead.set(pane.profile, pane);\n }\n return redundant;\n}\n\n/**\n * The `navRedundant` flag per tab for `tabs_sync`. Only visible panes are judged (a shell overlay\n * hides them all and so changes nothing); a hidden tab keeps its last value (`memory`) so it shows\n * up again without a flicker. Tabs that are gone are forgotten.\n */\nexport function withNavRedundant<T extends PaneBox>(boxes: readonly T[], isSiteUrl: (url: string) => boolean, memory: Map<string, boolean>): Array<T & { navRedundant: boolean }> {\n const redundant = redundantNavPanes(boxes, isSiteUrl);\n const items = boxes.map(box => {\n if (box.visible) memory.set(box.id, redundant.has(box.id));\n return { ...box, navRedundant: memory.get(box.id) ?? false };\n });\n for (const id of memory.keys()) if (!boxes.some(box => box.id === id)) memory.delete(id);\n return items;\n}\n"]}
1
+ {"version":3,"file":"paneModel.js","sourceRoot":"","sources":["../../../../../shell/src/paneModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pane geometry rules for the dock: where a link opened \"beside\" a pane goes, and which site panes\n// repeat a navigation rail already on screen. Two site panes of the same account side by side (or\n// stacked) both draw the site's rail; only the leftmost (then topmost) one needs it. Panes of\n// different accounts keep theirs: the rail's account button is the only in-page sign of which\n// account a pane is.\n\n/** `role`: 'column' boxes are deck columns (Power User Mode); they hide the site's chrome themselves\n * and never take part in the rail rules. Missing = an ordinary pane. */\nexport type PaneBox = { id: string; url: string; profile: string; x: number; y: number; visible: boolean; role?: 'pane' | 'column' };\n\n/** `besideOf`: the source group ids whose \"beside\" links this group's tabs were opened for. */\nexport type GroupBox = { id: string; left: number; top: number; right: number; bottom: number; besideOf?: readonly string[] };\n\n/**\n * Where a link opened \"beside\" a pane goes: the side pane this source opened before (so repeated\n * links reuse one), when it is still to its right and shares some of its height; else null to split\n * a new one. A group the user opened themselves (another feed, another account) is never taken over.\n */\nexport function besideGroup(source: GroupBox, groups: readonly GroupBox[]): string | null {\n let best: GroupBox | null = null;\n for (const group of groups) {\n if (group.id === source.id || !group.besideOf?.includes(source.id)) continue;\n const overlap = Math.min(group.bottom, source.bottom) - Math.max(group.top, source.top);\n if (group.left < source.right - 4 || overlap <= 0) continue;\n if (!best || group.left < best.left || (group.left === best.left && group.top < best.top)) best = group;\n }\n return best?.id ?? null;\n}\n\n/** Ids of visible site panes whose navigation duplicates the leftmost site pane of the same account. */\nexport function redundantNavPanes(panes: readonly PaneBox[], isSiteUrl: (url: string) => boolean): Set<string> {\n const lead = new Map<string, PaneBox>();\n const redundant = new Set<string>();\n const ordered = panes\n .filter(pane => pane.visible && pane.role !== 'column' && isSiteUrl(pane.url))\n .sort((a, b) => a.x - b.x || a.y - b.y || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n for (const pane of ordered) {\n if (lead.has(pane.profile)) redundant.add(pane.id);\n else lead.set(pane.profile, pane);\n }\n return redundant;\n}\n\n/**\n * The `navRedundant` flag per tab for `tabs_sync`. Only visible panes are judged (a shell overlay\n * hides them all and so changes nothing); a hidden tab keeps its last value (`memory`) so it shows\n * up again without a flicker. Tabs that are gone are forgotten.\n */\nexport function withNavRedundant<T extends PaneBox>(boxes: readonly T[], isSiteUrl: (url: string) => boolean, memory: Map<string, boolean>): Array<T & { navRedundant: boolean }> {\n const redundant = redundantNavPanes(boxes, isSiteUrl);\n const items = boxes.map(box => {\n if (box.visible) memory.set(box.id, redundant.has(box.id));\n return { ...box, navRedundant: memory.get(box.id) ?? false };\n });\n for (const id of memory.keys()) if (!boxes.some(box => box.id === id)) memory.delete(id);\n return items;\n}\n\n/**\n * A tab webview's `visible`/`parked` for `tabs_sync`. `shown`: its pane is on screen in the shell;\n * `overlay`: shell overlays open (menus, dialogs, palette, drags); `raiseSupported`: the shell can\n * be raised above the tab webviews for them (`shell_raise`), so panes stay visible under\n * the overlay. Where it cannot, an overlay hides every tab (the shell would draw under them). An\n * overlay never parks (drops to low memory) a tab: only a pane that is not shown is parked.\n */\nexport function paneVisibility(pane: { shown: boolean; overlay: number; raiseSupported: boolean }): { visible: boolean; parked: boolean } {\n return { visible: pane.shown && (pane.raiseSupported || pane.overlay === 0), parked: !pane.shown };\n}\n\n/** `shell_raise`'s startup probe (`probe`: its answer) unless the developer switch turned raising off. */\nexport function raiseSupported(probe: unknown, devOff: boolean): boolean {\n return probe === true && !devOff;\n}\n\n/** `[r, g, b]` of a computed CSS color (`rgb(...)`/`rgba(...)`), or null (unparsable or fully transparent). */\nexport function cssRgb(color: string): [number, number, number] | null {\n const parts = /^rgba?\\(([^)]+)\\)$/.exec(color.trim())?.[1]?.split(/[\\s,/]+/).filter(Boolean).map(Number);\n if (!parts || parts.length < 3 || parts.slice(0, 3).some(n => !Number.isFinite(n))) return null;\n if (parts.length > 3 && parts[3] === 0) return null;\n return [0, 1, 2].map(i => Math.max(0, Math.min(255, Math.round(parts[i]!)))) as [number, number, number];\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { type ThemeSpec } from '../../runtime/themeSpec.ts';
2
+ import { type Notify } from './site.ts';
3
+ import './builder.css';
4
+ /** Built-in themes have translated descriptions (`theme.<id>.description` in the app's catalog); imported ones keep their own. */
5
+ export declare const themeDescription: (theme: ThemeSpec) => string;
6
+ export declare function Appearance({ notify }: {
7
+ notify: Notify;
8
+ }): import("react").JSX.Element | null;