@rightkit/document-workspace 0.0.0-stage → 0.1.1

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 (262) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +74 -2
  5. package/dist/app/App.d.ts +1 -0
  6. package/dist/app/App.js +6 -0
  7. package/dist/app/AppDialogs.d.ts +52 -0
  8. package/dist/app/AppDialogs.js +23 -0
  9. package/dist/app/AppDialogsHost.d.ts +31 -0
  10. package/dist/app/AppDialogsHost.js +30 -0
  11. package/dist/app/AppLifecycle.d.ts +19 -0
  12. package/dist/app/AppLifecycle.js +87 -0
  13. package/dist/app/AppProvider.d.ts +317 -0
  14. package/dist/app/AppProvider.js +217 -0
  15. package/dist/app/AppRoot.d.ts +8 -0
  16. package/dist/app/AppRoot.js +159 -0
  17. package/dist/app/AppShell.d.ts +2 -0
  18. package/dist/app/AppShell.js +81 -0
  19. package/dist/app/CommandPalette.d.ts +13 -0
  20. package/dist/app/CommandPalette.js +47 -0
  21. package/dist/app/DocActionBar.d.ts +36 -0
  22. package/dist/app/DocActionBar.js +300 -0
  23. package/dist/app/DocumentContextMenu.d.ts +29 -0
  24. package/dist/app/DocumentContextMenu.js +122 -0
  25. package/dist/app/DocumentPane.d.ts +52 -0
  26. package/dist/app/DocumentPane.js +30 -0
  27. package/dist/app/DocumentRouterTable.d.ts +58 -0
  28. package/dist/app/DocumentRouterTable.js +143 -0
  29. package/dist/app/ErrorBoundary.d.ts +12 -0
  30. package/dist/app/ErrorBoundary.js +16 -0
  31. package/dist/app/FindBar.d.ts +12 -0
  32. package/dist/app/FindBar.js +199 -0
  33. package/dist/app/LiveTitle.d.ts +14 -0
  34. package/dist/app/LiveTitle.js +14 -0
  35. package/dist/app/OpeningProgress.d.ts +13 -0
  36. package/dist/app/OpeningProgress.js +21 -0
  37. package/dist/app/PrintPreviewWindow.d.ts +2 -0
  38. package/dist/app/PrintPreviewWindow.js +57 -0
  39. package/dist/app/ShortcutHelp.d.ts +3 -0
  40. package/dist/app/ShortcutHelp.js +99 -0
  41. package/dist/app/Sidebar.d.ts +36 -0
  42. package/dist/app/Sidebar.js +121 -0
  43. package/dist/app/ToastViewport.d.ts +1 -0
  44. package/dist/app/ToastViewport.js +31 -0
  45. package/dist/app/Toolbar.d.ts +26 -0
  46. package/dist/app/Toolbar.js +63 -0
  47. package/dist/app/activeFormatSavers.d.ts +7 -0
  48. package/dist/app/activeFormatSavers.js +4 -0
  49. package/dist/app/clipboardPaths.d.ts +1 -0
  50. package/dist/app/clipboardPaths.js +31 -0
  51. package/dist/app/documentDrafts.d.ts +17 -0
  52. package/dist/app/documentDrafts.js +104 -0
  53. package/dist/app/draftResolution.d.ts +5 -0
  54. package/dist/app/draftResolution.js +25 -0
  55. package/dist/app/markdownPaletteActions.d.ts +8 -0
  56. package/dist/app/markdownPaletteActions.js +107 -0
  57. package/dist/app/resourceCensusDev.d.ts +41 -0
  58. package/dist/app/resourceCensusDev.js +518 -0
  59. package/dist/app/setupRecovery.d.ts +34 -0
  60. package/dist/app/setupRecovery.js +70 -0
  61. package/dist/app/shell/DocStatsPill.d.ts +18 -0
  62. package/dist/app/shell/DocStatsPill.js +32 -0
  63. package/dist/app/shell/DocumentTools.d.ts +9 -0
  64. package/dist/app/shell/DocumentTools.js +73 -0
  65. package/dist/app/shell/InfoInspector.d.ts +9 -0
  66. package/dist/app/shell/InfoInspector.js +67 -0
  67. package/dist/app/shell/StartPage.d.ts +9 -0
  68. package/dist/app/shell/StartPage.js +49 -0
  69. package/dist/app/shell/readEdit.d.ts +6 -0
  70. package/dist/app/shell/readEdit.js +6 -0
  71. package/dist/app/sidebar/SidebarDocumentMenu.d.ts +20 -0
  72. package/dist/app/sidebar/SidebarDocumentMenu.js +56 -0
  73. package/dist/app/sidebar/SidebarExpandedPanel.d.ts +9 -0
  74. package/dist/app/sidebar/SidebarExpandedPanel.js +78 -0
  75. package/dist/app/sidebar/SidebarIcons.d.ts +3 -0
  76. package/dist/app/sidebar/SidebarIcons.js +18 -0
  77. package/dist/app/sidebar/SidebarMenus.d.ts +19 -0
  78. package/dist/app/sidebar/SidebarMenus.js +64 -0
  79. package/dist/app/sidebar/SidebarPathUtils.d.ts +10 -0
  80. package/dist/app/sidebar/SidebarPathUtils.js +55 -0
  81. package/dist/app/sidebar/SidebarPrimitives.d.ts +12 -0
  82. package/dist/app/sidebar/SidebarPrimitives.js +45 -0
  83. package/dist/app/sidebar/SidebarRail.d.ts +5 -0
  84. package/dist/app/sidebar/SidebarRail.js +37 -0
  85. package/dist/app/sidebar/explorer/ExplorerRowMenu.d.ts +21 -0
  86. package/dist/app/sidebar/explorer/ExplorerRowMenu.js +37 -0
  87. package/dist/app/sidebar/explorer/ExplorerSections.d.ts +16 -0
  88. package/dist/app/sidebar/explorer/ExplorerSections.js +259 -0
  89. package/dist/app/sidebar/explorer/ExplorerTree.d.ts +46 -0
  90. package/dist/app/sidebar/explorer/ExplorerTree.js +387 -0
  91. package/dist/app/sidebar/explorer/explorerState.d.ts +37 -0
  92. package/dist/app/sidebar/explorer/explorerState.js +135 -0
  93. package/dist/app/tabMountPolicy.d.ts +45 -0
  94. package/dist/app/tabMountPolicy.js +104 -0
  95. package/dist/app/tabWarmOrder.d.ts +7 -0
  96. package/dist/app/tabWarmOrder.js +48 -0
  97. package/dist/app/tabs/TabFuseCurves.d.ts +3 -0
  98. package/dist/app/tabs/TabFuseCurves.js +15 -0
  99. package/dist/app/tabs/TabOverview.d.ts +24 -0
  100. package/dist/app/tabs/TabOverview.js +121 -0
  101. package/dist/app/tabs/TabStrip.d.ts +42 -0
  102. package/dist/app/tabs/TabStrip.js +380 -0
  103. package/dist/app/tabs/tabIds.d.ts +5 -0
  104. package/dist/app/tabs/tabIds.js +7 -0
  105. package/dist/app/tabs/useTabDirty.d.ts +3 -0
  106. package/dist/app/tabs/useTabDirty.js +11 -0
  107. package/dist/app/useAppChromeState.d.ts +21 -0
  108. package/dist/app/useAppChromeState.js +48 -0
  109. package/dist/app/useAppCommands.d.ts +66 -0
  110. package/dist/app/useAppCommands.js +71 -0
  111. package/dist/app/useAppDocumentCore.d.ts +210 -0
  112. package/dist/app/useAppDocumentCore.js +40 -0
  113. package/dist/app/useAppEffects.d.ts +18 -0
  114. package/dist/app/useAppEffects.js +52 -0
  115. package/dist/app/useAppPaneSearch.d.ts +37 -0
  116. package/dist/app/useAppPaneSearch.js +74 -0
  117. package/dist/app/useAppShellSetup.d.ts +40 -0
  118. package/dist/app/useAppShellSetup.js +52 -0
  119. package/dist/app/useAppSlots.d.ts +28 -0
  120. package/dist/app/useAppSlots.js +40 -0
  121. package/dist/app/useAppTabChrome.d.ts +51 -0
  122. package/dist/app/useAppTabChrome.js +66 -0
  123. package/dist/app/useAutoSave.d.ts +34 -0
  124. package/dist/app/useAutoSave.js +116 -0
  125. package/dist/app/useCloseAll.d.ts +52 -0
  126. package/dist/app/useCloseAll.js +295 -0
  127. package/dist/app/useClosedTabEviction.d.ts +10 -0
  128. package/dist/app/useClosedTabEviction.js +38 -0
  129. package/dist/app/useCommandPalette.d.ts +44 -0
  130. package/dist/app/useCommandPalette.js +254 -0
  131. package/dist/app/useCrossDocSearch.d.ts +7 -0
  132. package/dist/app/useCrossDocSearch.js +94 -0
  133. package/dist/app/useDistractionFree.d.ts +21 -0
  134. package/dist/app/useDistractionFree.js +73 -0
  135. package/dist/app/useDocumentCreation.d.ts +18 -0
  136. package/dist/app/useDocumentCreation.js +63 -0
  137. package/dist/app/useDocumentDirty.d.ts +31 -0
  138. package/dist/app/useDocumentDirty.js +46 -0
  139. package/dist/app/useDocumentLoader.d.ts +55 -0
  140. package/dist/app/useDocumentLoader.js +267 -0
  141. package/dist/app/useDocumentOutputActions.d.ts +6 -0
  142. package/dist/app/useDocumentOutputActions.js +45 -0
  143. package/dist/app/useDocumentRuntimeEffects.d.ts +36 -0
  144. package/dist/app/useDocumentRuntimeEffects.js +458 -0
  145. package/dist/app/useDocumentSaver.d.ts +58 -0
  146. package/dist/app/useDocumentSaver.js +511 -0
  147. package/dist/app/useDocumentTabs.d.ts +41 -0
  148. package/dist/app/useDocumentTabs.js +207 -0
  149. package/dist/app/useDocumentWatcher.d.ts +83 -0
  150. package/dist/app/useDocumentWatcher.js +393 -0
  151. package/dist/app/useDocumentZoom.d.ts +24 -0
  152. package/dist/app/useDocumentZoom.js +104 -0
  153. package/dist/app/useDocuments.d.ts +169 -0
  154. package/dist/app/useDocuments.js +455 -0
  155. package/dist/app/useDraftConfirmGate.d.ts +27 -0
  156. package/dist/app/useDraftConfirmGate.js +47 -0
  157. package/dist/app/useFileDragOverlay.d.ts +12 -0
  158. package/dist/app/useFileDragOverlay.js +49 -0
  159. package/dist/app/useFormatApis.d.ts +13 -0
  160. package/dist/app/useFormatApis.js +62 -0
  161. package/dist/app/useFormatDirtyState.d.ts +29 -0
  162. package/dist/app/useFormatDirtyState.js +81 -0
  163. package/dist/app/useGlobalShortcuts.d.ts +47 -0
  164. package/dist/app/useGlobalShortcuts.js +359 -0
  165. package/dist/app/useHtmlSession.d.ts +68 -0
  166. package/dist/app/useHtmlSession.js +463 -0
  167. package/dist/app/useHtmlSessionProps.d.ts +33 -0
  168. package/dist/app/useHtmlSessionProps.js +57 -0
  169. package/dist/app/useLibrary.d.ts +21 -0
  170. package/dist/app/useLibrary.js +81 -0
  171. package/dist/app/useOpenFromClipboard.d.ts +7 -0
  172. package/dist/app/useOpenFromClipboard.js +44 -0
  173. package/dist/app/usePaneLiveness.d.ts +29 -0
  174. package/dist/app/usePaneLiveness.js +199 -0
  175. package/dist/app/usePendingSavePaths.d.ts +19 -0
  176. package/dist/app/usePendingSavePaths.js +67 -0
  177. package/dist/app/useReadyShow.d.ts +12 -0
  178. package/dist/app/useReadyShow.js +142 -0
  179. package/dist/app/useSearchController.d.ts +22 -0
  180. package/dist/app/useSearchController.js +114 -0
  181. package/dist/app/useSetupRecovery.d.ts +41 -0
  182. package/dist/app/useSetupRecovery.js +153 -0
  183. package/dist/app/useTabChrome.d.ts +40 -0
  184. package/dist/app/useTabChrome.js +115 -0
  185. package/dist/app/useViewState.d.ts +27 -0
  186. package/dist/app/useViewState.js +160 -0
  187. package/dist/appName.d.ts +2 -0
  188. package/dist/appName.js +8 -0
  189. package/dist/documents/DocumentRouter.d.ts +102 -0
  190. package/dist/documents/DocumentRouter.js +153 -0
  191. package/dist/documents/FileTypeIcon.d.ts +6 -0
  192. package/dist/documents/FileTypeIcon.js +93 -0
  193. package/dist/documents/ImageDocument.d.ts +14 -0
  194. package/dist/documents/ImageDocument.js +61 -0
  195. package/dist/documents/capabilities.d.ts +17 -0
  196. package/dist/documents/capabilities.js +18 -0
  197. package/dist/documents/html/HtmlDocument.d.ts +15 -0
  198. package/dist/documents/html/HtmlDocument.js +584 -0
  199. package/dist/documents/html/HtmlDocumentLayout.d.ts +87 -0
  200. package/dist/documents/html/HtmlDocumentLayout.js +25 -0
  201. package/dist/documents/html/HtmlDocumentProps.d.ts +60 -0
  202. package/dist/documents/html/HtmlDocumentProps.js +1 -0
  203. package/dist/documents/html/HtmlDocumentSource.d.ts +34 -0
  204. package/dist/documents/html/HtmlDocumentSource.js +28 -0
  205. package/dist/documents/markdown/MarkdownSplitPane.d.ts +115 -0
  206. package/dist/documents/markdown/MarkdownSplitPane.js +352 -0
  207. package/dist/documents/mdx/MdxSplitPane.d.ts +32 -0
  208. package/dist/documents/mdx/MdxSplitPane.js +60 -0
  209. package/dist/documents/txt/LinkDialog.d.ts +8 -0
  210. package/dist/documents/txt/LinkDialog.js +34 -0
  211. package/dist/documents/txt/MarkdownSourceToolbar.d.ts +8 -0
  212. package/dist/documents/txt/MarkdownSourceToolbar.js +25 -0
  213. package/dist/documents/txt/SourceEditorToolbar.d.ts +12 -0
  214. package/dist/documents/txt/SourceEditorToolbar.js +4 -0
  215. package/dist/documents/txt/TxtEditor.d.ts +39 -0
  216. package/dist/documents/txt/TxtEditor.js +186 -0
  217. package/dist/documents/txt/sourceEditorTypes.d.ts +49 -0
  218. package/dist/documents/txt/sourceEditorTypes.js +1 -0
  219. package/dist/documents/txt/sourceExtensions.d.ts +38 -0
  220. package/dist/documents/txt/sourceExtensions.js +444 -0
  221. package/dist/documents/txt/sourceFormatting.d.ts +18 -0
  222. package/dist/documents/txt/sourceFormatting.js +183 -0
  223. package/dist/documents/txt/sourceTheme.d.ts +5 -0
  224. package/dist/documents/txt/sourceTheme.js +220 -0
  225. package/dist/documents/txt/useCodeMirrorSourceEditor.d.ts +69 -0
  226. package/dist/documents/txt/useCodeMirrorSourceEditor.js +546 -0
  227. package/dist/documents/txt/useSourceSearch.d.ts +39 -0
  228. package/dist/documents/txt/useSourceSearch.js +122 -0
  229. package/dist/documents/txt/useTextEditorCommands.d.ts +26 -0
  230. package/dist/documents/txt/useTextEditorCommands.js +151 -0
  231. package/dist/documents/web/LivePreviewPane.d.ts +11 -0
  232. package/dist/documents/web/LivePreviewPane.js +58 -0
  233. package/dist/env.d.ts +66 -0
  234. package/dist/index.d.ts +121 -0
  235. package/dist/index.js +123 -0
  236. package/dist/settings/AppearanceMenu.d.ts +9 -0
  237. package/dist/settings/AppearanceMenu.js +54 -0
  238. package/dist/settings/SettingsPanel.d.ts +7 -0
  239. package/dist/settings/SettingsPanel.js +104 -0
  240. package/dist/settings/publishedSections.d.ts +22 -0
  241. package/dist/settings/publishedSections.js +79 -0
  242. package/dist/settings/sections/AboutSection.d.ts +1 -0
  243. package/dist/settings/sections/AboutSection.js +13 -0
  244. package/dist/settings/sections/DiagnosticsSection.d.ts +1 -0
  245. package/dist/settings/sections/DiagnosticsSection.js +42 -0
  246. package/dist/settings/sections/PrivacySection.d.ts +3 -0
  247. package/dist/settings/sections/PrivacySection.js +51 -0
  248. package/dist/settings/sections/UpdateLicenseBlock.d.ts +10 -0
  249. package/dist/settings/sections/UpdateLicenseBlock.js +158 -0
  250. package/dist/state/explorer.d.ts +32 -0
  251. package/dist/state/explorer.js +111 -0
  252. package/dist/state/legal.d.ts +51 -0
  253. package/dist/state/legal.js +130 -0
  254. package/dist/state/library.d.ts +33 -0
  255. package/dist/state/library.js +110 -0
  256. package/dist/state/updateLicense.d.ts +31 -0
  257. package/dist/state/updateLicense.js +340 -0
  258. package/dist/styles/explorer.css +219 -0
  259. package/dist/styles/index.css +1477 -0
  260. package/dist/styles/tabs.css +467 -0
  261. package/dist/styles.css +6 -0
  262. package/package.json +88 -3
