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,181 @@
1
+ import { type StoreText } from './storeMessages.ts';
2
+ import type { StringsInfo } from './stringPacksModel.ts';
3
+ export type InstallKind = 'theme' | 'plugin' | 'strings';
4
+ export type SourceKind = 'store' | 'link' | 'file';
5
+ export type PermissionTone = 'plain' | 'warn' | 'ok';
6
+ export type PermissionBadge = {
7
+ id: string;
8
+ label: string;
9
+ detail: string;
10
+ tone: PermissionTone;
11
+ };
12
+ /** A store catalog item (waybetter-host `CatalogItem`; the catalog format is documented in docs/STORE.md). */
13
+ export type StoreItem = {
14
+ /** The wayBetter apps it is for; native code only hands an app its own items. */
15
+ apps?: string[];
16
+ kind: InstallKind;
17
+ id: string;
18
+ name: string;
19
+ author: string;
20
+ version: string;
21
+ description: string;
22
+ category: string;
23
+ tags: string[];
24
+ url: string;
25
+ file?: string;
26
+ sha256: string;
27
+ size: number;
28
+ preview?: string;
29
+ permissions?: string[] | null;
30
+ colors?: {
31
+ bg: string;
32
+ surface?: string;
33
+ text: string;
34
+ accent: string;
35
+ } | null;
36
+ /** String packs: the pack's language tag. */
37
+ language?: string;
38
+ /** Any kind: its licence and who made, translated or reviewed it. */
39
+ license?: string;
40
+ credits?: string;
41
+ };
42
+ export type InstallRecord = {
43
+ kind: InstallKind;
44
+ source: SourceKind;
45
+ url?: string;
46
+ storeId?: string;
47
+ version: string;
48
+ sha256: string;
49
+ installedAt: string;
50
+ };
51
+ export type InstalledPlugin = {
52
+ version: string;
53
+ sha256: string;
54
+ enabled: boolean;
55
+ };
56
+ /** What `store_catalog` returns (waybetter-host `StoreView`): this app's items and what is installed. */
57
+ export type StoreCatalogView = {
58
+ catalog: {
59
+ format?: number;
60
+ name: string;
61
+ generatedAt: string;
62
+ items: StoreItem[];
63
+ } | null;
64
+ fetchedAt: string | null;
65
+ error: string | null;
66
+ plugins: Record<string, InstalledPlugin>;
67
+ records: {
68
+ items: Record<string, InstallRecord>;
69
+ };
70
+ };
71
+ export type ScriptPluginMeta = {
72
+ file: string;
73
+ name: string;
74
+ description: string;
75
+ version: string;
76
+ author: string;
77
+ enabled: boolean;
78
+ permissions: string[] | null;
79
+ problems?: string[];
80
+ };
81
+ /** What `install_stage_*` / `store_stage` return (waybetter-host `InstallPreview`). */
82
+ export type InstallPreview = {
83
+ token: string;
84
+ kind: InstallKind;
85
+ source: {
86
+ kind: SourceKind;
87
+ url: string | null;
88
+ label: string;
89
+ signed: boolean;
90
+ };
91
+ sha256: string;
92
+ size: number;
93
+ file: string | null;
94
+ /** The exact text that will be written. */
95
+ text: string;
96
+ version: string;
97
+ plugin: ScriptPluginMeta | null;
98
+ theme: {
99
+ name: string;
100
+ author: string;
101
+ description: string;
102
+ cssChars: number;
103
+ } | null;
104
+ /** String packs: what the pack says about itself (coverage comes from the site's inventory). */
105
+ strings?: StringsInfo | null;
106
+ findings: string[];
107
+ existing: {
108
+ version: string;
109
+ enabled: boolean;
110
+ same: boolean;
111
+ } | null;
112
+ store: StoreItem | null;
113
+ };
114
+ /** The `install-link` event and `install_pending` entries (waybetter-host `LinkEvent`). */
115
+ export type LinkEvent = {
116
+ link?: {
117
+ kind: InstallKind;
118
+ url: string;
119
+ };
120
+ error?: string;
121
+ setup?: string;
122
+ };
123
+ /** Plugin permissions (waybetter-host `PERMISSIONS`, runtime `permissions.ts`) and how much they allow. */
124
+ export declare const PERMISSION_TONES: Readonly<Record<string, PermissionTone>>;
125
+ /** Badges for a plugin's declared permissions; `null` = no `@permissions` line (legacy). `site`: the site's name. */
126
+ export declare function permissionBadges(permissions: readonly string[] | null | undefined, t: StoreText, site: string): PermissionBadge[];
127
+ /** A store category's name (`wb.store.category.<id>`); unknown ones show their id. */
128
+ export declare function categoryLabel(id: string, t: StoreText): string;
129
+ /** What a dropped file is, by name: `.plugin.js` → plugin, `.strings.json` → string pack, `.json` → theme, else nothing. */
130
+ export declare function kindForFile(name: string): InstallKind | null;
131
+ /** Largest file the shell reads before handing it to native validation (same caps as native). */
132
+ export declare const MAX_FILE_BYTES: Readonly<Record<InstallKind, number>>;
133
+ /** A free theme id: `wanted`, else `wanted-2`, `-3`, … (the way an import names copies). */
134
+ export declare function freeThemeId(wanted: string, taken: Iterable<string>): string;
135
+ /** `a` newer than `b` (numeric dot parts; same rule as native `newer_version`). */
136
+ export declare function newerVersion(a: string, b: string): boolean;
137
+ export type ItemState = {
138
+ state: 'install';
139
+ } | {
140
+ state: 'builtin';
141
+ } | {
142
+ state: 'installed';
143
+ version: string;
144
+ enabled?: boolean;
145
+ } | {
146
+ state: 'update';
147
+ version: string;
148
+ enabled?: boolean;
149
+ }
150
+ /** Installed but changed locally (edited file, or a copy from somewhere else): the store leaves it alone unless asked. */
151
+ | {
152
+ state: 'modified';
153
+ version: string;
154
+ enabled?: boolean;
155
+ };
156
+ export type ItemContext = {
157
+ plugins: Record<string, InstalledPlugin>;
158
+ records: Record<string, InstallRecord>;
159
+ /** Theme ids that ship with the app (a store copy of one is "built in"). */
160
+ builtinThemes: readonly string[];
161
+ /** The owner's own theme ids right now. */
162
+ userThemes: readonly string[];
163
+ };
164
+ /**
165
+ * Where a store item stands on this machine. Plugins: by their file in the plugins folder.
166
+ * Themes: built-in ids are part of the app; otherwise the install record for a theme the owner
167
+ * still has.
168
+ */
169
+ export declare function itemState(item: StoreItem, context: ItemContext): ItemState;
170
+ /** The installed user theme id a store theme item was installed as (for updates in place). */
171
+ export declare function installedThemeId(item: StoreItem, records: Record<string, InstallRecord>, userThemes: readonly string[]): string | null;
172
+ /** Search and category filter for the store list. */
173
+ export declare function filterItems(items: readonly StoreItem[], query: string, kind: InstallKind | 'all', category: string | 'all'): StoreItem[];
174
+ export declare const formatBytes: (bytes: number) => string;
175
+ /** Lines of a preview with their numbers, the first `limit` only unless `all`. */
176
+ export declare function previewLines(text: string, limit: number, all?: boolean): {
177
+ lines: string[];
178
+ hidden: number;
179
+ };
180
+ /** An error from a native command, without its `CODE: ` prefix. */
181
+ export declare const errorText: (error: unknown) => string;
@@ -0,0 +1,133 @@
1
+ // The wayBetter Store and install screen, pure part: the wire types of the native store commands
2
+ // (waybetter-host `store`), what each plugin permission means, where a dropped file goes, which id a
3
+ // new theme gets, whether a store item is installed, current or has an update, search, and preview
4
+ // lines. Native code validates everything again; nothing here decides what may be installed.
5
+ import { STORE_MESSAGES } from "./storeMessages.js";
6
+ /** Plugin permissions (waybetter-host `PERMISSIONS`, runtime `permissions.ts`) and how much they allow. */
7
+ export const PERMISSION_TONES = {
8
+ storage: 'plain',
9
+ ui: 'plain',
10
+ clipboard: 'plain',
11
+ account: 'warn',
12
+ commands: 'plain',
13
+ users: 'warn',
14
+ network: 'warn',
15
+ 'network:none': 'ok',
16
+ };
17
+ /** `t(key)` for a key assembled at runtime, or `fallback` when the framework has no such message. */
18
+ function lookup(t, key, params, fallback) {
19
+ return key in STORE_MESSAGES ? t(key, params) : fallback;
20
+ }
21
+ /** Badges for a plugin's declared permissions; `null` = no `@permissions` line (legacy). `site`: the site's name. */
22
+ export function permissionBadges(permissions, t, site) {
23
+ if (permissions == null)
24
+ return [{ id: 'legacy', label: t('wb.permission.legacy.label'), detail: t('wb.permission.legacy.detail'), tone: 'warn' }];
25
+ if (permissions.length === 0)
26
+ return [{ id: 'none', label: t('wb.permission.none.label'), detail: t('wb.permission.none.detail'), tone: 'ok' }];
27
+ return permissions.map(id => {
28
+ const tone = PERMISSION_TONES[id];
29
+ if (!tone)
30
+ return { id, label: id, detail: t('wb.permission.unknown'), tone: 'warn' };
31
+ const name = id.replace(':none', 'None');
32
+ return { id, label: lookup(t, `wb.permission.${name}.label`, undefined, id), detail: lookup(t, `wb.permission.${name}.detail`, { site }, ''), tone };
33
+ });
34
+ }
35
+ /** A store category's name (`wb.store.category.<id>`); unknown ones show their id. */
36
+ export function categoryLabel(id, t) {
37
+ return lookup(t, `wb.store.category.${id}`, undefined, id);
38
+ }
39
+ /** What a dropped file is, by name: `.plugin.js` → plugin, `.strings.json` → string pack, `.json` → theme, else nothing. */
40
+ export function kindForFile(name) {
41
+ const lower = name.toLowerCase();
42
+ if (lower.endsWith('.plugin.js'))
43
+ return 'plugin';
44
+ if (lower.endsWith('.strings.json'))
45
+ return 'strings';
46
+ if (lower.endsWith('.json'))
47
+ return 'theme';
48
+ return null;
49
+ }
50
+ /** Largest file the shell reads before handing it to native validation (same caps as native). */
51
+ export const MAX_FILE_BYTES = { theme: 2 * 1024 * 1024, plugin: 2 * 1024 * 1024, strings: 2 * 1024 * 1024 };
52
+ /** A free theme id: `wanted`, else `wanted-2`, `-3`, … (the way an import names copies). */
53
+ export function freeThemeId(wanted, taken) {
54
+ const used = new Set(taken);
55
+ if (!used.has(wanted))
56
+ return wanted;
57
+ for (let n = 2;; n += 1) {
58
+ const id = `${wanted.slice(0, 36)}-${n}`;
59
+ if (!used.has(id))
60
+ return id;
61
+ }
62
+ }
63
+ /** `a` newer than `b` (numeric dot parts; same rule as native `newer_version`). */
64
+ export function newerVersion(a, b) {
65
+ const parts = (value) => value.split(/[.+-]/).map(part => Number.parseInt(part, 10) || 0);
66
+ const [x, y] = [parts(a), parts(b)];
67
+ for (let i = 0; i < Math.max(x.length, y.length); i += 1) {
68
+ const [p, q] = [x[i] ?? 0, y[i] ?? 0];
69
+ if (p !== q)
70
+ return p > q;
71
+ }
72
+ return false;
73
+ }
74
+ /**
75
+ * Where a store item stands on this machine. Plugins: by their file in the plugins folder.
76
+ * Themes: built-in ids are part of the app; otherwise the install record for a theme the owner
77
+ * still has.
78
+ */
79
+ export function itemState(item, context) {
80
+ if (item.kind === 'plugin') {
81
+ const installed = item.file ? context.plugins[item.file] : undefined;
82
+ if (!installed)
83
+ return { state: 'install' };
84
+ const base = { version: installed.version, enabled: installed.enabled };
85
+ if (installed.sha256 === item.sha256)
86
+ return { state: 'installed', ...base };
87
+ if (newerVersion(item.version, installed.version))
88
+ return { state: 'update', ...base };
89
+ return { state: 'modified', ...base };
90
+ }
91
+ if (item.kind === 'strings') {
92
+ const record = context.records[`strings:${item.id}`];
93
+ if (!record)
94
+ return { state: 'install' };
95
+ if (record.sha256 === item.sha256)
96
+ return { state: 'installed', version: record.version };
97
+ return newerVersion(item.version, record.version) ? { state: 'update', version: record.version } : { state: 'installed', version: record.version };
98
+ }
99
+ if (context.builtinThemes.includes(item.id))
100
+ return { state: 'builtin' };
101
+ const id = installedThemeId(item, context.records, context.userThemes);
102
+ if (!id)
103
+ return { state: 'install' };
104
+ const value = context.records[`theme:${id}`];
105
+ if (value.sha256 === item.sha256)
106
+ return { state: 'installed', version: value.version };
107
+ return newerVersion(item.version, value.version) ? { state: 'update', version: value.version } : { state: 'installed', version: value.version };
108
+ }
109
+ /** The installed user theme id a store theme item was installed as (for updates in place). */
110
+ export function installedThemeId(item, records, userThemes) {
111
+ for (const [key, value] of Object.entries(records)) {
112
+ if (key.startsWith('theme:') && value.storeId === item.id && userThemes.includes(key.slice(6)))
113
+ return key.slice(6);
114
+ }
115
+ return null;
116
+ }
117
+ /** Search and category filter for the store list. */
118
+ export function filterItems(items, query, kind, category) {
119
+ const words = query.toLowerCase().split(/\s+/).filter(Boolean);
120
+ return items.filter(item => (kind === 'all' || item.kind === kind) && (category === 'all' || item.category === category)
121
+ && words.every(word => [item.name, item.description, item.author, item.category, item.language ?? '', ...item.tags, ...(item.permissions ?? [])].join(' ').toLowerCase().includes(word)));
122
+ }
123
+ export const formatBytes = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(2)} MB`;
124
+ /** Lines of a preview with their numbers, the first `limit` only unless `all`. */
125
+ export function previewLines(text, limit, all = false) {
126
+ const lines = text.replace(/\r\n?/g, '\n').split('\n');
127
+ if (all || lines.length <= limit)
128
+ return { lines, hidden: 0 };
129
+ return { lines: lines.slice(0, limit), hidden: lines.length - limit };
130
+ }
131
+ /** An error from a native command, without its `CODE: ` prefix. */
132
+ export const errorText = (error) => (error instanceof Error ? error.message : String(error)).replace(/^[A-Z]+: /, '');
133
+ //# sourceMappingURL=storeModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storeModel.js","sourceRoot":"","sources":["../../../../../shell/src/storeModel.ts"],"names":[],"mappings":"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","sourcesContent":["// The wayBetter Store and install screen, pure part: the wire types of the native store commands\n// (waybetter-host `store`), what each plugin permission means, where a dropped file goes, which id a\n// new theme gets, whether a store item is installed, current or has an update, search, and preview\n// lines. Native code validates everything again; nothing here decides what may be installed.\n\nimport { STORE_MESSAGES, type StoreKey, type StoreText } from './storeMessages.ts';\nimport type { StringsInfo } from './stringPacksModel.ts';\n\nexport type InstallKind = 'theme' | 'plugin' | 'strings';\nexport type SourceKind = 'store' | 'link' | 'file';\nexport type PermissionTone = 'plain' | 'warn' | 'ok';\nexport type PermissionBadge = { id: string; label: string; detail: string; tone: PermissionTone };\n\n/** A store catalog item (waybetter-host `CatalogItem`; the catalog format is documented in docs/STORE.md). */\nexport type StoreItem = {\n /** The wayBetter apps it is for; native code only hands an app its own items. */\n apps?: string[];\n kind: InstallKind; id: string; name: string; author: string; version: string; description: string;\n category: string; tags: string[]; url: string; file?: string; sha256: string; size: number;\n preview?: string; permissions?: string[] | null; colors?: { bg: string; surface?: string; text: string; accent: string } | null;\n /** String packs: the pack's language tag. */\n language?: string;\n /** Any kind: its licence and who made, translated or reviewed it. */\n license?: string; credits?: string;\n};\nexport type InstallRecord = { kind: InstallKind; source: SourceKind; url?: string; storeId?: string; version: string; sha256: string; installedAt: string };\nexport type InstalledPlugin = { version: string; sha256: string; enabled: boolean };\n\n/** What `store_catalog` returns (waybetter-host `StoreView`): this app's items and what is installed. */\nexport type StoreCatalogView = {\n catalog: { format?: number; name: string; generatedAt: string; items: StoreItem[] } | null;\n fetchedAt: string | null;\n error: string | null;\n plugins: Record<string, InstalledPlugin>;\n records: { items: Record<string, InstallRecord> };\n};\n\nexport type ScriptPluginMeta = {\n file: string; name: string; description: string; version: string; author: string; enabled: boolean;\n permissions: string[] | null; problems?: string[];\n};\n\n/** What `install_stage_*` / `store_stage` return (waybetter-host `InstallPreview`). */\nexport type InstallPreview = {\n token: string;\n kind: InstallKind;\n source: { kind: SourceKind; url: string | null; label: string; signed: boolean };\n sha256: string;\n size: number;\n file: string | null;\n /** The exact text that will be written. */\n text: string;\n version: string;\n plugin: ScriptPluginMeta | null;\n theme: { name: string; author: string; description: string; cssChars: number } | null;\n /** String packs: what the pack says about itself (coverage comes from the site's inventory). */\n strings?: StringsInfo | null;\n findings: string[];\n existing: { version: string; enabled: boolean; same: boolean } | null;\n store: StoreItem | null;\n};\n\n/** The `install-link` event and `install_pending` entries (waybetter-host `LinkEvent`). */\nexport type LinkEvent = { link?: { kind: InstallKind; url: string }; error?: string; setup?: string };\n\n/** Plugin permissions (waybetter-host `PERMISSIONS`, runtime `permissions.ts`) and how much they allow. */\nexport const PERMISSION_TONES: Readonly<Record<string, PermissionTone>> = {\n storage: 'plain',\n ui: 'plain',\n clipboard: 'plain',\n account: 'warn',\n commands: 'plain',\n users: 'warn',\n network: 'warn',\n 'network:none': 'ok',\n};\n\n/** `t(key)` for a key assembled at runtime, or `fallback` when the framework has no such message. */\nfunction lookup(t: StoreText, key: string, params: Record<string, string> | undefined, fallback: string): string {\n return key in STORE_MESSAGES ? t(key as StoreKey, params) : fallback;\n}\n\n/** Badges for a plugin's declared permissions; `null` = no `@permissions` line (legacy). `site`: the site's name. */\nexport function permissionBadges(permissions: readonly string[] | null | undefined, t: StoreText, site: string): PermissionBadge[] {\n if (permissions == null) return [{ id: 'legacy', label: t('wb.permission.legacy.label'), detail: t('wb.permission.legacy.detail'), tone: 'warn' }];\n if (permissions.length === 0) return [{ id: 'none', label: t('wb.permission.none.label'), detail: t('wb.permission.none.detail'), tone: 'ok' }];\n return permissions.map(id => {\n const tone = PERMISSION_TONES[id];\n if (!tone) return { id, label: id, detail: t('wb.permission.unknown'), tone: 'warn' as const };\n const name = id.replace(':none', 'None');\n return { id, label: lookup(t, `wb.permission.${name}.label`, undefined, id), detail: lookup(t, `wb.permission.${name}.detail`, { site }, ''), tone };\n });\n}\n\n/** A store category's name (`wb.store.category.<id>`); unknown ones show their id. */\nexport function categoryLabel(id: string, t: StoreText): string {\n return lookup(t, `wb.store.category.${id}`, undefined, id);\n}\n\n/** What a dropped file is, by name: `.plugin.js` → plugin, `.strings.json` → string pack, `.json` → theme, else nothing. */\nexport function kindForFile(name: string): InstallKind | null {\n const lower = name.toLowerCase();\n if (lower.endsWith('.plugin.js')) return 'plugin';\n if (lower.endsWith('.strings.json')) return 'strings';\n if (lower.endsWith('.json')) return 'theme';\n return null;\n}\n\n/** Largest file the shell reads before handing it to native validation (same caps as native). */\nexport const MAX_FILE_BYTES: Readonly<Record<InstallKind, number>> = { theme: 2 * 1024 * 1024, plugin: 2 * 1024 * 1024, strings: 2 * 1024 * 1024 };\n\n/** A free theme id: `wanted`, else `wanted-2`, `-3`, … (the way an import names copies). */\nexport function freeThemeId(wanted: string, taken: Iterable<string>): string {\n const used = new Set(taken);\n if (!used.has(wanted)) return wanted;\n for (let n = 2; ; n += 1) {\n const id = `${wanted.slice(0, 36)}-${n}`;\n if (!used.has(id)) return id;\n }\n}\n\n/** `a` newer than `b` (numeric dot parts; same rule as native `newer_version`). */\nexport function newerVersion(a: string, b: string): boolean {\n const parts = (value: string) => value.split(/[.+-]/).map(part => Number.parseInt(part, 10) || 0);\n const [x, y] = [parts(a), parts(b)];\n for (let i = 0; i < Math.max(x.length, y.length); i += 1) {\n const [p, q] = [x[i] ?? 0, y[i] ?? 0];\n if (p !== q) return p > q;\n }\n return false;\n}\n\nexport type ItemState =\n | { state: 'install' }\n | { state: 'builtin' }\n | { state: 'installed'; version: string; enabled?: boolean }\n | { state: 'update'; version: string; enabled?: boolean }\n /** Installed but changed locally (edited file, or a copy from somewhere else): the store leaves it alone unless asked. */\n | { state: 'modified'; version: string; enabled?: boolean };\n\nexport type ItemContext = {\n plugins: Record<string, InstalledPlugin>;\n records: Record<string, InstallRecord>;\n /** Theme ids that ship with the app (a store copy of one is \"built in\"). */\n builtinThemes: readonly string[];\n /** The owner's own theme ids right now. */\n userThemes: readonly string[];\n};\n\n/**\n * Where a store item stands on this machine. Plugins: by their file in the plugins folder.\n * Themes: built-in ids are part of the app; otherwise the install record for a theme the owner\n * still has.\n */\nexport function itemState(item: StoreItem, context: ItemContext): ItemState {\n if (item.kind === 'plugin') {\n const installed = item.file ? context.plugins[item.file] : undefined;\n if (!installed) return { state: 'install' };\n const base = { version: installed.version, enabled: installed.enabled };\n if (installed.sha256 === item.sha256) return { state: 'installed', ...base };\n if (newerVersion(item.version, installed.version)) return { state: 'update', ...base };\n return { state: 'modified', ...base };\n }\n if (item.kind === 'strings') {\n const record = context.records[`strings:${item.id}`];\n if (!record) return { state: 'install' };\n if (record.sha256 === item.sha256) return { state: 'installed', version: record.version };\n return newerVersion(item.version, record.version) ? { state: 'update', version: record.version } : { state: 'installed', version: record.version };\n }\n if (context.builtinThemes.includes(item.id)) return { state: 'builtin' };\n const id = installedThemeId(item, context.records, context.userThemes);\n if (!id) return { state: 'install' };\n const value = context.records[`theme:${id}`]!;\n if (value.sha256 === item.sha256) return { state: 'installed', version: value.version };\n return newerVersion(item.version, value.version) ? { state: 'update', version: value.version } : { state: 'installed', version: value.version };\n}\n\n/** The installed user theme id a store theme item was installed as (for updates in place). */\nexport function installedThemeId(item: StoreItem, records: Record<string, InstallRecord>, userThemes: readonly string[]): string | null {\n for (const [key, value] of Object.entries(records)) {\n if (key.startsWith('theme:') && value.storeId === item.id && userThemes.includes(key.slice(6))) return key.slice(6);\n }\n return null;\n}\n\n/** Search and category filter for the store list. */\nexport function filterItems(items: readonly StoreItem[], query: string, kind: InstallKind | 'all', category: string | 'all'): StoreItem[] {\n const words = query.toLowerCase().split(/\\s+/).filter(Boolean);\n return items.filter(item => (kind === 'all' || item.kind === kind) && (category === 'all' || item.category === category)\n && words.every(word => [item.name, item.description, item.author, item.category, item.language ?? '', ...item.tags, ...(item.permissions ?? [])].join(' ').toLowerCase().includes(word)));\n}\n\nexport const formatBytes = (bytes: number) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n\n/** Lines of a preview with their numbers, the first `limit` only unless `all`. */\nexport function previewLines(text: string, limit: number, all = false): { lines: string[]; hidden: number } {\n const lines = text.replace(/\\r\\n?/g, '\\n').split('\\n');\n if (all || lines.length <= limit) return { lines, hidden: 0 };\n return { lines: lines.slice(0, limit), hidden: lines.length - limit };\n}\n\n/** An error from a native command, without its `CODE: ` prefix. */\nexport const errorText = (error: unknown) => (error instanceof Error ? error.message : String(error)).replace(/^[A-Z]+: /, '');\n"]}
@@ -0,0 +1,44 @@
1
+ import { type PageInventory } from '../runtime/stringPacks.ts';
2
+ /** What `strings_list` returns per pack (waybetter-host `InstalledStrings`). */
3
+ export type InstalledStrings = {
4
+ id: string;
5
+ site: string;
6
+ catalog: string;
7
+ language: string;
8
+ name: string;
9
+ authors: string[];
10
+ version: string;
11
+ description: string;
12
+ strings: number;
13
+ sha256: string;
14
+ enabled: boolean;
15
+ };
16
+ /** The pack as the install screen gets it from native code (waybetter-host `StringsInfo`). */
17
+ export type StringsInfo = Omit<InstalledStrings, 'id' | 'sha256' | 'enabled'>;
18
+ export type StringsSummary = {
19
+ language: string;
20
+ /** Strings of the site the pack replaces / strings a pack can replace. */
21
+ translated: number;
22
+ translatable: number;
23
+ /** Keys the site has but no pack can replace yet (rich text, formatters). */
24
+ closed: number;
25
+ /** Keys the site does not have: ignored. */
26
+ unknown: number;
27
+ /** Values that do not fit the site's own string (parameters, plural forms, markup): not used. */
28
+ refused: number;
29
+ /** A few of the pack's own texts, for the screen. */
30
+ sample: string[];
31
+ /** The pack is for another catalog of the site than this inventory. */
32
+ otherCatalog: boolean;
33
+ };
34
+ /** Coverage and a sample of a pack's text; `null` when the text is not a pack at all. */
35
+ export declare function packSummary(text: string, inventory: PageInventory): StringsSummary | null;
36
+ /** `translated / translatable` as a percentage with one decimal. */
37
+ export declare const coveragePercent: (summary: Pick<StringsSummary, "translated" | "translatable">) => string;
38
+ /**
39
+ * What the site tabs get: the texts of the packs that are on, in application order, with the slice
40
+ * of the inventory their keys need. `null` when no usable pack is on (the tabs then drop theirs).
41
+ */
42
+ export declare function buildDelivery(texts: readonly string[], inventory: PageInventory, options?: {
43
+ translate?: boolean;
44
+ }): string | null;
@@ -0,0 +1,94 @@
1
+ // String packs in the shell, pure part (waybetter/docs/STRING-PACKS.md): what the install screen and
2
+ // the Languages section say about a pack (coverage against the site's inventory, what is ignored, a
3
+ // sample), and the delivery the site tabs get (the packs that are on, in order, with the slice of the
4
+ // inventory their keys need). Native code only keeps the data; it never sees the inventory.
5
+ import { compilePack, inventoryLookup, sliceInventory, translatable, } from "../runtime/stringPacks.js";
6
+ const MAX_SAMPLE = 6;
7
+ /** Coverage and a sample of a pack's text; `null` when the text is not a pack at all. */
8
+ export function packSummary(text, inventory) {
9
+ let pack;
10
+ try {
11
+ pack = JSON.parse(text);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ const record = pack;
17
+ if (!record || typeof record !== 'object' || typeof record.strings !== 'object' || record.strings === null)
18
+ return null;
19
+ const language = typeof record.language === 'string' ? record.language : '';
20
+ const lookup = inventoryLookup(inventory);
21
+ let translatableCount = 0;
22
+ let closed = 0;
23
+ // The page inventory lists every key once, in its groups: count what a pack can replace.
24
+ for (const ids of [inventory.text, inventory.closed])
25
+ if (ids)
26
+ for (const id of ids.split(' ')) {
27
+ if (lookup(id) && translatable(lookup(id).kind))
28
+ translatableCount += 1;
29
+ else
30
+ closed += 1;
31
+ }
32
+ translatableCount += Object.keys(inventory.message).length;
33
+ if (record.catalog !== inventory.catalog) {
34
+ return { language, translated: 0, translatable: translatableCount, closed, unknown: Object.keys(record.strings).length, refused: 0, sample: [], otherCatalog: true };
35
+ }
36
+ let compiled;
37
+ try {
38
+ compiled = compilePack(pack, inventory);
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ const sample = [];
44
+ for (const [id, value] of Object.entries(record.strings)) {
45
+ if (sample.length >= MAX_SAMPLE)
46
+ break;
47
+ if (compiled.values.has(id) && typeof value === 'string' && !value.includes('{') && value.length <= 40)
48
+ sample.push(value);
49
+ }
50
+ return {
51
+ language, translated: compiled.values.size, translatable: translatableCount, closed,
52
+ unknown: compiled.report.unknown.length, refused: compiled.report.rejected.length, sample, otherCatalog: false,
53
+ };
54
+ }
55
+ /** `translated / translatable` as a percentage with one decimal. */
56
+ export const coveragePercent = (summary) => summary.translatable ? `${(Math.round(summary.translated / summary.translatable * 1000) / 10).toFixed(1)}%` : '0%';
57
+ /**
58
+ * What the site tabs get: the texts of the packs that are on, in application order, with the slice
59
+ * of the inventory their keys need. `null` when no usable pack is on (the tabs then drop theirs).
60
+ */
61
+ export function buildDelivery(texts, inventory, options = {}) {
62
+ const packs = [];
63
+ const ids = new Set();
64
+ for (const text of texts) {
65
+ let pack;
66
+ try {
67
+ pack = JSON.parse(text);
68
+ }
69
+ catch {
70
+ continue;
71
+ }
72
+ let compiled;
73
+ try {
74
+ compiled = compilePack(pack, inventory);
75
+ }
76
+ catch {
77
+ continue;
78
+ }
79
+ if (!compiled.values.size)
80
+ continue;
81
+ packs.push(pack);
82
+ for (const id of compiled.values.keys())
83
+ ids.add(id);
84
+ if (packs.length >= 8)
85
+ break;
86
+ }
87
+ // Translate mode: the whole inventory (the author may change any string), packs or not.
88
+ if (options.translate)
89
+ return JSON.stringify({ inventory, packs, translate: true });
90
+ if (!packs.length)
91
+ return null;
92
+ return JSON.stringify({ inventory: sliceInventory(inventory, ids), packs });
93
+ }
94
+ //# sourceMappingURL=stringPacksModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringPacksModel.js","sourceRoot":"","sources":["../../../../../shell/src/stringPacksModel.ts"],"names":[],"mappings":"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","sourcesContent":["// String packs in the shell, pure part (waybetter/docs/STRING-PACKS.md): what the install screen and\n// the Languages section say about a pack (coverage against the site's inventory, what is ignored, a\n// sample), and the delivery the site tabs get (the packs that are on, in order, with the slice of the\n// inventory their keys need). Native code only keeps the data; it never sees the inventory.\nimport {\n compilePack, inventoryLookup, sliceInventory, translatable, type PageInventory,\n} from '../../runtime/src/stringPacks.ts';\n\n/** What `strings_list` returns per pack (waybetter-host `InstalledStrings`). */\nexport type InstalledStrings = {\n id: string; site: string; catalog: string; language: string; name: string; authors: string[];\n version: string; description: string; strings: number; sha256: string; enabled: boolean;\n};\n/** The pack as the install screen gets it from native code (waybetter-host `StringsInfo`). */\nexport type StringsInfo = Omit<InstalledStrings, 'id' | 'sha256' | 'enabled'>;\n\nexport type StringsSummary = {\n language: string;\n /** Strings of the site the pack replaces / strings a pack can replace. */\n translated: number;\n translatable: number;\n /** Keys the site has but no pack can replace yet (rich text, formatters). */\n closed: number;\n /** Keys the site does not have: ignored. */\n unknown: number;\n /** Values that do not fit the site's own string (parameters, plural forms, markup): not used. */\n refused: number;\n /** A few of the pack's own texts, for the screen. */\n sample: string[];\n /** The pack is for another catalog of the site than this inventory. */\n otherCatalog: boolean;\n};\n\nconst MAX_SAMPLE = 6;\n\n/** Coverage and a sample of a pack's text; `null` when the text is not a pack at all. */\nexport function packSummary(text: string, inventory: PageInventory): StringsSummary | null {\n let pack: unknown;\n try { pack = JSON.parse(text); } catch { return null; }\n const record = pack as { catalog?: unknown; language?: unknown; strings?: unknown };\n if (!record || typeof record !== 'object' || typeof record.strings !== 'object' || record.strings === null) return null;\n const language = typeof record.language === 'string' ? record.language : '';\n const lookup = inventoryLookup(inventory);\n let translatableCount = 0;\n let closed = 0;\n // The page inventory lists every key once, in its groups: count what a pack can replace.\n for (const ids of [inventory.text, inventory.closed]) if (ids) for (const id of ids.split(' ')) { if (lookup(id) && translatable(lookup(id)!.kind)) translatableCount += 1; else closed += 1; }\n translatableCount += Object.keys(inventory.message).length;\n if (record.catalog !== inventory.catalog) {\n return { language, translated: 0, translatable: translatableCount, closed, unknown: Object.keys(record.strings).length, refused: 0, sample: [], otherCatalog: true };\n }\n let compiled;\n try { compiled = compilePack(pack, inventory); } catch { return null; }\n const sample: string[] = [];\n for (const [id, value] of Object.entries(record.strings as Record<string, unknown>)) {\n if (sample.length >= MAX_SAMPLE) break;\n if (compiled.values.has(id) && typeof value === 'string' && !value.includes('{') && value.length <= 40) sample.push(value);\n }\n return {\n language, translated: compiled.values.size, translatable: translatableCount, closed,\n unknown: compiled.report.unknown.length, refused: compiled.report.rejected.length, sample, otherCatalog: false,\n };\n}\n\n/** `translated / translatable` as a percentage with one decimal. */\nexport const coveragePercent = (summary: Pick<StringsSummary, 'translated' | 'translatable'>) =>\n summary.translatable ? `${(Math.round(summary.translated / summary.translatable * 1000) / 10).toFixed(1)}%` : '0%';\n\n/**\n * What the site tabs get: the texts of the packs that are on, in application order, with the slice\n * of the inventory their keys need. `null` when no usable pack is on (the tabs then drop theirs).\n */\nexport function buildDelivery(texts: readonly string[], inventory: PageInventory, options: { translate?: boolean } = {}): string | null {\n const packs: unknown[] = [];\n const ids = new Set<string>();\n for (const text of texts) {\n let pack: unknown;\n try { pack = JSON.parse(text); } catch { continue; }\n let compiled;\n try { compiled = compilePack(pack, inventory); } catch { continue; }\n if (!compiled.values.size) continue;\n packs.push(pack);\n for (const id of compiled.values.keys()) ids.add(id);\n if (packs.length >= 8) break;\n }\n // Translate mode: the whole inventory (the author may change any string), packs or not.\n if (options.translate) return JSON.stringify({ inventory, packs, translate: true });\n if (!packs.length) return null;\n return JSON.stringify({ inventory: sliceInventory(inventory, ids), packs });\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type ShellText } from './messages.ts';
1
2
  /** Mirrors `UpdateStatus` in waybetter-host `update.rs` (serde tag "state"). */
2
3
  export type UpdateStatus = {
3
4
  state: 'idle' | 'checking' | 'upToDate';
@@ -32,4 +33,4 @@ export type UpdateChip = {
32
33
  /** Accepts only well-formed status payloads; anything else is treated as idle. */
33
34
  export declare function parseUpdateStatus(value: unknown): UpdateStatus;
34
35
  /** Unobtrusive: nothing while checking/downloading/erroring; a chip only when action is useful. */
35
- export declare function chipFor(status: UpdateStatus, product: string): UpdateChip | null;
36
+ export declare function chipFor(status: UpdateStatus, product: string, text?: ShellText): UpdateChip | null;
@@ -1,4 +1,5 @@
1
1
  // Pure model for the titlebar update chip (no Tauri imports, so it is unit-tested under node).
2
+ import { shellText } from "./messages.js";
2
3
  const STATES = new Set(['idle', 'checking', 'upToDate', 'downloading', 'installing', 'ready', 'error', 'problem']);
3
4
  /** Accepts only well-formed status payloads; anything else is treated as idle. */
4
5
  export function parseUpdateStatus(value) {
@@ -21,11 +22,11 @@ export function parseUpdateStatus(value) {
21
22
  }
22
23
  }
23
24
  /** Unobtrusive: nothing while checking/downloading/erroring; a chip only when action is useful. */
24
- export function chipFor(status, product) {
25
+ export function chipFor(status, product, text) {
25
26
  switch (status.state) {
26
- case 'ready': return { kind: 'restart', label: 'Update ready · restart', title: `Restart to update to ${product} ${status.version}. Tabs are restored.` };
27
- case 'installing': return { kind: 'installing', label: 'Updating…', title: `Installing ${product} ${status.version}` };
28
- case 'problem': return { kind: 'problem', label: 'Update problem', title: 'The last update did not start correctly. Download the current version.', href: status.downloadUrl };
27
+ case 'ready': return { kind: 'restart', label: shellText('wb.update.readyLabel', {}, text), title: shellText('wb.update.readyTitle', { product, version: status.version }, text) };
28
+ case 'installing': return { kind: 'installing', label: shellText('wb.update.installingLabel', {}, text), title: shellText('wb.update.installingTitle', { product, version: status.version }, text) };
29
+ case 'problem': return { kind: 'problem', label: shellText('wb.update.problemLabel', {}, text), title: shellText('wb.update.problemTitle', {}, text), href: status.downloadUrl };
29
30
  default: return null;
30
31
  }
31
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"updateModel.js","sourceRoot":"","sources":["../../../shell/src/updateModel.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAe/F,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AAEnH,kFAAkF;AAClF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClE,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClF,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,GAAG,CAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpF,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAChB,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACtF,KAAK,aAAa,CAAC;QAAC,KAAK,YAAY,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1F,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;YAChC,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACnG,CAAC;QACD,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAyC,EAAE,CAAC;IACzE,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,OAAO,CAAC,MAAoB,EAAE,OAAe;IAC3D,QAAQ,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,wBAAwB,OAAO,IAAI,MAAM,CAAC,OAAO,sBAAsB,EAAE,CAAC;QAC1J,KAAK,YAAY,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QACvH,KAAK,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,wEAAwE,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QAC/K,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC;IACvB,CAAC;AACH,CAAC","sourcesContent":["// Pure model for the titlebar update chip (no Tauri imports, so it is unit-tested under node).\n\n/** Mirrors `UpdateStatus` in waybetter-host `update.rs` (serde tag \"state\"). */\nexport type UpdateStatus =\n | { state: 'idle' | 'checking' | 'upToDate' }\n | { state: 'downloading' | 'installing'; version: string }\n | { state: 'ready'; version: string; notes: string }\n | { state: 'error'; message: string }\n | { state: 'problem'; downloadUrl: string };\n\nexport type UpdateChip =\n | { kind: 'restart'; label: string; title: string }\n | { kind: 'installing'; label: string; title: string }\n | { kind: 'problem'; label: string; title: string; href: string };\n\nconst STATES = new Set(['idle', 'checking', 'upToDate', 'downloading', 'installing', 'ready', 'error', 'problem']);\n\n/** Accepts only well-formed status payloads; anything else is treated as idle. */\nexport function parseUpdateStatus(value: unknown): UpdateStatus {\n if (!value || typeof value !== 'object') return { state: 'idle' };\n const v = value as Record<string, unknown>;\n if (typeof v.state !== 'string' || !STATES.has(v.state)) return { state: 'idle' };\n const str = (key: string) => (typeof v[key] === 'string' ? (v[key] as string) : '');\n switch (v.state) {\n case 'ready': return { state: 'ready', version: str('version'), notes: str('notes') };\n case 'downloading': case 'installing': return { state: v.state, version: str('version') };\n case 'error': return { state: 'error', message: str('message') };\n case 'problem': {\n const href = str('downloadUrl');\n return href.startsWith('https://') ? { state: 'problem', downloadUrl: href } : { state: 'idle' };\n }\n default: return { state: v.state as 'idle' | 'checking' | 'upToDate' };\n }\n}\n\n/** Unobtrusive: nothing while checking/downloading/erroring; a chip only when action is useful. */\nexport function chipFor(status: UpdateStatus, product: string): UpdateChip | null {\n switch (status.state) {\n case 'ready': return { kind: 'restart', label: 'Update ready · restart', title: `Restart to update to ${product} ${status.version}. Tabs are restored.` };\n case 'installing': return { kind: 'installing', label: 'Updating…', title: `Installing ${product} ${status.version}` };\n case 'problem': return { kind: 'problem', label: 'Update problem', title: 'The last update did not start correctly. Download the current version.', href: status.downloadUrl };\n default: return null;\n }\n}\n"]}
1
+ {"version":3,"file":"updateModel.js","sourceRoot":"","sources":["../../../../../shell/src/updateModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure model for the titlebar update chip (no Tauri imports, so it is unit-tested under node).\n\nimport { shellText, type ShellText } from './messages.ts';\n\n/** Mirrors `UpdateStatus` in waybetter-host `update.rs` (serde tag \"state\"). */\nexport type UpdateStatus =\n | { state: 'idle' | 'checking' | 'upToDate' }\n | { state: 'downloading' | 'installing'; version: string }\n | { state: 'ready'; version: string; notes: string }\n | { state: 'error'; message: string }\n | { state: 'problem'; downloadUrl: string };\n\nexport type UpdateChip =\n | { kind: 'restart'; label: string; title: string }\n | { kind: 'installing'; label: string; title: string }\n | { kind: 'problem'; label: string; title: string; href: string };\n\nconst STATES = new Set(['idle', 'checking', 'upToDate', 'downloading', 'installing', 'ready', 'error', 'problem']);\n\n/** Accepts only well-formed status payloads; anything else is treated as idle. */\nexport function parseUpdateStatus(value: unknown): UpdateStatus {\n if (!value || typeof value !== 'object') return { state: 'idle' };\n const v = value as Record<string, unknown>;\n if (typeof v.state !== 'string' || !STATES.has(v.state)) return { state: 'idle' };\n const str = (key: string) => (typeof v[key] === 'string' ? (v[key] as string) : '');\n switch (v.state) {\n case 'ready': return { state: 'ready', version: str('version'), notes: str('notes') };\n case 'downloading': case 'installing': return { state: v.state, version: str('version') };\n case 'error': return { state: 'error', message: str('message') };\n case 'problem': {\n const href = str('downloadUrl');\n return href.startsWith('https://') ? { state: 'problem', downloadUrl: href } : { state: 'idle' };\n }\n default: return { state: v.state as 'idle' | 'checking' | 'upToDate' };\n }\n}\n\n/** Unobtrusive: nothing while checking/downloading/erroring; a chip only when action is useful. */\nexport function chipFor(status: UpdateStatus, product: string, text?: ShellText): UpdateChip | null {\n switch (status.state) {\n case 'ready': return { kind: 'restart', label: shellText('wb.update.readyLabel', {}, text), title: shellText('wb.update.readyTitle', { product, version: status.version }, text) };\n case 'installing': return { kind: 'installing', label: shellText('wb.update.installingLabel', {}, text), title: shellText('wb.update.installingTitle', { product, version: status.version }, text) };\n case 'problem': return { kind: 'problem', label: shellText('wb.update.problemLabel', {}, text), title: shellText('wb.update.problemTitle', {}, text), href: status.downloadUrl };\n default: return null;\n }\n}\n"]}
@@ -5,6 +5,8 @@ export type NativeWindow = {
5
5
  toggleMaximize(): Promise<void>;
6
6
  close(): Promise<void>;
7
7
  startResizeDragging(direction: ResizeDirection): Promise<void>;
8
+ /** Moves the window with the pointer (the titlebar logo, once a press on it becomes a drag). */
9
+ startDragging?(): Promise<void>;
8
10
  isMaximized(): Promise<boolean>;
9
11
  onResized(handler: () => void): Promise<() => void>;
10
12
  };
@@ -18,6 +20,8 @@ export declare function createWindowControls(invoke: Invoke, currentWindow: () =
18
20
  toggleMaximize: () => Promise<void>;
19
21
  close: () => Promise<void>;
20
22
  startResize: (direction: ResizeDirection) => Promise<void>;
23
+ /** Starts a native window move while the pointer is down (nothing where the app's window lacks it, or in a preview). */
24
+ startDrag: () => void;
21
25
  onMaximizedChange: (cb: (maximized: boolean) => void) => Promise<() => void>;
22
26
  /** The native system menu at a screen position (host `system_menu`; Windows only). */
23
27
  systemMenu: (x: number, y: number) => Promise<unknown>;
@@ -10,6 +10,11 @@ export function createWindowControls(invoke, currentWindow) {
10
10
  toggleMaximize: () => currentWindow().toggleMaximize().catch(() => { }),
11
11
  close: () => currentWindow().close().catch(() => { }),
12
12
  startResize: (direction) => currentWindow().startResizeDragging(direction).catch(() => { }),
13
+ /** Starts a native window move while the pointer is down (nothing where the app's window lacks it, or in a preview). */
14
+ startDrag: () => { try {
15
+ void currentWindow().startDragging?.().catch(() => { });
16
+ }
17
+ catch { /* No native window. */ } },
13
18
  onMaximizedChange: (cb) => {
14
19
  const read = () => { currentWindow().isMaximized().then(cb).catch(() => { }); };
15
20
  read();
@@ -1 +1 @@
1
- {"version":3,"file":"windowControls.js","sourceRoot":"","sources":["../../../shell/src/windowControls.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,8FAA8F;AAe9F,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,WAAW,IAAI,qBAAqB,IAAI,MAAM,CAAC;AACxF,mHAAmH;AACnH,MAAM,CAAC,MAAM,EAAE,GAAwB,OAAO,SAAS,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAClI,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,IAAI,EAAE,KAAK,OAAO,CAAC;AAEnD,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,aAAiC;IACpF,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC1D,cAAc,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QACtE,KAAK,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QACpD,WAAW,EAAE,CAAC,SAA0B,EAAE,EAAE,CAAC,aAAa,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC3G,iBAAiB,EAAE,CAAC,EAAgC,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,EAAE,CAAC;YACP,OAAO,aAAa,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,sFAAsF;QACtF,UAAU,EAAE,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;KAC7F,CAAC;AACJ,CAAC","sourcesContent":["// Native window calls for the custom titlebar, resize grips and caption buttons. The Tauri API is\n// passed in (the app owns its `@tauri-apps/api` version), so this module has no dependencies.\n\nexport type ResizeDirection = 'North' | 'South' | 'East' | 'West' | 'NorthEast' | 'NorthWest' | 'SouthEast' | 'SouthWest';\n\n/** The subset of Tauri's `Window` the shell uses. */\nexport type NativeWindow = {\n minimize(): Promise<void>;\n toggleMaximize(): Promise<void>;\n close(): Promise<void>;\n startResizeDragging(direction: ResizeDirection): Promise<void>;\n isMaximized(): Promise<boolean>;\n onResized(handler: () => void): Promise<() => void>;\n};\nexport type Invoke = (command: string, args?: Record<string, unknown>) => Promise<unknown>;\n\nexport const isTauri = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;\n/** macOS keeps a native (overlay) frame with traffic lights; Windows is frameless with our own caption buttons. */\nexport const os: 'macos' | 'windows' = typeof navigator !== 'undefined' && /Mac/i.test(navigator.userAgent) ? 'macos' : 'windows';\nexport const frameless = isTauri && os !== 'macos';\n\nexport function createWindowControls(invoke: Invoke, currentWindow: () => NativeWindow) {\n return {\n minimize: () => currentWindow().minimize().catch(() => {}),\n toggleMaximize: () => currentWindow().toggleMaximize().catch(() => {}),\n close: () => currentWindow().close().catch(() => {}),\n startResize: (direction: ResizeDirection) => currentWindow().startResizeDragging(direction).catch(() => {}),\n onMaximizedChange: (cb: (maximized: boolean) => void) => {\n const read = () => { currentWindow().isMaximized().then(cb).catch(() => {}); };\n read();\n return currentWindow().onResized(read);\n },\n /** The native system menu at a screen position (host `system_menu`; Windows only). */\n systemMenu: (x: number, y: number) => invoke('window_system_menu', { x, y }).catch(() => {}),\n };\n}\n"]}
1
+ {"version":3,"file":"windowControls.js","sourceRoot":"","sources":["../../../../../shell/src/windowControls.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,8FAA8F;AAiB9F,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,WAAW,IAAI,qBAAqB,IAAI,MAAM,CAAC;AACxF,mHAAmH;AACnH,MAAM,CAAC,MAAM,EAAE,GAAwB,OAAO,SAAS,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAClI,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,IAAI,EAAE,KAAK,OAAO,CAAC;AAEnD,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,aAAiC;IACpF,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC1D,cAAc,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QACtE,KAAK,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QACpD,WAAW,EAAE,CAAC,SAA0B,EAAE,EAAE,CAAC,aAAa,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC3G,wHAAwH;QACxH,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YAAC,KAAK,aAAa,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;QACtH,iBAAiB,EAAE,CAAC,EAAgC,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,EAAE,CAAC;YACP,OAAO,aAAa,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,sFAAsF;QACtF,UAAU,EAAE,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;KAC7F,CAAC;AACJ,CAAC","sourcesContent":["// Native window calls for the custom titlebar, resize grips and caption buttons. The Tauri API is\n// passed in (the app owns its `@tauri-apps/api` version), so this module has no dependencies.\n\nexport type ResizeDirection = 'North' | 'South' | 'East' | 'West' | 'NorthEast' | 'NorthWest' | 'SouthEast' | 'SouthWest';\n\n/** The subset of Tauri's `Window` the shell uses. */\nexport type NativeWindow = {\n minimize(): Promise<void>;\n toggleMaximize(): Promise<void>;\n close(): Promise<void>;\n startResizeDragging(direction: ResizeDirection): Promise<void>;\n /** Moves the window with the pointer (the titlebar logo, once a press on it becomes a drag). */\n startDragging?(): Promise<void>;\n isMaximized(): Promise<boolean>;\n onResized(handler: () => void): Promise<() => void>;\n};\nexport type Invoke = (command: string, args?: Record<string, unknown>) => Promise<unknown>;\n\nexport const isTauri = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;\n/** macOS keeps a native (overlay) frame with traffic lights; Windows is frameless with our own caption buttons. */\nexport const os: 'macos' | 'windows' = typeof navigator !== 'undefined' && /Mac/i.test(navigator.userAgent) ? 'macos' : 'windows';\nexport const frameless = isTauri && os !== 'macos';\n\nexport function createWindowControls(invoke: Invoke, currentWindow: () => NativeWindow) {\n return {\n minimize: () => currentWindow().minimize().catch(() => {}),\n toggleMaximize: () => currentWindow().toggleMaximize().catch(() => {}),\n close: () => currentWindow().close().catch(() => {}),\n startResize: (direction: ResizeDirection) => currentWindow().startResizeDragging(direction).catch(() => {}),\n /** Starts a native window move while the pointer is down (nothing where the app's window lacks it, or in a preview). */\n startDrag: () => { try { void currentWindow().startDragging?.().catch(() => {}); } catch { /* No native window. */ } },\n onMaximizedChange: (cb: (maximized: boolean) => void) => {\n const read = () => { currentWindow().isMaximized().then(cb).catch(() => {}); };\n read();\n return currentWindow().onResized(read);\n },\n /** The native system menu at a screen position (host `system_menu`; Windows only). */\n systemMenu: (x: number, y: number) => invoke('window_system_menu', { x, y }).catch(() => {}),\n };\n}\n"]}