waybetter 0.1.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/README.md +143 -9
  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 +148 -6
  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,24 @@
1
+ import { type FeatureTable, type Flags } from '../../runtime/featureTable.ts';
2
+ import { type Notify } from './site.ts';
3
+ import './plugins.css';
4
+ /** The app's feature table (an app without one has no area cards). */
5
+ export declare const featureTable: () => FeatureTable | null;
6
+ /**
7
+ * The saved flags as a full map (defaults filled in) and a setter that shows a change at once,
8
+ * saves only what differs from the defaults and reverts when native code refuses it.
9
+ */
10
+ export declare function useFlags(table: FeatureTable, notify: Notify): [Flags | null, (patch: Flags) => Promise<boolean>, () => Promise<void>];
11
+ /** Tells every `useFlags` that the saved flags changed. */
12
+ export declare const flagsChanged: () => boolean;
13
+ /**
14
+ * Lines for the app menu's "Report a problem" summary (the frame's `ShellSite.menu.report.details`):
15
+ * the feature flags the focused site tab says paused themselves. Flag ids only.
16
+ */
17
+ export declare function reportDetails(): Array<{
18
+ label: string;
19
+ values: string[];
20
+ }>;
21
+ /** The area cards and the Fixes list. Renders nothing for an app without a feature table. */
22
+ export declare function AreaPlugins({ notify }: {
23
+ notify: Notify;
24
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,165 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Area plugins: one card per area of the app's feature table (runtime featureTable.ts), each with
3
+ // its switch, its features grouped with a toggle per feature, and a Settings button that opens the
4
+ // area's settings dialog in the site tab. Under the cards, the core flags as "Fixes": on in every
5
+ // mode, owned by no plugin. Flags are the host's (`features_get/set`, stored sparsely); a feature
6
+ // that is still an old plugin file is switched with `plugin_set_enabled`.
7
+ import { useEffect, useRef, useState } from 'react';
8
+ import { areaFlag, normalizeFlags, pausedFeatures, sparseFlags } from "../../runtime/featureTable.js";
9
+ import { invoke } from "../frame/bridge.js";
10
+ import { useT } from "../frame/hooks.js";
11
+ import { tx } from "../frame/i18n.js";
12
+ import { COMMANDS_CHANGED, focusedCommands, runPluginCommand } from "../frame/pluginCommandStore.js";
13
+ import { hasFeature } from "../frame/site.js";
14
+ import { Badge, Button, Row, Section, Toggle, matchesQuery, useSettingsQuery } from "./controls.js";
15
+ import { areaCards, fixRows, rowKeywords } from "./featureModel.js";
16
+ import { NavIcon } from "./NavIcon.js";
17
+ import { panelSite } from "./site.js";
18
+ import './plugins.css';
19
+ const getError = (error) => error instanceof Error ? error.message : String(error);
20
+ const AREA_ICON = 'M6 2.5v3M10 2.5v3M4 5.5h8V8a4 4 0 0 1-8 0zM8 12v1.5';
21
+ /** The app's feature table (an app without one has no area cards). */
22
+ export const featureTable = () => panelSite().features?.table ?? null;
23
+ /**
24
+ * The saved flags as a full map (defaults filled in) and a setter that shows a change at once,
25
+ * saves only what differs from the defaults and reverts when native code refuses it.
26
+ */
27
+ export function useFlags(table, notify) {
28
+ const [flags, setFlags] = useState(null);
29
+ const latest = useRef(null);
30
+ latest.current = flags;
31
+ const load = () => invoke('features_get').then(value => setFlags(normalizeFlags(table, value))).catch(err => notify(getError(err), true));
32
+ useEffect(() => {
33
+ void load();
34
+ // Another part of the panel changed them (a mode was chosen).
35
+ const again = () => void load();
36
+ window.addEventListener('wb-features-changed', again);
37
+ return () => window.removeEventListener('wb-features-changed', again);
38
+ }, []);
39
+ async function choose(patch) {
40
+ const before = latest.current;
41
+ if (!before)
42
+ return false;
43
+ const next = { ...before, ...patch };
44
+ setFlags(next);
45
+ try {
46
+ await invoke('features_set', { features: sparseFlags(table, next) });
47
+ return true;
48
+ }
49
+ catch (err) {
50
+ setFlags(before);
51
+ notify(getError(err), true);
52
+ return false;
53
+ }
54
+ }
55
+ return [flags, choose, load];
56
+ }
57
+ /** Tells every `useFlags` that the saved flags changed. */
58
+ export const flagsChanged = () => window.dispatchEvent(new CustomEvent('wb-features-changed'));
59
+ function usePluginFiles() {
60
+ const [plugins, setPlugins] = useState([]);
61
+ useEffect(() => {
62
+ const load = () => invoke('plugins_list').then(setPlugins).catch(() => { });
63
+ void load();
64
+ window.addEventListener('bt-plugins-changed', load);
65
+ return () => window.removeEventListener('bt-plugins-changed', load);
66
+ }, []);
67
+ return [plugins, setPlugins];
68
+ }
69
+ /** The flags the focused site tab says paused themselves (its area's `health` palette entry). */
70
+ function usePaused(table) {
71
+ const [paused, setPaused] = useState(() => pausedFeatures(table, focusedCommands()?.items));
72
+ useEffect(() => {
73
+ const read = () => setPaused(before => {
74
+ const next = pausedFeatures(table, focusedCommands()?.items);
75
+ return next.size === before.size && [...next].every(id => before.has(id)) ? before : next;
76
+ });
77
+ read();
78
+ window.addEventListener(COMMANDS_CHANGED, read);
79
+ return () => window.removeEventListener(COMMANDS_CHANGED, read);
80
+ }, [table]);
81
+ return paused;
82
+ }
83
+ /**
84
+ * Lines for the app menu's "Report a problem" summary (the frame's `ShellSite.menu.report.details`):
85
+ * the feature flags the focused site tab says paused themselves. Flag ids only.
86
+ */
87
+ export function reportDetails() {
88
+ const table = featureTable();
89
+ return table ? [{ label: 'Paused features', values: [...pausedFeatures(table, focusedCommands()?.items)].sort() }] : [];
90
+ }
91
+ /** The area cards and the Fixes list. Renders nothing for an app without a feature table. */
92
+ export function AreaPlugins({ notify }) {
93
+ const table = featureTable();
94
+ return table ? _jsx(AreaPluginsOf, { table: table, notify: notify }) : null;
95
+ }
96
+ function AreaPluginsOf({ table, notify }) {
97
+ const t = useT();
98
+ const query = useSettingsQuery().trim();
99
+ const [flags, choose] = useFlags(table, notify);
100
+ const [plugins, setPlugins] = usePluginFiles();
101
+ const [open, setOpen] = useState({});
102
+ const [asking, setAsking] = useState(null);
103
+ const paused = usePaused(table);
104
+ if (!flags)
105
+ return null;
106
+ const cards = areaCards(table, flags, plugins, paused);
107
+ const fixes = fixRows(table, flags, panelSite().features?.elsewhere);
108
+ const words = (row) => ({ label: tx(row.label, undefined, row.spec.id), description: tx(row.description, undefined, '') });
109
+ const shown = (row, card) => !query || matchesQuery(query, words(row).label, words(row).description, rowKeywords(row, card?.area));
110
+ async function setPlugin(file, enabled) {
111
+ try {
112
+ setPlugins(await invoke('plugin_set_enabled', { file, enabled }));
113
+ window.dispatchEvent(new CustomEvent('bt-plugins-changed'));
114
+ return true;
115
+ }
116
+ catch (err) {
117
+ notify(getError(err), true);
118
+ return false;
119
+ }
120
+ }
121
+ async function toggle(row, next) {
122
+ if (row.kind === 'plugin') {
123
+ await setPlugin(row.spec.file, next);
124
+ return;
125
+ }
126
+ // Never the owner's own copy of the old plugin and the built-in feature at once.
127
+ if (next && row.ownCopy?.enabled) {
128
+ setAsking(row.spec.id);
129
+ return;
130
+ }
131
+ await choose({ [row.spec.id]: next });
132
+ }
133
+ async function useBuiltIn(row) {
134
+ setAsking(null);
135
+ if (row.ownCopy && await setPlugin(row.ownCopy.file, false))
136
+ await choose({ [row.spec.id]: true });
137
+ }
138
+ function openSettings(card) {
139
+ const commands = focusedCommands();
140
+ const id = `${card.area.owner}:settings`;
141
+ if (commands?.items.some(item => item.id === id))
142
+ runPluginCommand(commands.tab, id);
143
+ else
144
+ notify(t('wb.features.settingsNoTab'), true);
145
+ }
146
+ const featureRow = (row, card) => {
147
+ if (!shown(row, card))
148
+ return null;
149
+ const text = words(row);
150
+ const copy = row.ownCopy;
151
+ const locked = row.missing || (!!card && !card.enabled && row.kind === 'flag');
152
+ return _jsx(Row, { label: text.label, keywords: `${rowKeywords(row, card?.area)} ${text.description}`, hint: _jsxs(_Fragment, { children: [text.description, row.paused && _jsx("span", { className: "wbf-note", children: t('wb.features.paused') }), copy && !row.on && _jsx("span", { className: "wbf-note", children: t('wb.features.ownCopy', { name: copy.name ?? copy.file }) }), asking === row.spec.id && copy && _jsxs("span", { className: "wbf-ask", role: "alertdialog", children: [t('wb.features.ownCopyAsk', { name: copy.name ?? copy.file }), _jsx(Button, { size: "sm", tone: "primary", onClick: () => void useBuiltIn(row), children: t('wb.features.useBuiltIn') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setAsking(null), children: t('wb.common.cancel') })] })] }), badge: _jsxs(_Fragment, { children: [row.paused && _jsx(Badge, { tone: "warn", children: t('wb.features.pausedBadge') }), row.isDefault && _jsx(Badge, { children: t('wb.features.default') }), card && row.spec.backing === 'app' && _jsx(Badge, { children: t('wb.features.inApp') }), row.kind === 'plugin' && _jsx(Badge, { tone: row.missing ? 'warn' : 'plain', children: row.missing ? t('wb.features.missing') : t('wb.features.pluginFile') })] }), children: _jsx(Toggle, { label: text.label, checked: row.on, disabled: locked, onChange: next => void toggle(row, next) }) }, row.spec.id);
153
+ };
154
+ const visibleCards = cards.filter(card => !query || card.rows.some(row => shown(row, card)));
155
+ return _jsxs(_Fragment, { children: [visibleCards.length > 0 && _jsx(Section, { title: t('wb.features.areas'), hint: query ? undefined : t('wb.features.areasHint'), id: "areas", children: visibleCards.map(card => {
156
+ const expanded = !!query || !!open[card.area.id];
157
+ return _jsxs("div", { className: `wbf-area ${card.enabled ? '' : 'is-off'}`, "data-area": card.area.id, children: [_jsxs("div", { className: "wbf-head", children: [_jsx("span", { className: "wbf-icon", "aria-hidden": "true", children: _jsx(NavIcon, { d: card.area.icon ?? AREA_ICON }) }), _jsxs("button", { type: "button", className: "wbf-title", "aria-expanded": expanded, disabled: card.total === 0, onClick: () => setOpen({ ...open, [card.area.id]: !expanded }), children: [_jsx("strong", { children: card.area.name }), card.total > 0 && _jsx("span", { className: "wbf-count", children: t('wb.features.count', { on: card.on, total: card.total }) }), _jsxs("small", { children: [card.enabled ? tx(card.area.description, undefined, '') : t('wb.features.off'), card.total === 0 && ` ${t('wb.features.soon')}`] })] }), card.total > 0 && _jsx("span", { className: `wbf-caret ${expanded ? 'is-open' : ''}`, "aria-hidden": "true", children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", children: _jsx("path", { d: "M3 4.5 6 7.5l3-3", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), card.paused > 0 && _jsx(Badge, { tone: "warn", children: t('wb.features.pausedBadge') }), card.settings && hasFeature('pluginCommands') && _jsx(Button, { size: "sm", tone: "ghost", onClick: () => openSettings(card), children: t('wb.panel.section.settings') }), _jsx(Toggle, { label: t('wb.plugins.enabled', { name: card.area.name }), checked: card.enabled, onChange: next => void choose({ [areaFlag(card.area.id)]: next }) })] }), expanded && _jsx("div", { className: "wbf-body", children: card.groups.map(group => {
158
+ const rows = group.rows.map(row => featureRow(row, card)).filter(Boolean);
159
+ if (!rows.length)
160
+ return null;
161
+ return _jsxs("div", { className: "wbf-group", children: [group.id && _jsx("h3", { children: tx(`features.group.${group.id}`, undefined, group.id) }), rows] }, group.id);
162
+ }) })] }, card.area.id);
163
+ }) }), fixes.some(row => shown(row)) && _jsx(Section, { title: t('wb.features.fixes'), hint: query ? undefined : t('wb.features.fixesHint'), id: "fixes", children: fixes.map(row => featureRow(row)) })] });
164
+ }
165
+ //# sourceMappingURL=PluginFeatures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginFeatures.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/PluginFeatures.tsx"],"names":[],"mappings":"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","sourcesContent":["// Area plugins: one card per area of the app's feature table (runtime featureTable.ts), each with\n// its switch, its features grouped with a toggle per feature, and a Settings button that opens the\n// area's settings dialog in the site tab. Under the cards, the core flags as \"Fixes\": on in every\n// mode, owned by no plugin. Flags are the host's (`features_get/set`, stored sparsely); a feature\n// that is still an old plugin file is switched with `plugin_set_enabled`.\nimport { useEffect, useRef, useState } from 'react';\nimport { areaFlag, normalizeFlags, pausedFeatures, sparseFlags, type FeatureTable, type Flags } from '../../../runtime/src/featureTable.ts';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { tx } from '../frame/i18n.ts';\nimport { COMMANDS_CHANGED, focusedCommands, runPluginCommand } from '../frame/pluginCommandStore.ts';\nimport { hasFeature } from '../frame/site.ts';\nimport { Badge, Button, Row, Section, Toggle, matchesQuery, useSettingsQuery } from './controls.tsx';\nimport { areaCards, fixRows, rowKeywords, type AreaCard, type FeatureRow, type PluginFileState } from './featureModel.ts';\nimport { NavIcon } from './NavIcon.tsx';\nimport { panelSite, type Notify } from './site.ts';\nimport './plugins.css';\n\nconst getError = (error: unknown) => error instanceof Error ? error.message : String(error);\nconst AREA_ICON = 'M6 2.5v3M10 2.5v3M4 5.5h8V8a4 4 0 0 1-8 0zM8 12v1.5';\n\n/** The app's feature table (an app without one has no area cards). */\nexport const featureTable = (): FeatureTable | null => panelSite().features?.table ?? null;\n\n/**\n * The saved flags as a full map (defaults filled in) and a setter that shows a change at once,\n * saves only what differs from the defaults and reverts when native code refuses it.\n */\nexport function useFlags(table: FeatureTable, notify: Notify): [Flags | null, (patch: Flags) => Promise<boolean>, () => Promise<void>] {\n const [flags, setFlags] = useState<Flags | null>(null);\n const latest = useRef<Flags | null>(null);\n latest.current = flags;\n const load = () => invoke<unknown>('features_get').then(value => setFlags(normalizeFlags(table, value))).catch(err => notify(getError(err), true));\n useEffect(() => {\n void load();\n // Another part of the panel changed them (a mode was chosen).\n const again = () => void load();\n window.addEventListener('wb-features-changed', again);\n return () => window.removeEventListener('wb-features-changed', again);\n }, []);\n async function choose(patch: Flags) {\n const before = latest.current;\n if (!before) return false;\n const next = { ...before, ...patch };\n setFlags(next);\n try { await invoke('features_set', { features: sparseFlags(table, next) }); return true; }\n catch (err) { setFlags(before); notify(getError(err), true); return false; }\n }\n return [flags, choose, load];\n}\n\n/** Tells every `useFlags` that the saved flags changed. */\nexport const flagsChanged = () => window.dispatchEvent(new CustomEvent('wb-features-changed'));\n\nfunction usePluginFiles(): [PluginFileState[], (list: PluginFileState[]) => void] {\n const [plugins, setPlugins] = useState<PluginFileState[]>([]);\n useEffect(() => {\n const load = () => invoke<PluginFileState[]>('plugins_list').then(setPlugins).catch(() => {});\n void load();\n window.addEventListener('bt-plugins-changed', load);\n return () => window.removeEventListener('bt-plugins-changed', load);\n }, []);\n return [plugins, setPlugins];\n}\n\n/** The flags the focused site tab says paused themselves (its area's `health` palette entry). */\nfunction usePaused(table: FeatureTable): Set<string> {\n const [paused, setPaused] = useState(() => pausedFeatures(table, focusedCommands()?.items));\n useEffect(() => {\n const read = () => setPaused(before => {\n const next = pausedFeatures(table, focusedCommands()?.items);\n return next.size === before.size && [...next].every(id => before.has(id)) ? before : next;\n });\n read();\n window.addEventListener(COMMANDS_CHANGED, read);\n return () => window.removeEventListener(COMMANDS_CHANGED, read);\n }, [table]);\n return paused;\n}\n\n/**\n * Lines for the app menu's \"Report a problem\" summary (the frame's `ShellSite.menu.report.details`):\n * the feature flags the focused site tab says paused themselves. Flag ids only.\n */\nexport function reportDetails(): Array<{ label: string; values: string[] }> {\n const table = featureTable();\n return table ? [{ label: 'Paused features', values: [...pausedFeatures(table, focusedCommands()?.items)].sort() }] : [];\n}\n\n/** The area cards and the Fixes list. Renders nothing for an app without a feature table. */\nexport function AreaPlugins({ notify }: { notify: Notify }) {\n const table = featureTable();\n return table ? <AreaPluginsOf table={table} notify={notify}/> : null;\n}\n\nfunction AreaPluginsOf({ table, notify }: { table: FeatureTable; notify: Notify }) {\n const t = useT();\n const query = useSettingsQuery().trim();\n const [flags, choose] = useFlags(table, notify);\n const [plugins, setPlugins] = usePluginFiles();\n const [open, setOpen] = useState<Record<string, boolean>>({});\n const [asking, setAsking] = useState<string | null>(null);\n const paused = usePaused(table);\n if (!flags) return null;\n\n const cards = areaCards(table, flags, plugins, paused);\n const fixes = fixRows(table, flags, panelSite().features?.elsewhere);\n const words = (row: FeatureRow) => ({ label: tx(row.label, undefined, row.spec.id), description: tx(row.description, undefined, '') });\n const shown = (row: FeatureRow, card?: AreaCard) => !query || matchesQuery(query, words(row).label, words(row).description, rowKeywords(row, card?.area));\n\n async function setPlugin(file: string, enabled: boolean) {\n try { setPlugins(await invoke<PluginFileState[]>('plugin_set_enabled', { file, enabled })); window.dispatchEvent(new CustomEvent('bt-plugins-changed')); return true; }\n catch (err) { notify(getError(err), true); return false; }\n }\n async function toggle(row: FeatureRow, next: boolean) {\n if (row.kind === 'plugin') { await setPlugin(row.spec.file!, next); return; }\n // Never the owner's own copy of the old plugin and the built-in feature at once.\n if (next && row.ownCopy?.enabled) { setAsking(row.spec.id); return; }\n await choose({ [row.spec.id]: next });\n }\n async function useBuiltIn(row: FeatureRow) {\n setAsking(null);\n if (row.ownCopy && await setPlugin(row.ownCopy.file, false)) await choose({ [row.spec.id]: true });\n }\n function openSettings(card: AreaCard) {\n const commands = focusedCommands();\n const id = `${card.area.owner}:settings`;\n if (commands?.items.some(item => item.id === id)) runPluginCommand(commands.tab, id);\n else notify(t('wb.features.settingsNoTab'), true);\n }\n\n const featureRow = (row: FeatureRow, card?: AreaCard) => {\n if (!shown(row, card)) return null;\n const text = words(row);\n const copy = row.ownCopy;\n const locked = row.missing || (!!card && !card.enabled && row.kind === 'flag');\n return <Row key={row.spec.id} label={text.label} keywords={`${rowKeywords(row, card?.area)} ${text.description}`}\n hint={<>{text.description}\n {row.paused && <span className=\"wbf-note\">{t('wb.features.paused')}</span>}\n {copy && !row.on && <span className=\"wbf-note\">{t('wb.features.ownCopy', { name: copy.name ?? copy.file })}</span>}\n {asking === row.spec.id && copy && <span className=\"wbf-ask\" role=\"alertdialog\">{t('wb.features.ownCopyAsk', { name: copy.name ?? copy.file })}\n <Button size=\"sm\" tone=\"primary\" onClick={() => void useBuiltIn(row)}>{t('wb.features.useBuiltIn')}</Button>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => setAsking(null)}>{t('wb.common.cancel')}</Button>\n </span>}</>}\n badge={<>\n {row.paused && <Badge tone=\"warn\">{t('wb.features.pausedBadge')}</Badge>}\n {row.isDefault && <Badge>{t('wb.features.default')}</Badge>}\n {card && row.spec.backing === 'app' && <Badge>{t('wb.features.inApp')}</Badge>}\n {row.kind === 'plugin' && <Badge tone={row.missing ? 'warn' : 'plain'}>{row.missing ? t('wb.features.missing') : t('wb.features.pluginFile')}</Badge>}\n </>}>\n <Toggle label={text.label} checked={row.on} disabled={locked} onChange={next => void toggle(row, next)}/>\n </Row>;\n };\n\n const visibleCards = cards.filter(card => !query || card.rows.some(row => shown(row, card)));\n return <>\n {visibleCards.length > 0 && <Section title={t('wb.features.areas')} hint={query ? undefined : t('wb.features.areasHint')} id=\"areas\">\n {visibleCards.map(card => {\n const expanded = !!query || !!open[card.area.id];\n return <div key={card.area.id} className={`wbf-area ${card.enabled ? '' : 'is-off'}`} data-area={card.area.id}>\n <div className=\"wbf-head\">\n <span className=\"wbf-icon\" aria-hidden=\"true\"><NavIcon d={card.area.icon ?? AREA_ICON}/></span>\n <button type=\"button\" className=\"wbf-title\" aria-expanded={expanded} disabled={card.total === 0} onClick={() => setOpen({ ...open, [card.area.id]: !expanded })}>\n <strong>{card.area.name}</strong>\n {card.total > 0 && <span className=\"wbf-count\">{t('wb.features.count', { on: card.on, total: card.total })}</span>}\n <small>{card.enabled ? tx(card.area.description, undefined, '') : t('wb.features.off')}{card.total === 0 && ` ${t('wb.features.soon')}`}</small>\n </button>\n {card.total > 0 && <span className={`wbf-caret ${expanded ? 'is-open' : ''}`} aria-hidden=\"true\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\"><path d=\"M3 4.5 6 7.5l3-3\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg></span>}\n {card.paused > 0 && <Badge tone=\"warn\">{t('wb.features.pausedBadge')}</Badge>}\n {card.settings && hasFeature('pluginCommands') && <Button size=\"sm\" tone=\"ghost\" onClick={() => openSettings(card)}>{t('wb.panel.section.settings')}</Button>}\n <Toggle label={t('wb.plugins.enabled', { name: card.area.name })} checked={card.enabled} onChange={next => void choose({ [areaFlag(card.area.id)]: next })}/>\n </div>\n {expanded && <div className=\"wbf-body\">\n {card.groups.map(group => {\n const rows = group.rows.map(row => featureRow(row, card)).filter(Boolean);\n if (!rows.length) return null;\n return <div key={group.id} className=\"wbf-group\">\n {group.id && <h3>{tx(`features.group.${group.id}`, undefined, group.id)}</h3>}\n {rows}\n </div>;\n })}\n </div>}\n </div>;\n })}\n </Section>}\n {fixes.some(row => shown(row)) && <Section title={t('wb.features.fixes')} hint={query ? undefined : t('wb.features.fixesHint')} id=\"fixes\">\n {fixes.map(row => featureRow(row))}\n </Section>}\n </>;\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import './plugins.css';
2
+ /** A `*.plugin.js` file from the local plugins folder (waybetter-host `plugins::ScriptPlugin`). */
3
+ export type ScriptPlugin = {
4
+ file: string;
5
+ name: string;
6
+ description: string;
7
+ version: string;
8
+ author: string;
9
+ enabled: boolean;
10
+ /** Declared `@permissions`; null/absent = no line (legacy: full API, full page access). */
11
+ permissions?: string[] | null;
12
+ /** Header problems (e.g. an unknown permission name). */
13
+ problems?: string[];
14
+ };
15
+ type Notify = (text: string, error?: boolean) => void;
16
+ /** A bundled plugin's name/description in the active language (`plugin.<file stem>.name`), else its header's. */
17
+ export declare const pluginText: (plugin: {
18
+ file: string;
19
+ name: string;
20
+ description?: string;
21
+ }) => {
22
+ name: string;
23
+ description: string;
24
+ };
25
+ /** BetterDiscord-style JavaScript plugins loaded from the local plugins folder into the site's page. */
26
+ export declare function ScriptPlugins({ notify }: {
27
+ notify: Notify;
28
+ }): import("react").JSX.Element;
29
+ /** Free-form CSS applied to the site's page, like BetterDiscord's Custom CSS. */
30
+ export declare function CustomCssEditor({ notify }: {
31
+ notify: Notify;
32
+ }): import("react").JSX.Element | null;
33
+ export {};
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Plugins: the `*.plugin.js` files in the app's plugins folder (on/off live in every site tab, their
3
+ // declared permissions, where each came from, removal through the install records) and the custom
4
+ // CSS editor. Native code serves them (waybetter-host `plugins_*`, `custom_css_*`).
5
+ import { useEffect, useState } from 'react';
6
+ import { invoke } from "../frame/bridge.js";
7
+ import { useT } from "../frame/hooks.js";
8
+ import { t as frameText, tx } from "../frame/i18n.js";
9
+ import { site } from "../frame/site.js";
10
+ import { permissionBadges } from "../storeModel.js";
11
+ import { Badge, Button, EmptyState, Row, Section, Toggle, useSettingsQuery } from "./controls.js";
12
+ import { featureFiles } from "./featureModel.js";
13
+ import { panelSite } from "./site.js";
14
+ import './plugins.css';
15
+ const getError = (error) => error instanceof Error ? error.message : String(error);
16
+ const PLUG = _jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M9 3v5M15 3v5M6 8h12v3a6 6 0 0 1-12 0zM12 17v4", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
17
+ /** A bundled plugin's name/description in the active language (`plugin.<file stem>.name`), else its header's. */
18
+ export const pluginText = (plugin) => {
19
+ const ns = plugin.file.replace(/\.plugin\.js$/i, '');
20
+ return { name: tx(`plugin.${ns}.name`, undefined, plugin.name), description: tx(`plugin.${ns}.description`, undefined, plugin.description ?? '') };
21
+ };
22
+ const PLUGIN_EXAMPLE = '/** @name Hello @description Says hi */\nmodule.exports = class {\n start() { console.log("hi"); }\n stop() {}\n};';
23
+ /** BetterDiscord-style JavaScript plugins loaded from the local plugins folder into the site's page. */
24
+ export function ScriptPlugins({ notify }) {
25
+ const t = useT();
26
+ const [plugins, setPlugins] = useState(null);
27
+ const [error, setError] = useState('');
28
+ const [busy, setBusy] = useState(null);
29
+ const query = useSettingsQuery();
30
+ const [records, setRecords] = useState({});
31
+ const [removing, setRemoving] = useState(null);
32
+ const refresh = () => {
33
+ invoke('install_records').then(value => setRecords(value.items ?? {})).catch(() => { });
34
+ return invoke('plugins_list').then(items => { setPlugins(items); setError(''); }).catch(err => setError(getError(err)));
35
+ };
36
+ useEffect(() => {
37
+ void refresh();
38
+ // The install screen (links, dropped files, the Store) added or updated one.
39
+ const again = () => void refresh();
40
+ window.addEventListener('bt-plugins-changed', again);
41
+ return () => window.removeEventListener('bt-plugins-changed', again);
42
+ }, []);
43
+ async function remove(plugin) {
44
+ setRemoving(null);
45
+ setBusy(plugin.file);
46
+ try {
47
+ setPlugins(await invoke('plugin_remove', { file: plugin.file }));
48
+ notify(t('wb.common.removedNamed', { name: pluginText(plugin).name }));
49
+ }
50
+ catch (err) {
51
+ notify(getError(err), true);
52
+ }
53
+ finally {
54
+ setBusy(null);
55
+ }
56
+ }
57
+ async function toggle(plugin) {
58
+ setBusy(plugin.file);
59
+ try {
60
+ setPlugins(await invoke('plugin_set_enabled', { file: plugin.file, enabled: !plugin.enabled }));
61
+ notify(plugin.enabled ? t('wb.plugins.stopped', { name: pluginText(plugin).name }) : t('wb.plugins.started', { name: pluginText(plugin).name }));
62
+ }
63
+ catch (err) {
64
+ notify(getError(err), true);
65
+ }
66
+ finally {
67
+ setBusy(null);
68
+ }
69
+ }
70
+ // A plugin file that is a feature of an area card (until it is ported) is switched there.
71
+ const table = panelSite().features?.table;
72
+ const inCards = table ? featureFiles(table) : null;
73
+ const listed = plugins && inCards ? plugins.filter(plugin => !inCards.has(plugin.file)) : plugins;
74
+ // Removing a file goes through the install screen's native side (`plugin_remove`).
75
+ const removable = !!panelSite().store;
76
+ const folder = _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => void invoke('plugins_open_folder').catch(err => notify(getError(err), true)), children: t('wb.plugins.openFolder') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => void refresh(), children: t('wb.plugins.rescan') })] });
77
+ return _jsxs(Section, { title: t('wb.plugins.title'), hint: t('wb.plugins.hint'), action: plugins && (plugins.length > 0 || table) ? folder : undefined, children: [error && _jsx("div", { className: "bt-alert", role: "alert", children: error }), listed?.length === 0 && !query && !table && _jsxs(EmptyState, { icon: PLUG, title: t('wb.plugins.none'), action: folder, children: [t('wb.plugins.noneHint'), _jsx("code", { className: "bt-snippet", style: { display: 'block' }, children: PLUGIN_EXAMPLE })] }), listed?.map(plugin => {
78
+ const record = records[`plugin:${plugin.file}`];
79
+ const source = record ? (record.source === 'store' ? t('wb.panel.section.store') : record.source === 'link' ? t('wb.plugins.source.link') : t('wb.plugins.source.file')) : null;
80
+ const text = pluginText(plugin);
81
+ return _jsxs(Row, { label: text.name, hint: _jsxs(_Fragment, { children: [text.description || plugin.file, plugin.author ? ` · ${plugin.author}` : '', _jsxs("span", { className: "wbx-perms", children: [permissionBadges(plugin.permissions, frameText, site().name).map(badge => _jsx("span", { className: `is-${badge.tone}`, title: badge.detail, children: badge.label }, badge.id)), source && _jsx("span", { className: "is-source", title: record?.url ?? t('wb.plugins.source.fileTitle'), children: source }), (plugin.problems ?? []).map(problem => _jsx("span", { className: "is-warn", title: problem, children: t('wb.plugins.headerProblem') }, problem))] })] }), keywords: `plugin ${plugin.file} ${plugin.name} ${(plugin.permissions ?? ['legacy']).join(' ')}`, badge: _jsx(Badge, { children: plugin.version || t('wb.plugins.noVersion') }), children: [!removable ? null : removing === plugin.file
82
+ ? _jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", tone: "danger", onClick: () => void remove(plugin), children: t('wb.plugins.deleteFile') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setRemoving(null), children: t('wb.plugins.keep') })] })
83
+ : _jsx(Button, { size: "sm", tone: "ghost", disabled: busy === plugin.file, onClick: () => setRemoving(plugin.file), children: t('wb.common.remove') }), _jsx(Toggle, { label: t('wb.plugins.enabled', { name: text.name }), checked: plugin.enabled, disabled: busy === plugin.file, onChange: () => void toggle(plugin) })] }, plugin.file);
84
+ })] });
85
+ }
86
+ /** Free-form CSS applied to the site's page, like BetterDiscord's Custom CSS. */
87
+ export function CustomCssEditor({ notify }) {
88
+ const t = useT();
89
+ const [css, setCss] = useState('');
90
+ const [saved, setSaved] = useState('');
91
+ const [loaded, setLoaded] = useState(false);
92
+ const query = useSettingsQuery();
93
+ useEffect(() => { invoke('custom_css_get').then(value => { setCss(value); setSaved(value); setLoaded(true); }).catch(err => notify(getError(err), true)); }, []);
94
+ async function apply() {
95
+ try {
96
+ await invoke('custom_css_set', { css });
97
+ setSaved(css);
98
+ notify(t('wb.css.applied'));
99
+ }
100
+ catch (err) {
101
+ notify(getError(err), true);
102
+ }
103
+ }
104
+ if (query && !`custom css stylesheet style code ${t('wb.css.title')}`.toLowerCase().includes(query.toLowerCase().trim()))
105
+ return null;
106
+ const dirty = css !== saved;
107
+ return _jsx(Section, { title: t('wb.css.title'), hint: t('wb.css.hint'), action: _jsx("span", { className: `bt-status ${dirty ? 'is-warn' : ''}`, children: dirty ? t('wb.css.unsaved') : loaded ? (saved.trim() ? t('wb.css.applied.short') : t('wb.css.empty')) : '' }), children: _jsxs("div", { className: "bt-code", children: [_jsx("textarea", { "aria-label": t('wb.css.label'), spellCheck: false, value: css, placeholder: panelSite().cssExamples?.custom ?? '/* CSS for the page */', onChange: event => setCss(event.target.value), onKeyDown: event => { if ((event.ctrlKey || event.metaKey) && event.key === 's') {
108
+ event.preventDefault();
109
+ void apply();
110
+ } } }), _jsxs("div", { className: "bt-code-bar", children: [_jsx("small", { children: t('wb.appearance.cssLines', { count: css.split('\n').length }) }), dirty && _jsx(Button, { size: "sm", tone: "ghost", onClick: () => setCss(saved), children: t('wb.common.discard') }), _jsx(Button, { size: "sm", tone: "primary", disabled: !loaded || !dirty, onClick: () => void apply(), children: t('wb.common.apply') })] })] }) });
111
+ }
112
+ //# sourceMappingURL=Plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plugins.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/Plugins.tsx"],"names":[],"mappings":"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","sourcesContent":["// Plugins: the `*.plugin.js` files in the app's plugins folder (on/off live in every site tab, their\n// declared permissions, where each came from, removal through the install records) and the custom\n// CSS editor. Native code serves them (waybetter-host `plugins_*`, `custom_css_*`).\nimport { useEffect, useState } from 'react';\nimport { invoke } from '../frame/bridge.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { t as frameText, tx } from '../frame/i18n.ts';\nimport { site } from '../frame/site.ts';\nimport { permissionBadges, type InstallRecord } from '../storeModel.ts';\nimport { Badge, Button, EmptyState, Row, Section, Toggle, useSettingsQuery } from './controls.tsx';\nimport { featureFiles } from './featureModel.ts';\nimport { panelSite } from './site.ts';\nimport './plugins.css';\n\n/** A `*.plugin.js` file from the local plugins folder (waybetter-host `plugins::ScriptPlugin`). */\nexport type ScriptPlugin = {\n file: string;\n name: string;\n description: string;\n version: string;\n author: string;\n enabled: boolean;\n /** Declared `@permissions`; null/absent = no line (legacy: full API, full page access). */\n permissions?: string[] | null;\n /** Header problems (e.g. an unknown permission name). */\n problems?: string[];\n};\n\ntype Notify = (text: string, error?: boolean) => void;\nconst getError = (error: unknown) => error instanceof Error ? error.message : String(error);\nconst PLUG = <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 3v5M15 3v5M6 8h12v3a6 6 0 0 1-12 0zM12 17v4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>;\n\n/** A bundled plugin's name/description in the active language (`plugin.<file stem>.name`), else its header's. */\nexport const pluginText = (plugin: { file: string; name: string; description?: string }) => {\n const ns = plugin.file.replace(/\\.plugin\\.js$/i, '');\n return { name: tx(`plugin.${ns}.name`, undefined, plugin.name), description: tx(`plugin.${ns}.description`, undefined, plugin.description ?? '') };\n};\n\nconst PLUGIN_EXAMPLE = '/** @name Hello @description Says hi */\\nmodule.exports = class {\\n start() { console.log(\"hi\"); }\\n stop() {}\\n};';\n\n/** BetterDiscord-style JavaScript plugins loaded from the local plugins folder into the site's page. */\nexport function ScriptPlugins({ notify }: { notify: Notify }) {\n const t = useT();\n const [plugins, setPlugins] = useState<ScriptPlugin[] | null>(null);\n const [error, setError] = useState('');\n const [busy, setBusy] = useState<string | null>(null);\n const query = useSettingsQuery();\n\n const [records, setRecords] = useState<Record<string, InstallRecord>>({});\n const [removing, setRemoving] = useState<string | null>(null);\n const refresh = () => {\n invoke<{ items: Record<string, InstallRecord> }>('install_records').then(value => setRecords(value.items ?? {})).catch(() => {});\n return invoke<ScriptPlugin[]>('plugins_list').then(items => { setPlugins(items); setError(''); }).catch(err => setError(getError(err)));\n };\n useEffect(() => {\n void refresh();\n // The install screen (links, dropped files, the Store) added or updated one.\n const again = () => void refresh();\n window.addEventListener('bt-plugins-changed', again);\n return () => window.removeEventListener('bt-plugins-changed', again);\n }, []);\n\n async function remove(plugin: ScriptPlugin) {\n setRemoving(null);\n setBusy(plugin.file);\n try {\n setPlugins(await invoke<ScriptPlugin[]>('plugin_remove', { file: plugin.file }));\n notify(t('wb.common.removedNamed', { name: pluginText(plugin).name }));\n } catch (err) { notify(getError(err), true); }\n finally { setBusy(null); }\n }\n\n async function toggle(plugin: ScriptPlugin) {\n setBusy(plugin.file);\n try {\n setPlugins(await invoke<ScriptPlugin[]>('plugin_set_enabled', { file: plugin.file, enabled: !plugin.enabled }));\n notify(plugin.enabled ? t('wb.plugins.stopped', { name: pluginText(plugin).name }) : t('wb.plugins.started', { name: pluginText(plugin).name }));\n } catch (err) { notify(getError(err), true); }\n finally { setBusy(null); }\n }\n\n // A plugin file that is a feature of an area card (until it is ported) is switched there.\n const table = panelSite().features?.table;\n const inCards = table ? featureFiles(table) : null;\n const listed = plugins && inCards ? plugins.filter(plugin => !inCards.has(plugin.file)) : plugins;\n // Removing a file goes through the install screen's native side (`plugin_remove`).\n const removable = !!panelSite().store;\n const folder = <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => void invoke('plugins_open_folder').catch(err => notify(getError(err), true))}>{t('wb.plugins.openFolder')}</Button>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => void refresh()}>{t('wb.plugins.rescan')}</Button>\n </div>;\n\n return <Section title={t('wb.plugins.title')} hint={t('wb.plugins.hint')}\n action={plugins && (plugins.length > 0 || table) ? folder : undefined}>\n {error && <div className=\"bt-alert\" role=\"alert\">{error}</div>}\n {listed?.length === 0 && !query && !table && <EmptyState icon={PLUG} title={t('wb.plugins.none')} action={folder}>\n {t('wb.plugins.noneHint')}\n <code className=\"bt-snippet\" style={{ display: 'block' }}>{PLUGIN_EXAMPLE}</code>\n </EmptyState>}\n {listed?.map(plugin => {\n const record = records[`plugin:${plugin.file}`];\n const source = record ? (record.source === 'store' ? t('wb.panel.section.store') : record.source === 'link' ? t('wb.plugins.source.link') : t('wb.plugins.source.file')) : null;\n const text = pluginText(plugin);\n return <Row key={plugin.file} label={text.name} hint={<>{text.description || plugin.file}{plugin.author ? ` · ${plugin.author}` : ''}\n <span className=\"wbx-perms\">\n {permissionBadges(plugin.permissions, frameText, site().name).map(badge => <span key={badge.id} className={`is-${badge.tone}`} title={badge.detail}>{badge.label}</span>)}\n {source && <span className=\"is-source\" title={record?.url ?? t('wb.plugins.source.fileTitle')}>{source}</span>}\n {(plugin.problems ?? []).map(problem => <span key={problem} className=\"is-warn\" title={problem}>{t('wb.plugins.headerProblem')}</span>)}\n </span></>} keywords={`plugin ${plugin.file} ${plugin.name} ${(plugin.permissions ?? ['legacy']).join(' ')}`}\n badge={<Badge>{plugin.version || t('wb.plugins.noVersion')}</Badge>}>\n {!removable ? null : removing === plugin.file\n ? <><Button size=\"sm\" tone=\"danger\" onClick={() => void remove(plugin)}>{t('wb.plugins.deleteFile')}</Button><Button size=\"sm\" tone=\"ghost\" onClick={() => setRemoving(null)}>{t('wb.plugins.keep')}</Button></>\n : <Button size=\"sm\" tone=\"ghost\" disabled={busy === plugin.file} onClick={() => setRemoving(plugin.file)}>{t('wb.common.remove')}</Button>}\n <Toggle label={t('wb.plugins.enabled', { name: text.name })} checked={plugin.enabled} disabled={busy === plugin.file} onChange={() => void toggle(plugin)}/>\n </Row>;\n })}\n </Section>;\n}\n\n/** Free-form CSS applied to the site's page, like BetterDiscord's Custom CSS. */\nexport function CustomCssEditor({ notify }: { notify: Notify }) {\n const t = useT();\n const [css, setCss] = useState('');\n const [saved, setSaved] = useState('');\n const [loaded, setLoaded] = useState(false);\n const query = useSettingsQuery();\n\n useEffect(() => { invoke<string>('custom_css_get').then(value => { setCss(value); setSaved(value); setLoaded(true); }).catch(err => notify(getError(err), true)); }, []);\n\n async function apply() {\n try { await invoke('custom_css_set', { css }); setSaved(css); notify(t('wb.css.applied')); }\n catch (err) { notify(getError(err), true); }\n }\n if (query && !`custom css stylesheet style code ${t('wb.css.title')}`.toLowerCase().includes(query.toLowerCase().trim())) return null;\n\n const dirty = css !== saved;\n return <Section title={t('wb.css.title')} hint={t('wb.css.hint')}\n action={<span className={`bt-status ${dirty ? 'is-warn' : ''}`}>{dirty ? t('wb.css.unsaved') : loaded ? (saved.trim() ? t('wb.css.applied.short') : t('wb.css.empty')) : ''}</span>}>\n <div className=\"bt-code\">\n <textarea aria-label={t('wb.css.label')} spellCheck={false} value={css} placeholder={panelSite().cssExamples?.custom ?? '/* CSS for the page */'} onChange={event => setCss(event.target.value)}\n onKeyDown={event => { if ((event.ctrlKey || event.metaKey) && event.key === 's') { event.preventDefault(); void apply(); } }}/>\n <div className=\"bt-code-bar\">\n <small>{t('wb.appearance.cssLines', { count: css.split('\\n').length })}</small>\n {dirty && <Button size=\"sm\" tone=\"ghost\" onClick={() => setCss(saved)}>{t('wb.common.discard')}</Button>}\n <Button size=\"sm\" tone=\"primary\" disabled={!loaded || !dirty} onClick={() => void apply()}>{t('wb.common.apply')}</Button>\n </div>\n </div>\n </Section>;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { type Notify } from './site.ts';
2
+ export declare function PowerSettings({ notify }: {
3
+ notify: Notify;
4
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Settings → Power User: the deck's defaults (column width, density, default column flags), the
3
+ // memory guard (columns per page, with the memory one column was measured to take, when the app
4
+ // says so), parking off-page columns, presets and the list of decks. Stored in the shell
5
+ // (frame/deckStore.ts); the column kinds, flags and presets are the site's (`site.deck`).
6
+ import { useEffect, useReducer } from 'react';
7
+ import { COLUMN_WIDTHS, DEFAULT_MAX_VISIBLE } from "../deckModel.js";
8
+ import { createDeck, decks, forgetColumn, saveDecks, setDeckSettings } from "../frame/deckStore.js";
9
+ import { useT } from "../frame/hooks.js";
10
+ import { site } from "../frame/site.js";
11
+ import { shell } from "../frame/state.js";
12
+ import { Badge, Button, Row, Section, Segmented, Stepper, Toggle } from "./controls.js";
13
+ import { panelSite } from "./site.js";
14
+ function useDeckState() {
15
+ const [, tick] = useReducer((n) => n + 1, 0);
16
+ useEffect(() => { window.addEventListener('bt-decks', tick); return () => window.removeEventListener('bt-decks', tick); }, []);
17
+ }
18
+ const openDeck = (deckId) => window.dispatchEvent(new CustomEvent('bt-deck-open', { detail: deckId }));
19
+ export function PowerSettings({ notify }) {
20
+ const t = useT();
21
+ useDeckState();
22
+ const settings = decks.settings;
23
+ const save = (patch, message) => { setDeckSettings({ ...settings, ...patch }); notify(message); };
24
+ const perPage = settings.maxVisible;
25
+ const guard = perPage > DEFAULT_MAX_VISIBLE;
26
+ const profiles = shell.profiles.profiles.map(p => p.id);
27
+ const deckSite = site().deck;
28
+ const power = panelSite().power;
29
+ const memory = power?.memory;
30
+ if (!deckSite)
31
+ return null;
32
+ const listed = power?.defaultFlags ?? Object.keys(deckSite.defaultFlags);
33
+ const preset = (item) => {
34
+ const ordered = [shell.profiles.active, ...profiles.filter(id => id !== shell.profiles.active)];
35
+ const deck = createDeck((item.name ?? item.label)(), item.columns(ordered));
36
+ openDeck(deck.id);
37
+ notify(t('wb.power.deckCreated', { name: deck.name }));
38
+ };
39
+ return _jsxs(_Fragment, { children: [_jsxs(Section, { title: t('wb.power.title'), hint: t('wb.power.hint'), action: _jsx(Button, { size: "sm", tone: "primary", onClick: () => openDeck(), children: t('wb.power.openDeck') }), children: [_jsx(Row, { label: t('wb.power.width'), hint: t('wb.power.widthHint'), keywords: "deck width narrow", children: _jsx(Segmented, { label: t('wb.power.width'), size: "sm", value: settings.width, onChange: width => save({ width }, t('wb.power.widthSaved', { width })), options: COLUMN_WIDTHS.map(width => ({ value: width, label: String(width) })) }) }), _jsx(Row, { label: t('wb.appearance.density'), hint: t('wb.power.densityHint'), keywords: "deck compact comfortable spacing", children: _jsx(Segmented, { label: t('wb.appearance.density'), size: "sm", value: settings.density, onChange: density => save({ density }, density === 'compact' ? t('wb.power.densityCompact') : t('wb.power.densityComfortable')), options: [{ value: 'compact', label: t('wb.appearance.density.compact') }, { value: 'comfortable', label: t('wb.power.comfortable') }] }) }), deckSite.flags.filter(option => listed.includes(option.key)).map(option => _jsx(Row, { label: t('wb.power.columnsFlag', { flag: option.label }), hint: option.hint, keywords: "deck column default flags autoplay promoted counts", children: _jsx(Toggle, { label: option.label, checked: settings.flags[option.key] === true, onChange: next => save({ flags: { ...settings.flags, [option.key]: next } }, next ? t('wb.power.flagOn', { flag: option.label }) : t('wb.power.flagOff', { flag: option.label })) }) }, option.key))] }), _jsxs(Section, { title: t('wb.power.memory'), hint: memory ? t('wb.power.memoryHint', { range: memory.range }) : undefined, children: [_jsx(Row, { label: t('wb.power.perPage'), hint: !memory ? t('wb.power.perPageSaved', { count: perPage }) : guard
40
+ ? t('wb.power.perPageGuard', { max: DEFAULT_MAX_VISIBLE, mb: perPage * memory.perColumn })
41
+ : t('wb.power.perPageHint', { count: perPage, mb: perPage * memory.perColumn }), badge: guard ? _jsx(Badge, { tone: "warn", children: t('wb.power.guard') }) : undefined, keywords: "deck memory ram guard page visible", children: _jsx(Stepper, { label: t('wb.power.perPage'), value: perPage, min: 1, max: 12, onChange: maxVisible => save({ maxVisible }, t('wb.power.perPageSaved', { count: maxVisible })) }) }), _jsx(Row, { label: t('wb.power.park'), hint: t('wb.power.parkHint'), keywords: "deck memory park low", children: _jsx(Toggle, { label: t('wb.power.park'), checked: settings.parkOffPage, onChange: parkOffPage => save({ parkOffPage }, parkOffPage ? t('wb.power.parkOn') : t('wb.power.parkOff')) }) })] }), _jsxs(Section, { title: t('wb.power.decks'), hint: t('wb.power.decksHint'), children: [(deckSite.presets ?? []).map(item => {
42
+ const blocked = !!item.needsTwoAccounts && profiles.length < 2;
43
+ return _jsx(Row, { label: (item.name ?? item.label)(), hint: item.hint?.(), keywords: `deck preset ${item.needsTwoAccounts ? 'accounts' : item.id}`, children: _jsx(Button, { size: "sm", disabled: blocked, onClick: () => preset(item), children: blocked ? t('wb.power.addAccountFirst') : t('wb.common.create') }) }, item.id);
44
+ }), decks.list.map(deck => _jsx(Row, { label: deck.name, hint: t('wb.power.columnCount', { count: deck.columns.length }), keywords: "deck", children: _jsxs("div", { className: "bt-inline", children: [_jsx(Button, { size: "sm", onClick: () => openDeck(deck.id), children: t('wb.common.open') }), _jsx(Button, { size: "sm", tone: "ghost", onClick: () => {
45
+ for (const column of deck.columns)
46
+ forgetColumn(column.tabId);
47
+ decks.list = decks.list.filter(d => d.id !== deck.id);
48
+ saveDecks();
49
+ notify(t('wb.common.removedNamed', { name: deck.name }));
50
+ }, children: t('wb.common.remove') })] }) }, deck.id))] }), _jsxs(Section, { title: t('wb.power.keys'), hint: power?.keysHint?.(), children: [_jsx(Row, { label: t('wb.power.key.column'), hint: t('wb.power.key.columnHint'), keywords: "deck keys shortcut" }), _jsx(Row, { label: t('wb.power.key.jump'), hint: "Alt+1 \u2026 Alt+9", keywords: "deck keys shortcut" }), _jsx(Row, { label: t('wb.power.key.page'), hint: "Alt+PageUp / Alt+PageDown", keywords: "deck keys shortcut" }), _jsx(Row, { label: t('wb.power.key.read'), hint: "Alt+R / Alt+U", keywords: "deck keys shortcut unread" }), deckSite.compose && _jsx(Row, { label: t('wb.power.key.post'), hint: t('wb.power.key.postHint'), keywords: "deck keys shortcut compose" }), _jsx(Row, { label: t('wb.power.key.toggle'), hint: "Ctrl+Shift+D", keywords: "deck keys shortcut toggle" })] })] });
51
+ }
52
+ //# sourceMappingURL=PowerSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PowerSettings.js","sourceRoot":"","sources":["../../../../../../shell/src/panel/PowerSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["// Settings → Power User: the deck's defaults (column width, density, default column flags), the\n// memory guard (columns per page, with the memory one column was measured to take, when the app\n// says so), parking off-page columns, presets and the list of decks. Stored in the shell\n// (frame/deckStore.ts); the column kinds, flags and presets are the site's (`site.deck`).\n\nimport { useEffect, useReducer } from 'react';\nimport { COLUMN_WIDTHS, DEFAULT_MAX_VISIBLE } from '../deckModel.ts';\nimport { createDeck, decks, forgetColumn, saveDecks, setDeckSettings, type DeckSettings } from '../frame/deckStore.ts';\nimport { useT } from '../frame/hooks.ts';\nimport { site, type DeckPreset } from '../frame/site.ts';\nimport { shell } from '../frame/state.ts';\nimport { Badge, Button, Row, Section, Segmented, Stepper, Toggle } from './controls.tsx';\nimport { panelSite, type Notify } from './site.ts';\n\nfunction useDeckState() {\n const [, tick] = useReducer((n: number) => n + 1, 0);\n useEffect(() => { window.addEventListener('bt-decks', tick); return () => window.removeEventListener('bt-decks', tick); }, []);\n}\n\nconst openDeck = (deckId?: string) => window.dispatchEvent(new CustomEvent('bt-deck-open', { detail: deckId }));\n\nexport function PowerSettings({ notify }: { notify: Notify }) {\n const t = useT();\n useDeckState();\n const settings = decks.settings;\n const save = (patch: Partial<DeckSettings>, message: string) => { setDeckSettings({ ...settings, ...patch }); notify(message); };\n const perPage = settings.maxVisible;\n const guard = perPage > DEFAULT_MAX_VISIBLE;\n const profiles = shell.profiles.profiles.map(p => p.id);\n const deckSite = site().deck;\n const power = panelSite().power;\n const memory = power?.memory;\n if (!deckSite) return null;\n const listed = power?.defaultFlags ?? Object.keys(deckSite.defaultFlags);\n const preset = (item: DeckPreset) => {\n const ordered = [shell.profiles.active, ...profiles.filter(id => id !== shell.profiles.active)];\n const deck = createDeck((item.name ?? item.label)(), item.columns(ordered));\n openDeck(deck.id);\n notify(t('wb.power.deckCreated', { name: deck.name }));\n };\n\n return <>\n <Section title={t('wb.power.title')} hint={t('wb.power.hint')}\n action={<Button size=\"sm\" tone=\"primary\" onClick={() => openDeck()}>{t('wb.power.openDeck')}</Button>}>\n <Row label={t('wb.power.width')} hint={t('wb.power.widthHint')} keywords=\"deck width narrow\">\n <Segmented label={t('wb.power.width')} size=\"sm\" value={settings.width} onChange={width => save({ width }, t('wb.power.widthSaved', { width }))}\n options={COLUMN_WIDTHS.map(width => ({ value: width, label: String(width) }))}/>\n </Row>\n <Row label={t('wb.appearance.density')} hint={t('wb.power.densityHint')} keywords=\"deck compact comfortable spacing\">\n <Segmented label={t('wb.appearance.density')} size=\"sm\" value={settings.density} onChange={density => save({ density }, density === 'compact' ? t('wb.power.densityCompact') : t('wb.power.densityComfortable'))}\n options={[{ value: 'compact', label: t('wb.appearance.density.compact') }, { value: 'comfortable', label: t('wb.power.comfortable') }]}/>\n </Row>\n {deckSite.flags.filter(option => listed.includes(option.key)).map(option =>\n <Row key={option.key} label={t('wb.power.columnsFlag', { flag: option.label })} hint={option.hint} keywords=\"deck column default flags autoplay promoted counts\">\n <Toggle label={option.label} checked={settings.flags[option.key] === true}\n onChange={next => save({ flags: { ...settings.flags, [option.key]: next } }, next ? t('wb.power.flagOn', { flag: option.label }) : t('wb.power.flagOff', { flag: option.label }))}/>\n </Row>)}\n </Section>\n <Section title={t('wb.power.memory')} hint={memory ? t('wb.power.memoryHint', { range: memory.range }) : undefined}>\n <Row label={t('wb.power.perPage')} hint={!memory ? t('wb.power.perPageSaved', { count: perPage }) : guard\n ? t('wb.power.perPageGuard', { max: DEFAULT_MAX_VISIBLE, mb: perPage * memory.perColumn })\n : t('wb.power.perPageHint', { count: perPage, mb: perPage * memory.perColumn })}\n badge={guard ? <Badge tone=\"warn\">{t('wb.power.guard')}</Badge> : undefined} keywords=\"deck memory ram guard page visible\">\n <Stepper label={t('wb.power.perPage')} value={perPage} min={1} max={12} onChange={maxVisible => save({ maxVisible }, t('wb.power.perPageSaved', { count: maxVisible }))}/>\n </Row>\n <Row label={t('wb.power.park')} hint={t('wb.power.parkHint')} keywords=\"deck memory park low\">\n <Toggle label={t('wb.power.park')} checked={settings.parkOffPage} onChange={parkOffPage => save({ parkOffPage }, parkOffPage ? t('wb.power.parkOn') : t('wb.power.parkOff'))}/>\n </Row>\n </Section>\n <Section title={t('wb.power.decks')} hint={t('wb.power.decksHint')}>\n {(deckSite.presets ?? []).map(item => {\n const blocked = !!item.needsTwoAccounts && profiles.length < 2;\n return <Row key={item.id} label={(item.name ?? item.label)()} hint={item.hint?.()} keywords={`deck preset ${item.needsTwoAccounts ? 'accounts' : item.id}`}>\n <Button size=\"sm\" disabled={blocked} onClick={() => preset(item)}>{blocked ? t('wb.power.addAccountFirst') : t('wb.common.create')}</Button>\n </Row>;\n })}\n {decks.list.map(deck => <Row key={deck.id} label={deck.name} hint={t('wb.power.columnCount', { count: deck.columns.length })} keywords=\"deck\">\n <div className=\"bt-inline\">\n <Button size=\"sm\" onClick={() => openDeck(deck.id)}>{t('wb.common.open')}</Button>\n <Button size=\"sm\" tone=\"ghost\" onClick={() => {\n for (const column of deck.columns) forgetColumn(column.tabId);\n decks.list = decks.list.filter(d => d.id !== deck.id);\n saveDecks();\n notify(t('wb.common.removedNamed', { name: deck.name }));\n }}>{t('wb.common.remove')}</Button>\n </div>\n </Row>)}\n </Section>\n <Section title={t('wb.power.keys')} hint={power?.keysHint?.()}>\n <Row label={t('wb.power.key.column')} hint={t('wb.power.key.columnHint')} keywords=\"deck keys shortcut\"/>\n <Row label={t('wb.power.key.jump')} hint=\"Alt+1 … Alt+9\" keywords=\"deck keys shortcut\"/>\n <Row label={t('wb.power.key.page')} hint=\"Alt+PageUp / Alt+PageDown\" keywords=\"deck keys shortcut\"/>\n <Row label={t('wb.power.key.read')} hint=\"Alt+R / Alt+U\" keywords=\"deck keys shortcut unread\"/>\n {deckSite.compose && <Row label={t('wb.power.key.post')} hint={t('wb.power.key.postHint')} keywords=\"deck keys shortcut compose\"/>}\n <Row label={t('wb.power.key.toggle')} hint=\"Ctrl+Shift+D\" keywords=\"deck keys shortcut toggle\"/>\n </Section>\n </>;\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { type Notify } from './site.ts';
2
+ /** The shell's settings (waybetter-host `ShellSettings`). */
3
+ export type ShellSettings = {
4
+ homeUrl: string;
5
+ /** Links to other sites: beside the tab (split), a new tab, or the system browser. */
6
+ externalLinks: 'pane' | 'tab' | 'browser';
7
+ /** Site pages clicked in the page: the site's in-place navigation, beside, a new tab, or the system browser. */
8
+ siteLinks: 'same' | 'pane' | 'tab' | 'browser';
9
+ restoreTabs: boolean;
10
+ };
11
+ /** Home page, where links open, session restore. Stored natively; read by the tab webviews. */
12
+ export declare function BrowserSettings({ notify }: {
13
+ notify: Notify;
14
+ }): import("react").JSX.Element | null;
15
+ export declare const parseKeywords: (text: string) => string[];
16
+ /** Keyword alerts: local OS notifications for keywords in items the site already loaded. Native only. */
17
+ export declare function AlertSettings({ notify }: {
18
+ notify: Notify;
19
+ }): import("react").JSX.Element | null;
20
+ /** Gallery folders and the opt-in clipboard history for the Media panel (Ctrl+Shift+G). Native only. */
21
+ export declare function MediaSettingsRows({ notify }: {
22
+ notify: Notify;
23
+ }): import("react").JSX.Element | null;