@@ -0,0 +1,158 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { SettingRow, SettingsGroup, licenseSection, } from "@rightkit/settings-ui";
4
+ import { LicenseClientError, isLicensed, isPro, licenseMessage } from "@rightkit/license";
5
+ import { openExternal } from "@rightkit/document-core/state/tauriBridge";
6
+ import { UPDATE_LICENSE_URL, getLicenseClient } from "../../state/updateLicense.js";
7
+ import { PublishedLicense } from "../publishedSections.js";
8
+ /** Fields the published section displays; a native change that alters none of them needs no re-read. */
9
+ const signature = (v) => [v.mode, v.status, v.lifecycle, v.revisionState, v.kind, v.tier, v.validUntil, v.confirmationDueAt, v.staleSince, v.message]
10
+ .map(String)
11
+ .join("|");
12
+ /**
13
+ * LicenseClientLike over the native client. Retained app code: the published section needs a
14
+ * synchronous client and `getLicenseClient()` is async; the key is trimmed here because the package
15
+ * passes the pasted text through untrimmed; the first read is memoised behind a loading gate. The key is only ever a
16
+ * transient command argument.
17
+ */
18
+ function createLicenseClientLike() {
19
+ const firstRead = async () => {
20
+ const client = await getLicenseClient();
21
+ return client.status();
22
+ };
23
+ let first = null;
24
+ let firstDone = false;
25
+ return {
26
+ status: async () => {
27
+ if (!firstDone) {
28
+ first ??= firstRead().finally(() => {
29
+ firstDone = true;
30
+ });
31
+ return first;
32
+ }
33
+ return (await getLicenseClient()).status();
34
+ },
35
+ activate: async (key) => (await getLicenseClient()).activate(key.trim()),
36
+ deactivate: async () => (await getLicenseClient()).deactivate(),
37
+ refresh: async () => (await getLicenseClient()).refresh(),
38
+ };
39
+ }
40
+ /** Kind badges stay neutral; the "updates" claims below depend on the view's entitlement. */
41
+ const KIND = { trial: "Trial", term: "Term", lifetime: "Lifetime" };
42
+ function licenseLabels(pro) {
43
+ return {
44
+ sectionLabel: "Update license",
45
+ statusLabel: "Update license",
46
+ activeStatusLabel: "Update license",
47
+ searchStatus: "Update license status",
48
+ searchActivate: "Activate update license key",
49
+ free: "Free public build",
50
+ freeDetail: "Activate a key for signed in-app updates.",
51
+ attention: "Update license — needs attention",
52
+ expired: "Expired",
53
+ trial: KIND.trial,
54
+ subscription: KIND.term,
55
+ lifetime: KIND.lifetime,
56
+ activeDetail: (kind, until) => {
57
+ if (!pro)
58
+ return `${kind} license active on this device.`;
59
+ if (kind === KIND.lifetime)
60
+ return "Lifetime updates active on this device.";
61
+ if (kind === KIND.trial)
62
+ return `Trial updates active${until ? ` through ${until}` : ""}.`;
63
+ return `Updates active${until ? ` through ${until}` : ""}.`;
64
+ },
65
+ expiredDetail: (kind, until) => kind === KIND.trial
66
+ ? "Update trial expired."
67
+ : `Update license expired${until ? ` on ${until}` : ""}.`,
68
+ deactivateTitle: "Remove this license",
69
+ deactivateHint: "Frees this device so you can enter a different key.",
70
+ deactivate: "Remove license",
71
+ keyTitle: "License key",
72
+ keyHint: "Paste the key from your purchase email.",
73
+ keyAria: "Update license key",
74
+ keyPlaceholder: "VR-XXXX-XXXX-XXXX",
75
+ activate: "Activate",
76
+ activating: "Activating...",
77
+ purchaseTitle: "Need an update license?",
78
+ purchase: "Buy update license",
79
+ verifyTitle: "Update license check",
80
+ verifyHint: "Connect once to verify this purchase.",
81
+ verify: "Verify purchase",
82
+ };
83
+ }
84
+ /**
85
+ * the host app update-license block: the published `licenseSection()` (`@rightkit/settings-ui` 0.7.0)
86
+ * over the native licence client. App-owned remainder, each piece with its reason:
87
+ * the lazy client above, the Disabled-build notice, the loading gate (the package shows "Free"
88
+ * until its first read settles), the non-Pro notice (the package marks any active licence as
89
+ * licensed), the cross-window re-read on native change events (the package only reads on mount),
90
+ * and the label map. The webview holds no key or token: the key is a transient command input and
91
+ * the view is the only state. Record: docs/rightkit-exceptions/M12.md#m12-update-license-block.
92
+ */
93
+ export function UpdateLicenseBlock() {
94
+ const client = useMemo(createLicenseClientLike, []);
95
+ const [view, setView] = useState(null);
96
+ const [failure, setFailure] = useState(null);
97
+ const [revision, setRevision] = useState(0);
98
+ const shown = useRef("");
99
+ const adopt = useCallback((next) => {
100
+ if (!next)
101
+ return;
102
+ shown.current = signature(next);
103
+ setView(next);
104
+ }, []);
105
+ useEffect(() => {
106
+ let cancelled = false;
107
+ let stop;
108
+ void (async () => {
109
+ try {
110
+ const first = await client.status();
111
+ if (cancelled)
112
+ return;
113
+ adopt(first);
114
+ const release = await (await getLicenseClient()).onChange((changed) => {
115
+ if (cancelled || signature(changed) === shown.current)
116
+ return;
117
+ adopt(changed);
118
+ setRevision((n) => n + 1); // remount the section so its own read picks the change up
119
+ }, () => undefined);
120
+ if (cancelled)
121
+ release();
122
+ else
123
+ stop = release;
124
+ }
125
+ catch (error) {
126
+ if (!cancelled)
127
+ setFailure(error instanceof LicenseClientError && error.message ? error.message : licenseMessage("unknown"));
128
+ }
129
+ })();
130
+ return () => {
131
+ cancelled = true;
132
+ stop?.();
133
+ };
134
+ }, [client, adopt]);
135
+ const licensed = isLicensed(view);
136
+ const pro = isPro(view);
137
+ const section = useMemo(() => licenseSection({
138
+ client,
139
+ confirmDeactivate: false,
140
+ purchaseUrl: UPDATE_LICENSE_URL,
141
+ openExternal,
142
+ tierLabels: { pro: "Pro" },
143
+ onChange: adopt,
144
+ labels: licenseLabels(pro),
145
+ planSlot: licensed && !pro ? (_jsx(SettingsGroup, { children: _jsx(SettingRow, { label: "License active, updates not included", description: "This license does not include signed paid updates. Public patches stay available." }) })) : undefined,
146
+ }), [client, adopt, licensed, pro]);
147
+ let body = null;
148
+ if (failure) {
149
+ body = (_jsx(SettingsGroup, { title: "Update license", children: _jsx(SettingRow, { label: "Update license", description: _jsx("span", { role: "alert", children: failure }) }) }));
150
+ }
151
+ else if (view?.mode === "disabled") {
152
+ body = (_jsx(SettingsGroup, { title: "Update license", children: _jsx(SettingRow, { label: "Update license", description: licenseMessage("unconfigured") }) }));
153
+ }
154
+ else if (view) {
155
+ body = _jsx(PublishedLicense, { section: section }, revision);
156
+ }
157
+ return (_jsx("div", { "data-update-license": true, "aria-busy": !view && !failure ? true : undefined, children: body }));
158
+ }
@@ -0,0 +1,32 @@
1
+ export type ExplorerLocationKind = "home" | "desktop" | "documents" | "downloads" | "icloud" | "onedrive" | "volume" | "root";
2
+ export interface ExplorerLocation {
3
+ id: string;
4
+ label: string;
5
+ kind: ExplorerLocationKind | string;
6
+ dir: string;
7
+ }
8
+ export interface ExplorerEntry {
9
+ name: string;
10
+ /** "dir" | a supported format id (e.g. "md", "pdf") | "other". */
11
+ kind: string;
12
+ /** Unix epoch milliseconds; null when unknown. */
13
+ modified: number | null;
14
+ /** Bytes; null for directories. */
15
+ size: number | null;
16
+ /** Dirs: canonical dir path. Supported files: broker-granted path (openable via `open`). */
17
+ path: string;
18
+ }
19
+ export interface ExplorerListing {
20
+ entries: ExplorerEntry[];
21
+ truncated: boolean;
22
+ }
23
+ export declare function explorerLocations(): Promise<ExplorerLocation[]>;
24
+ /** `keep` is the NAME of one child the backend must list even when its cap would cut it. */
25
+ export declare function explorerListDir(dir: string, keep?: string): Promise<ExplorerListing>;
26
+ export declare function explorerWatchDir(dir: string): Promise<void>;
27
+ export declare function explorerUnwatchDir(dir: string): Promise<void>;
28
+ /** OS-level reveal (Finder select / Explorer /select) for dirs and unsupported files — unlike
29
+ * `revealInFileExplorer` this does not need a broker grant; it only shows the file manager. */
30
+ export declare function explorerReveal(path: string): Promise<void>;
31
+ /** `explorer:changed` events fire {dir} when a watched directory changes; relist that node. */
32
+ export declare function onExplorerChanged(cb: (dir: string) => void): Promise<() => void>;
@@ -0,0 +1,111 @@
1
+ // Bridge for the Tauri explorer backend (src-tauri/src/commands/explorer.rs). Follows the same
2
+ // conventions as library.ts: lazy invoke import so vitest never touches the Tauri API, browser-QA
3
+ // stubs, and no-op returns outside Tauri.
4
+ import { inTauri, isBrowserQaMode } from "@rightkit/document-core/state/tauriBridge";
5
+ import { hostAppName } from "../appName.js";
6
+ async function invoke(cmd, args) {
7
+ const { invoke } = await import("@tauri-apps/api/core");
8
+ return invoke(cmd, args);
9
+ }
10
+ const QA_ROOT = `D:\\${hostAppName()} QA`;
11
+ const QA_LOCATIONS = [
12
+ { id: "home", label: "Home", kind: "home", dir: QA_ROOT },
13
+ { id: "desktop", label: "Desktop", kind: "desktop", dir: `${QA_ROOT}\\Desktop` },
14
+ { id: "documents", label: "Documents", kind: "documents", dir: QA_ROOT },
15
+ { id: "downloads", label: "Downloads", kind: "downloads", dir: `${QA_ROOT}\\Downloads` },
16
+ { id: "c", label: "Windows (C:)", kind: "volume", dir: "C:\\" },
17
+ ];
18
+ const QA_DIRS = {
19
+ [QA_ROOT]: [
20
+ { name: "Notes", kind: "dir", modified: null, size: null, path: `${QA_ROOT}\\Notes` },
21
+ { name: "Specs", kind: "dir", modified: null, size: null, path: `${QA_ROOT}\\Specs` },
22
+ {
23
+ name: "source-notes.md",
24
+ kind: "md",
25
+ modified: 1_725_000_000_000,
26
+ size: 4210,
27
+ path: `${QA_ROOT}\\source-notes.md`,
28
+ },
29
+ {
30
+ name: "local-preview.html",
31
+ kind: "html",
32
+ modified: 1_724_000_000_000,
33
+ size: 9182,
34
+ path: `${QA_ROOT}\\local-preview.html`,
35
+ },
36
+ {
37
+ name: "scratch.txt",
38
+ kind: "txt",
39
+ modified: 1_723_000_000_000,
40
+ size: 812,
41
+ path: `${QA_ROOT}\\scratch.txt`,
42
+ },
43
+ {
44
+ name: "installer.msi",
45
+ kind: "other",
46
+ modified: 1_722_000_000_000,
47
+ size: 5_242_880,
48
+ path: `${QA_ROOT}\\installer.msi`,
49
+ },
50
+ ],
51
+ [`${QA_ROOT}\\Notes`]: [
52
+ {
53
+ name: "roadmap.md",
54
+ kind: "md",
55
+ modified: 1_725_100_000_000,
56
+ size: 1204,
57
+ path: `${QA_ROOT}\\Notes\\roadmap.md`,
58
+ },
59
+ ],
60
+ [`${QA_ROOT}\\Specs`]: [],
61
+ [`${QA_ROOT}\\Desktop`]: [],
62
+ [`${QA_ROOT}\\Downloads`]: [],
63
+ "C:\\": [],
64
+ };
65
+ export async function explorerLocations() {
66
+ if (isBrowserQaMode())
67
+ return QA_LOCATIONS;
68
+ if (!inTauri())
69
+ return [];
70
+ return invoke("explorer_locations");
71
+ }
72
+ /** `keep` is the NAME of one child the backend must list even when its cap would cut it. */
73
+ export async function explorerListDir(dir, keep) {
74
+ if (isBrowserQaMode())
75
+ return { entries: QA_DIRS[dir] ?? [], truncated: false };
76
+ if (!inTauri())
77
+ return { entries: [], truncated: false };
78
+ return invoke("explorer_list_dir", keep === undefined ? { dir } : { dir, keep });
79
+ }
80
+ export async function explorerWatchDir(dir) {
81
+ if (isBrowserQaMode() || !inTauri())
82
+ return;
83
+ await invoke("explorer_watch_dir", { dir });
84
+ }
85
+ export async function explorerUnwatchDir(dir) {
86
+ if (isBrowserQaMode() || !inTauri())
87
+ return;
88
+ await invoke("explorer_unwatch_dir", { dir });
89
+ }
90
+ /** OS-level reveal (Finder select / Explorer /select) for dirs and unsupported files — unlike
91
+ * `revealInFileExplorer` this does not need a broker grant; it only shows the file manager. */
92
+ export async function explorerReveal(path) {
93
+ if (isBrowserQaMode() || !inTauri())
94
+ return;
95
+ await invoke("explorer_reveal", { path });
96
+ }
97
+ /** `explorer:changed` events fire {dir} when a watched directory changes; relist that node. */
98
+ export async function onExplorerChanged(cb) {
99
+ if (isBrowserQaMode() || !inTauri())
100
+ return () => { };
101
+ const { listen } = await import("@tauri-apps/api/event");
102
+ const un = await listen("explorer:changed", (e) => cb(e.payload.dir));
103
+ return () => {
104
+ try {
105
+ un();
106
+ }
107
+ catch {
108
+ /* bridge teardown race */
109
+ }
110
+ };
111
+ }
@@ -0,0 +1,51 @@
1
+ import type { LegalAcceptanceRecord, SettingsBackend } from "@rightkit/onboarding";
2
+ import type { Settings } from "@rightkit/document-core/settings/settings";
3
+ /** The host app's generated acceptance contract (src/generated/legal-contract.json). */
4
+ export interface LegalContract {
5
+ acceptanceVersion: string;
6
+ materialSha256: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export declare let REQUIRED_LEGAL_ACCEPTANCE_VERSION: string;
10
+ export declare let LEGAL_MATERIAL_SHA256: string;
11
+ export type LegalEligibilityBasis = NonNullable<Settings["legalEligibilityBasis"]>;
12
+ /** The four flat settings fields that together form the host app acceptance receipt. */
13
+ export type LegalReceiptFields = Pick<Settings, "legalAcceptanceVersion" | "legalAcceptedAt" | "legalEligibilityBasis" | "legalMaterialSha256">;
14
+ /**
15
+ * The checkout-role documents shown on the first-run/re-acceptance gate: every
16
+ * manifest document EXCEPT third_party_notices (a build-provenance appendix —
17
+ * not something a user agrees to at first run). Titles/URLs are sourced from
18
+ * legal-manifest.json, never hardcoded, so a publicUrl change (e.g. VR's
19
+ * privacy_notice lives at /privacy/, not /legal/privacy/) or a title change
20
+ * propagates automatically instead of drifting out of sync with the gate.
21
+ */
22
+ export interface LegalGateDocumentLink {
23
+ title: string;
24
+ url: string;
25
+ }
26
+ export declare let LEGAL_GATE_DOCUMENTS: LegalGateDocumentLink[];
27
+ /** Permanent legal links in Settings → About: every manifest document, with About's short names. */
28
+ export declare let LEGAL_ABOUT_LINKS: LegalGateDocumentLink[];
29
+ /** The host hands over its legal/legal-manifest.json and src/generated/legal-contract.json once at startup. */
30
+ export declare function configureLegal({ manifest, contract }: {
31
+ manifest: unknown;
32
+ contract: LegalContract;
33
+ }): void;
34
+ /** True only when every field of the acceptance receipt is current: the
35
+ * acceptance version and material-document hash match the generated
36
+ * contract (src/generated/legal-contract.json, synced from legal-manifest.json
37
+ * by scripts/sync-legal-acceptance-contract.mjs), the timestamp is a
38
+ * canonical UTC instant, and an eligibility basis was recorded. */
39
+ export declare function legalAcceptanceCurrent(settings: LegalReceiptFields): boolean;
40
+ /** Map the flat settings receipt to the onboarding package's record (`null` when no receipt is stored). */
41
+ export declare function legalReceiptRecord(settings: LegalReceiptFields): LegalAcceptanceRecord | null;
42
+ /** Inverse of legalReceiptRecord(): the settings patch that stores one acceptance. */
43
+ export declare function legalReceiptFields(record: LegalAcceptanceRecord): LegalReceiptFields;
44
+ /** Onboarding's `isAccepted`: the stored record must pass every legalAcceptanceCurrent() rule. */
45
+ export declare function legalRecordCurrent(record: LegalAcceptanceRecord | undefined): boolean;
46
+ /**
47
+ * Backing store for onboarding's own progress record (`onboarding.state`). The legal receipt is NOT
48
+ * kept here: it stays in the settings store and reaches onboarding through `legalReceipt`. A storage
49
+ * failure throws so the gate surfaces it instead of silently dropping progress.
50
+ */
51
+ export declare function createOnboardingSettingsBackend(): SettingsBackend;
@@ -0,0 +1,130 @@
1
+ import { createAcceptanceReceipt, isCanonicalUtcTimestamp, needsLegalAcceptance, } from "@rightkit/legal";
2
+ // Set once by the host at startup (configureLegal): a published package cannot import files of the app that installs it.
3
+ // ES module exports are live bindings, so every importer sees the configured values.
4
+ let legalManifest;
5
+ export let REQUIRED_LEGAL_ACCEPTANCE_VERSION;
6
+ export let LEGAL_MATERIAL_SHA256;
7
+ // The manifest's suite-wide document titles ("Right Suite Desktop License v1.0
8
+ // Ownership Notice") are too long for the gate's compact document list — these
9
+ // three roles get a short display title instead. product_schedule and
10
+ // privacy_notice already carry the host app-specific titles in the manifest
11
+ // ("the host app Product Schedule" / "the host app Privacy Notice"), so those pass
12
+ // through unchanged.
13
+ const GATE_DOCUMENT_SHORT_TITLES = {
14
+ license: "License",
15
+ eula: "End User License Agreement",
16
+ acceptable_use: "Acceptable Use Policy",
17
+ };
18
+ function manifestLinks(shortTitles, excludeRoles = []) {
19
+ return legalManifest.documents
20
+ .filter((document) => !excludeRoles.includes(document.role))
21
+ .map((document) => ({
22
+ title: shortTitles[document.role] ?? document.title,
23
+ url: document.publicUrl,
24
+ }));
25
+ }
26
+ export let LEGAL_GATE_DOCUMENTS = [];
27
+ /** Permanent legal links in Settings → About: every manifest document, with About's short names. */
28
+ export let LEGAL_ABOUT_LINKS = [];
29
+ /** The host hands over its legal/legal-manifest.json and src/generated/legal-contract.json once at startup. */
30
+ export function configureLegal({ manifest, contract }) {
31
+ const m = manifest;
32
+ if (!m || !Array.isArray(m.documents))
33
+ throw new TypeError("configureLegal: a legal manifest with documents is required");
34
+ if (typeof contract?.acceptanceVersion !== "string" || typeof contract?.materialSha256 !== "string") {
35
+ throw new TypeError("configureLegal: the contract needs acceptanceVersion and materialSha256 strings");
36
+ }
37
+ legalManifest = m;
38
+ REQUIRED_LEGAL_ACCEPTANCE_VERSION = contract.acceptanceVersion;
39
+ LEGAL_MATERIAL_SHA256 = contract.materialSha256;
40
+ LEGAL_GATE_DOCUMENTS = manifestLinks(GATE_DOCUMENT_SHORT_TITLES, ["third_party_notices"]);
41
+ LEGAL_ABOUT_LINKS = manifestLinks({
42
+ license: "Ownership Notice",
43
+ eula: "EULA",
44
+ acceptable_use: "Acceptable Use",
45
+ product_schedule: "Product Schedule",
46
+ privacy_notice: "Privacy",
47
+ third_party_notices: "Third-party Notices",
48
+ });
49
+ }
50
+ /** True only when every field of the acceptance receipt is current: the
51
+ * acceptance version and material-document hash match the generated
52
+ * contract (src/generated/legal-contract.json, synced from legal-manifest.json
53
+ * by scripts/sync-legal-acceptance-contract.mjs), the timestamp is a
54
+ * canonical UTC instant, and an eligibility basis was recorded. */
55
+ export function legalAcceptanceCurrent(settings) {
56
+ const basis = settings.legalEligibilityBasis;
57
+ if (!isCanonicalUtcTimestamp(settings.legalAcceptedAt) ||
58
+ (basis !== "individual" && basis !== "enterprise") ||
59
+ settings.legalMaterialSha256 !== LEGAL_MATERIAL_SHA256) {
60
+ return false;
61
+ }
62
+ // The stored acceptance is the flat settings fields, not a document-level receipt. Material
63
+ // hash equality (above) proves the agreed documents are unchanged, so the receipt is rebuilt from
64
+ // the manifest carrying the STORED acceptance version, and the package gate checks schema,
65
+ // app key and version against the manifest.
66
+ const manifest = legalManifest;
67
+ const receipt = {
68
+ ...createAcceptanceReceipt(manifest, {
69
+ acceptedAt: settings.legalAcceptedAt,
70
+ surface: "first_run",
71
+ eligibilityBasis: basis,
72
+ }),
73
+ acceptanceVersion: settings.legalAcceptanceVersion,
74
+ };
75
+ return !needsLegalAcceptance(manifest, receipt);
76
+ }
77
+ /** Map the flat settings receipt to the onboarding package's record (`null` when no receipt is stored). */
78
+ export function legalReceiptRecord(settings) {
79
+ const basis = settings.legalEligibilityBasis;
80
+ if (!settings.legalAcceptanceVersion ||
81
+ !settings.legalMaterialSha256 ||
82
+ !isCanonicalUtcTimestamp(settings.legalAcceptedAt) ||
83
+ (basis !== "individual" && basis !== "enterprise")) {
84
+ return null;
85
+ }
86
+ return {
87
+ version: settings.legalAcceptanceVersion,
88
+ documentsHash: settings.legalMaterialSha256,
89
+ acceptedAt: settings.legalAcceptedAt,
90
+ eligibilityBasis: basis,
91
+ };
92
+ }
93
+ /** Inverse of legalReceiptRecord(): the settings patch that stores one acceptance. */
94
+ export function legalReceiptFields(record) {
95
+ return {
96
+ legalAcceptanceVersion: record.version,
97
+ legalAcceptedAt: record.acceptedAt,
98
+ legalEligibilityBasis: record.eligibilityBasis,
99
+ legalMaterialSha256: record.documentsHash,
100
+ };
101
+ }
102
+ /** Onboarding's `isAccepted`: the stored record must pass every legalAcceptanceCurrent() rule. */
103
+ export function legalRecordCurrent(record) {
104
+ return record !== undefined && legalAcceptanceCurrent(legalReceiptFields(record));
105
+ }
106
+ const ONBOARDING_STORE_KEY = "vr.onboarding.v1";
107
+ /**
108
+ * Backing store for onboarding's own progress record (`onboarding.state`). The legal receipt is NOT
109
+ * kept here: it stays in the settings store and reaches onboarding through `legalReceipt`. A storage
110
+ * failure throws so the gate surfaces it instead of silently dropping progress.
111
+ */
112
+ export function createOnboardingSettingsBackend() {
113
+ let revision = 0;
114
+ const read = () => {
115
+ const raw = localStorage.getItem(ONBOARDING_STORE_KEY);
116
+ return raw ? JSON.parse(raw) : {};
117
+ };
118
+ const snapshot = (values) => ({ values, revision });
119
+ return {
120
+ async load() {
121
+ return snapshot(read());
122
+ },
123
+ async patch(patch) {
124
+ const values = { ...read(), ...patch };
125
+ localStorage.setItem(ONBOARDING_STORE_KEY, JSON.stringify(values));
126
+ revision += 1;
127
+ return snapshot(values);
128
+ },
129
+ };
130
+ }
@@ -0,0 +1,33 @@
1
+ import { type DocFormat, type LoadedDocument, type ViewMode, type ViewMeta } from "@rightkit/document-core/documents/types";
2
+ export interface FileEntry {
3
+ /** Opaque backend token for a known file. This is not a filesystem path. */
4
+ token: string;
5
+ displayName: string;
6
+ /** Location metadata for identity/display only. Opening still exchanges token for a grant. */
7
+ displayPath?: string;
8
+ format: DocFormat;
9
+ /** Last-opened time in epoch ms (recent_files.opened_at × 1000). Undefined when unavailable. */
10
+ openedAt?: number;
11
+ }
12
+ export interface OpenFileEntry {
13
+ /** Authorized real filesystem path for an already-open file. */
14
+ path: string;
15
+ displayName: string;
16
+ format: DocFormat;
17
+ }
18
+ export declare function listRecent(): Promise<FileEntry[]>;
19
+ export declare function clearRecent(): Promise<void>;
20
+ export declare function togglePin(entry: OpenFileEntry): Promise<boolean>;
21
+ export declare function isPinnedPath(path: string): Promise<boolean>;
22
+ export interface PinEntry {
23
+ path: string;
24
+ displayName: string;
25
+ format: string;
26
+ /** "file" | "dir" — directory pins power the explorer sidebar's pinned folders. */
27
+ kind: "file" | "dir";
28
+ }
29
+ /** All pins — files AND directories (dirs first, then files, in pin order). */
30
+ export declare function listPins(): Promise<PinEntry[]>;
31
+ export declare function togglePinDir(path: string, displayName: string): Promise<boolean>;
32
+ export declare function recordRecent(doc: LoadedDocument): Promise<void>;
33
+ export declare function saveViewState(path: string, lastView: ViewMode, viewMeta?: ViewMeta): Promise<void>;
@@ -0,0 +1,110 @@
1
+ import { baseName, formatFromPath, } from "@rightkit/document-core/documents/types";
2
+ import { inTauri, isBrowserQaMode } from "@rightkit/document-core/state/tauriBridge";
3
+ import { hostAppName } from "../appName.js";
4
+ async function invoke(cmd, args) {
5
+ const { invoke } = await import("@tauri-apps/api/core");
6
+ return invoke(cmd, args);
7
+ }
8
+ function map(rows) {
9
+ return rows.map((r) => ({
10
+ token: r.path,
11
+ displayName: r.display_name,
12
+ displayPath: r.display_path,
13
+ format: r.format,
14
+ openedAt: r.opened_at ? r.opened_at * 1000 : undefined,
15
+ }));
16
+ }
17
+ export async function listRecent() {
18
+ if (isBrowserQaMode()) {
19
+ const now = Date.now();
20
+ return [
21
+ {
22
+ token: `D:\\${hostAppName()} QA\\source-notes.md`,
23
+ displayName: "source-notes.md",
24
+ format: "md",
25
+ openedAt: now - 12 * 60_000,
26
+ },
27
+ {
28
+ token: `D:\\${hostAppName()} QA\\local-preview.html`,
29
+ displayName: "local-preview.html",
30
+ format: "html",
31
+ openedAt: now - 3 * 3_600_000,
32
+ },
33
+ {
34
+ token: `D:\\${hostAppName()} QA\\scratch.txt`,
35
+ displayName: "scratch.txt",
36
+ format: "txt",
37
+ openedAt: now - 26 * 3_600_000,
38
+ },
39
+ ];
40
+ }
41
+ if (!inTauri())
42
+ return [];
43
+ return map(await invoke("list_recent", { limit: 20 }));
44
+ }
45
+ export async function clearRecent() {
46
+ if (isBrowserQaMode() || !inTauri())
47
+ return;
48
+ await invoke("clear_recent");
49
+ }
50
+ export async function togglePin(entry) {
51
+ if (isBrowserQaMode())
52
+ return true;
53
+ if (!inTauri())
54
+ return false;
55
+ return invoke("toggle_pin", {
56
+ path: entry.path,
57
+ displayName: entry.displayName,
58
+ format: entry.format,
59
+ });
60
+ }
61
+ export async function isPinnedPath(path) {
62
+ if (isBrowserQaMode())
63
+ return false;
64
+ if (!inTauri())
65
+ return false;
66
+ return invoke("is_pinned_path", { path });
67
+ }
68
+ /** All pins — files AND directories (dirs first, then files, in pin order). */
69
+ export async function listPins() {
70
+ if (isBrowserQaMode())
71
+ return [];
72
+ if (!inTauri())
73
+ return [];
74
+ const rows = await invoke("list_pins");
75
+ return rows.map((r) => ({
76
+ path: r.path,
77
+ displayName: r.display_name,
78
+ format: r.format,
79
+ kind: r.kind,
80
+ }));
81
+ }
82
+ export async function togglePinDir(path, displayName) {
83
+ if (isBrowserQaMode())
84
+ return true;
85
+ if (!inTauri())
86
+ return false;
87
+ return invoke("toggle_pin_dir", { path, displayName });
88
+ }
89
+ export async function recordRecent(doc) {
90
+ if (isBrowserQaMode())
91
+ return;
92
+ if (!inTauri())
93
+ return;
94
+ await invoke("record_recent", {
95
+ path: doc.path,
96
+ displayName: baseName(doc.path),
97
+ format: formatFromPath(doc.path),
98
+ });
99
+ }
100
+ export async function saveViewState(path, lastView, viewMeta) {
101
+ if (isBrowserQaMode())
102
+ return;
103
+ if (!inTauri())
104
+ return;
105
+ await invoke("save_view_state", {
106
+ path,
107
+ lastView,
108
+ viewMeta: viewMeta ? JSON.stringify(viewMeta) : null,
109
+ });
110
+ }
@@ -0,0 +1,31 @@
1
+ import { type LicenseClient } from "@rightkit/license";
2
+ import { type AutoUpdateStatus, type UpdateTier } from "@rightkit/app-update";
3
+ export type UpdateState = "idle" | "checking" | "current" | "available" | "available-external" | "installing" | "install-failed" | "failed" | "license-required";
4
+ export declare function resolvedAppVersion(): string;
5
+ export declare const APP_VERSION: string;
6
+ export declare const UPDATE_LICENSE_URL = "https://viewright.cc/pricing/";
7
+ export type { UpdateTier };
8
+ export declare function getLicenseClient(): Promise<LicenseClient>;
9
+ export declare function openPendingExternalUpdate(): Promise<void>;
10
+ export declare const UPDATE_CHECK_CACHE_KEY = "vr.updateCheck.v3";
11
+ export declare function checkForUpdate(setLatestVersion: (version: string) => void, setUpdateState: (state: UpdateState) => void, setLatestTier?: (tier: UpdateTier | null) => void): Promise<UpdateState>;
12
+ export declare function installPendingUpdate(setUpdateState: (state: UpdateState) => void, setInstallError?: (message: string) => void): Promise<UpdateState>;
13
+ /** True while a manual-download installer URL is staged (public fallback or failed patch install). */
14
+ export declare function hasPendingExternalUpdate(): boolean;
15
+ /**
16
+ * the host app update flow as the function-style client `@rightkit/settings-ui` `updatesSection`
17
+ * expects (`UpdatesAdapter`): check()/install() resolve to an `AutoUpdateStatus`. The explicit
18
+ * check -> install split, the last-known-good cache and the public-release fallback stay in
19
+ * checkForUpdate()/installPendingUpdate(); this only maps their UpdateState into the shared status.
20
+ * `onChange` fires after each call so UI outside the section can re-read hasPendingExternalUpdate().
21
+ */
22
+ export declare function createHostUpdatesAdapter(onChange?: () => void): {
23
+ check(): Promise<AutoUpdateStatus>;
24
+ install(): Promise<AutoUpdateStatus>;
25
+ };
26
+ /** Startup check through the native host. The host reads the licence record, so a paid update is
27
+ * announced for a licensed user; a failure is advisory and returns null. */
28
+ export declare function checkForBackgroundUpdate(): Promise<{
29
+ version: string;
30
+ tier: UpdateTier | null;
31
+ } | null>;