@peers-app/peers-ui 0.27.3 → 0.27.4

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 (309) hide show
  1. package/dist/screens/network-viewer/network-viewer-ipc.d.ts +3 -1
  2. package/dist/screens/network-viewer/network-viewer-ipc.js +6 -0
  3. package/dist/screens/network-viewer/sync-recovery.js +103 -1
  4. package/dist/screens/variables/variable-details.js +2 -1
  5. package/dist/tabs-layout/network-status-indicator.js +26 -12
  6. package/dist/tabs-layout/use-network-status.d.ts +6 -1
  7. package/dist/tabs-layout/use-network-status.js +27 -4
  8. package/package.json +9 -3
  9. package/.claude/settings.local.json +0 -34
  10. package/.github/README.md +0 -52
  11. package/.github/workflows/delete-all-artifacts.yml +0 -49
  12. package/.github/workflows/publish.yml +0 -51
  13. package/babel.config.js +0 -7
  14. package/biome.json +0 -198
  15. package/dist/app-updates/app-updates-consumer.test.d.ts +0 -1
  16. package/dist/app-updates/app-updates-consumer.test.js +0 -56
  17. package/dist/app-updates/app-updates-settings.test.d.ts +0 -1
  18. package/dist/app-updates/app-updates-settings.test.js +0 -93
  19. package/dist/app-updates/remote-app-update-panel.test.d.ts +0 -1
  20. package/dist/app-updates/remote-app-update-panel.test.js +0 -165
  21. package/dist/components/access-level-field.test.d.ts +0 -1
  22. package/dist/components/access-level-field.test.js +0 -28
  23. package/dist/components/message-logs/tool-access-approval-card.test.d.ts +0 -1
  24. package/dist/components/message-logs/tool-access-approval-card.test.js +0 -102
  25. package/dist/components/responsive-section-nav.test.d.ts +0 -1
  26. package/dist/components/responsive-section-nav.test.js +0 -45
  27. package/dist/globals-hash.test.d.ts +0 -1
  28. package/dist/globals-hash.test.js +0 -16
  29. package/dist/hooks/use-observable-state.test.d.ts +0 -1
  30. package/dist/hooks/use-observable-state.test.js +0 -64
  31. package/dist/hooks/use-observable.test.d.ts +0 -1
  32. package/dist/hooks/use-observable.test.js +0 -191
  33. package/dist/hooks/use-rows.test.d.ts +0 -1
  34. package/dist/hooks/use-rows.test.js +0 -175
  35. package/dist/hooks/use-tool.test.d.ts +0 -1
  36. package/dist/hooks/use-tool.test.js +0 -190
  37. package/dist/host-shell/host-shell-consumer.test.d.ts +0 -1
  38. package/dist/host-shell/host-shell-consumer.test.js +0 -28
  39. package/dist/root-layout/root-layout-host.test.d.ts +0 -1
  40. package/dist/root-layout/root-layout-host.test.js +0 -86
  41. package/dist/screens/account/account-screen.test.d.ts +0 -1
  42. package/dist/screens/account/account-screen.test.js +0 -51
  43. package/dist/screens/assistants/assistant-config.test.d.ts +0 -1
  44. package/dist/screens/assistants/assistant-config.test.js +0 -57
  45. package/dist/screens/contacts/contact-list.test.d.ts +0 -1
  46. package/dist/screens/contacts/contact-list.test.js +0 -48
  47. package/dist/screens/device-pairing/device-pairing.test.d.ts +0 -1
  48. package/dist/screens/device-pairing/device-pairing.test.js +0 -119
  49. package/dist/screens/devices/devices-list.test.d.ts +0 -1
  50. package/dist/screens/devices/devices-list.test.js +0 -53
  51. package/dist/screens/groups/group-list.test.d.ts +0 -1
  52. package/dist/screens/groups/group-list.test.js +0 -38
  53. package/dist/screens/identity/identity-routes.test.d.ts +0 -1
  54. package/dist/screens/identity/identity-routes.test.js +0 -51
  55. package/dist/screens/identity/identity-screen.test.d.ts +0 -1
  56. package/dist/screens/identity/identity-screen.test.js +0 -103
  57. package/dist/screens/invites/accept-invite.test.d.ts +0 -1
  58. package/dist/screens/invites/accept-invite.test.js +0 -103
  59. package/dist/screens/invites/activity-view.test.d.ts +0 -1
  60. package/dist/screens/invites/activity-view.test.js +0 -108
  61. package/dist/screens/invites/invite-classify.test.d.ts +0 -1
  62. package/dist/screens/invites/invite-classify.test.js +0 -115
  63. package/dist/screens/network-viewer/network-viewer-ipc.test.d.ts +0 -1
  64. package/dist/screens/network-viewer/network-viewer-ipc.test.js +0 -61
  65. package/dist/screens/network-viewer/network-viewer.section.test.d.ts +0 -1
  66. package/dist/screens/network-viewer/network-viewer.section.test.js +0 -63
  67. package/dist/screens/network-viewer/sync-recovery.test.d.ts +0 -1
  68. package/dist/screens/network-viewer/sync-recovery.test.js +0 -104
  69. package/dist/screens/packages/package-helpers.test.d.ts +0 -1
  70. package/dist/screens/packages/package-helpers.test.js +0 -53
  71. package/dist/screens/packages/package-runtime-status.test.d.ts +0 -1
  72. package/dist/screens/packages/package-runtime-status.test.js +0 -50
  73. package/dist/screens/packages/packages-ipc.test.d.ts +0 -1
  74. package/dist/screens/packages/packages-ipc.test.js +0 -43
  75. package/dist/screens/settings/settings-page.test.d.ts +0 -1
  76. package/dist/screens/settings/settings-page.test.js +0 -19
  77. package/dist/screens/tools/tool-access-ipc.test.d.ts +0 -1
  78. package/dist/screens/tools/tool-access-ipc.test.js +0 -40
  79. package/dist/screens/tools/tool-catalog-ipc.test.d.ts +0 -1
  80. package/dist/screens/tools/tool-catalog-ipc.test.js +0 -52
  81. package/dist/tabs-layout/network-status-indicator.test.d.ts +0 -1
  82. package/dist/tabs-layout/network-status-indicator.test.js +0 -665
  83. package/dist/tabs-layout/tabs-state.test.d.ts +0 -1
  84. package/dist/tabs-layout/tabs-state.test.js +0 -110
  85. package/dist/tabs-layout/use-network-status.test.d.ts +0 -1
  86. package/dist/tabs-layout/use-network-status.test.js +0 -45
  87. package/dist/ui-router/ui-loader.test.d.ts +0 -1
  88. package/dist/ui-router/ui-loader.test.js +0 -91
  89. package/jest.config.js +0 -25
  90. package/release-guard.js +0 -10
  91. package/src/app-updates/app-update-controls.tsx +0 -73
  92. package/src/app-updates/app-updates-consumer.test.ts +0 -83
  93. package/src/app-updates/app-updates-consumer.ts +0 -121
  94. package/src/app-updates/app-updates-settings.test.tsx +0 -109
  95. package/src/app-updates/app-updates-settings.tsx +0 -136
  96. package/src/app-updates/remote-app-update-panel.test.tsx +0 -205
  97. package/src/app-updates/remote-app-update-panel.tsx +0 -210
  98. package/src/app-updates/use-app-update-status.ts +0 -16
  99. package/src/command-palette/command-palette-ui.tsx +0 -564
  100. package/src/command-palette/command-palette.ts +0 -242
  101. package/src/components/access-level-field.test.tsx +0 -32
  102. package/src/components/access-level-field.tsx +0 -68
  103. package/src/components/checkbox.tsx +0 -25
  104. package/src/components/group-switcher.tsx +0 -526
  105. package/src/components/input-date.tsx +0 -29
  106. package/src/components/input-number.tsx +0 -83
  107. package/src/components/input.tsx +0 -25
  108. package/src/components/inverse-lazy-list.tsx +0 -107
  109. package/src/components/io-schema-values.tsx +0 -103
  110. package/src/components/io-schema.tsx +0 -259
  111. package/src/components/lazy-list.tsx +0 -115
  112. package/src/components/list-screen.tsx +0 -126
  113. package/src/components/loading-indicator.tsx +0 -7
  114. package/src/components/markdown-editor/autolink-plugin.tsx +0 -29
  115. package/src/components/markdown-editor/editor-inline.tsx +0 -9
  116. package/src/components/markdown-editor/editor.tsx +0 -158
  117. package/src/components/markdown-editor/markdown-plugin.tsx +0 -202
  118. package/src/components/markdown-editor/mention-node.ts +0 -204
  119. package/src/components/markdown-editor/mentions-plugin.tsx +0 -354
  120. package/src/components/markdown-editor/move-line-plugin.tsx +0 -186
  121. package/src/components/markdown-editor/select-line-boundary-plugin.tsx +0 -95
  122. package/src/components/markdown-editor/theme.ts +0 -46
  123. package/src/components/markdown-editor/toolbar.tsx +0 -269
  124. package/src/components/markdown-with-mentions.tsx +0 -198
  125. package/src/components/message-logs/message-logs.tsx +0 -523
  126. package/src/components/message-logs/tool-access-approval-card.test.tsx +0 -127
  127. package/src/components/message-logs/tool-access-approval-card.tsx +0 -178
  128. package/src/components/messages/avatar.tsx +0 -171
  129. package/src/components/messages/channel-message-list.tsx +0 -189
  130. package/src/components/messages/channel-view.tsx +0 -92
  131. package/src/components/messages/message-compose.tsx +0 -192
  132. package/src/components/messages/message-display.tsx +0 -231
  133. package/src/components/messages/thread-message-list.tsx +0 -135
  134. package/src/components/qr-scanner.tsx +0 -180
  135. package/src/components/responsive-section-nav.test.tsx +0 -88
  136. package/src/components/responsive-section-nav.tsx +0 -92
  137. package/src/components/router.tsx +0 -175
  138. package/src/components/save-button.tsx +0 -134
  139. package/src/components/sortable-list.tsx +0 -130
  140. package/src/components/tabs.tsx +0 -76
  141. package/src/components/tooltip.tsx +0 -43
  142. package/src/components/trust-level-badge.tsx +0 -44
  143. package/src/components/trust-level-dropdown.tsx +0 -136
  144. package/src/components/typeahead.tsx +0 -357
  145. package/src/globals-hash.test.ts +0 -19
  146. package/src/globals.tsx +0 -226
  147. package/src/hooks/index.ts +0 -8
  148. package/src/hooks/use-host-contract.ts +0 -75
  149. package/src/hooks/use-observable-state.test.tsx +0 -101
  150. package/src/hooks/use-observable-state.ts +0 -29
  151. package/src/hooks/use-observable.test.tsx +0 -258
  152. package/src/hooks/use-observable.ts +0 -67
  153. package/src/hooks/use-on-screen.ts +0 -24
  154. package/src/hooks/use-promise.ts +0 -34
  155. package/src/hooks/use-rows.test.tsx +0 -196
  156. package/src/hooks/use-rows.ts +0 -120
  157. package/src/hooks/use-subscription.ts +0 -24
  158. package/src/hooks/use-tool.test.tsx +0 -225
  159. package/src/hooks/use-tool.ts +0 -116
  160. package/src/host-shell/host-shell-consumer.test.ts +0 -32
  161. package/src/host-shell/host-shell-consumer.ts +0 -53
  162. package/src/index.tsx +0 -42
  163. package/src/mention-configs.ts +0 -185
  164. package/src/operator-console/operator-console-state.ts +0 -119
  165. package/src/operator-console/operator-console.tsx +0 -233
  166. package/src/peers-services-registration.ts +0 -6
  167. package/src/root-layout/global-overlays.ts +0 -50
  168. package/src/root-layout/layout-picker.tsx +0 -47
  169. package/src/root-layout/layouts/full-screen-layout.tsx +0 -144
  170. package/src/root-layout/layouts/tabs-with-console-layout.tsx +0 -260
  171. package/src/root-layout/root-layout-host.test.tsx +0 -108
  172. package/src/root-layout/root-layout-host.tsx +0 -147
  173. package/src/root-layout/root-layout-registry.ts +0 -51
  174. package/src/root-layout/root-layout-state.ts +0 -55
  175. package/src/root-layout/root-layout.ts +0 -32
  176. package/src/screens/account/account-screen.test.tsx +0 -65
  177. package/src/screens/account/account-screen.tsx +0 -942
  178. package/src/screens/assistants/assistant-config.test.tsx +0 -54
  179. package/src/screens/assistants/assistant-config.tsx +0 -121
  180. package/src/screens/assistants/assistant-details.tsx +0 -89
  181. package/src/screens/assistants/assistant-info.tsx +0 -66
  182. package/src/screens/assistants/assistant-list.tsx +0 -145
  183. package/src/screens/assistants/assistant-tools.tsx +0 -82
  184. package/src/screens/console-logs/console-logs-list.tsx +0 -374
  185. package/src/screens/console-logs/log-display.tsx +0 -137
  186. package/src/screens/console-logs/log-filters.tsx +0 -64
  187. package/src/screens/console-logs/mobile-log-card.tsx +0 -161
  188. package/src/screens/console-logs/resizable-table-header.tsx +0 -110
  189. package/src/screens/contacts/contact-details.tsx +0 -123
  190. package/src/screens/contacts/contact-list.test.tsx +0 -59
  191. package/src/screens/contacts/contact-list.tsx +0 -286
  192. package/src/screens/contacts/index.ts +0 -2
  193. package/src/screens/data-explorer/data-explorer.tsx +0 -633
  194. package/src/screens/data-explorer/index.ts +0 -6
  195. package/src/screens/data-explorer/query-executor.tsx +0 -520
  196. package/src/screens/device-pairing/device-pairing.test.tsx +0 -143
  197. package/src/screens/device-pairing/device-pairing.tsx +0 -461
  198. package/src/screens/device-pairing/identity-ipc.ts +0 -25
  199. package/src/screens/device-pairing/index.ts +0 -2
  200. package/src/screens/device-pairing/use-device-pairing-state.ts +0 -15
  201. package/src/screens/devices/devices-list.test.tsx +0 -68
  202. package/src/screens/devices/devices-list.tsx +0 -365
  203. package/src/screens/devices/index.ts +0 -1
  204. package/src/screens/groups/group-details.tsx +0 -160
  205. package/src/screens/groups/group-invite-panel.tsx +0 -311
  206. package/src/screens/groups/group-list.test.tsx +0 -44
  207. package/src/screens/groups/group-list.tsx +0 -317
  208. package/src/screens/groups/group-members.tsx +0 -343
  209. package/src/screens/groups/index.ts +0 -3
  210. package/src/screens/identity/identity-routes.test.ts +0 -70
  211. package/src/screens/identity/identity-routes.ts +0 -301
  212. package/src/screens/identity/identity-screen.test.tsx +0 -138
  213. package/src/screens/identity/identity-screen.tsx +0 -282
  214. package/src/screens/identity/index.ts +0 -2
  215. package/src/screens/identity/invite-contact-panel.tsx +0 -45
  216. package/src/screens/identity/profile-invite.tsx +0 -93
  217. package/src/screens/invites/accept-invite.test.tsx +0 -115
  218. package/src/screens/invites/accept-invite.tsx +0 -318
  219. package/src/screens/invites/activity-view.test.tsx +0 -127
  220. package/src/screens/invites/activity-view.tsx +0 -162
  221. package/src/screens/invites/index.ts +0 -6
  222. package/src/screens/invites/invite-capture.ts +0 -104
  223. package/src/screens/invites/invite-classify.test.ts +0 -129
  224. package/src/screens/invites/invite-share.tsx +0 -104
  225. package/src/screens/invites/invites-ipc.ts +0 -25
  226. package/src/screens/invites/pending-invites-list.tsx +0 -256
  227. package/src/screens/network-viewer/connection-troubleshooter.tsx +0 -395
  228. package/src/screens/network-viewer/cpu-usage-graph.tsx +0 -294
  229. package/src/screens/network-viewer/device-details-modal.tsx +0 -339
  230. package/src/screens/network-viewer/group-details-modal.tsx +0 -421
  231. package/src/screens/network-viewer/index.ts +0 -8
  232. package/src/screens/network-viewer/network-viewer-ipc.test.ts +0 -72
  233. package/src/screens/network-viewer/network-viewer-ipc.ts +0 -39
  234. package/src/screens/network-viewer/network-viewer-section.ts +0 -12
  235. package/src/screens/network-viewer/network-viewer.section.test.tsx +0 -68
  236. package/src/screens/network-viewer/network-viewer.tsx +0 -708
  237. package/src/screens/network-viewer/remote-logs-panel.tsx +0 -190
  238. package/src/screens/network-viewer/sync-recovery.test.tsx +0 -114
  239. package/src/screens/network-viewer/sync-recovery.tsx +0 -461
  240. package/src/screens/network-viewer/usage-graph.tsx +0 -455
  241. package/src/screens/packages/local-folder-grants-panel.tsx +0 -290
  242. package/src/screens/packages/local-folders-ipc.ts +0 -28
  243. package/src/screens/packages/package-details.tsx +0 -166
  244. package/src/screens/packages/package-helpers.test.ts +0 -57
  245. package/src/screens/packages/package-helpers.ts +0 -137
  246. package/src/screens/packages/package-info.tsx +0 -354
  247. package/src/screens/packages/package-list.tsx +0 -519
  248. package/src/screens/packages/package-network-panel.tsx +0 -82
  249. package/src/screens/packages/package-new-local.tsx +0 -100
  250. package/src/screens/packages/package-runtime-status.test.tsx +0 -58
  251. package/src/screens/packages/package-runtime-status.tsx +0 -68
  252. package/src/screens/packages/package-versions.tsx +0 -298
  253. package/src/screens/packages/packages-ipc.test.ts +0 -47
  254. package/src/screens/packages/packages-ipc.ts +0 -125
  255. package/src/screens/peer-types/peer-type-details.tsx +0 -172
  256. package/src/screens/peer-types/peer-type-list.tsx +0 -64
  257. package/src/screens/search/global-search.tsx +0 -406
  258. package/src/screens/settings/color-mode-dropdown.tsx +0 -82
  259. package/src/screens/settings/settings-page.test.tsx +0 -24
  260. package/src/screens/settings/settings-page.tsx +0 -426
  261. package/src/screens/setup-user.tsx +0 -355
  262. package/src/screens/tools/tool-access-ipc.test.ts +0 -55
  263. package/src/screens/tools/tool-access-ipc.ts +0 -27
  264. package/src/screens/tools/tool-catalog-ipc.test.ts +0 -52
  265. package/src/screens/tools/tool-catalog-ipc.ts +0 -51
  266. package/src/screens/tools/tool-details.tsx +0 -52
  267. package/src/screens/tools/tool-info.tsx +0 -45
  268. package/src/screens/tools/tool-list.tsx +0 -106
  269. package/src/screens/tools/tool-schema.tsx +0 -44
  270. package/src/screens/tools/tool-test-details.tsx +0 -89
  271. package/src/screens/tools/tool-test-list.tsx +0 -73
  272. package/src/screens/variables/variable-details.tsx +0 -289
  273. package/src/screens/variables/variable-list.tsx +0 -110
  274. package/src/screens/welcome-modal.tsx +0 -294
  275. package/src/screens/workflows/workflow-details.tsx +0 -115
  276. package/src/screens/workflows/workflow-info.tsx +0 -22
  277. package/src/screens/workflows/workflow-instructions.tsx +0 -134
  278. package/src/screens/workflows/workflow-list.tsx +0 -117
  279. package/src/setupTests.ts +0 -38
  280. package/src/system-apps/assistants.app.ts +0 -7
  281. package/src/system-apps/console-logs.app.ts +0 -7
  282. package/src/system-apps/data-explorer.app.ts +0 -8
  283. package/src/system-apps/identity.app.ts +0 -9
  284. package/src/system-apps/index.ts +0 -77
  285. package/src/system-apps/mobile-settings.app.ts +0 -7
  286. package/src/system-apps/network-viewer.app.ts +0 -8
  287. package/src/system-apps/packages.app.ts +0 -7
  288. package/src/system-apps/search.app.ts +0 -8
  289. package/src/system-apps/settings.app.ts +0 -7
  290. package/src/system-apps/threads.app.ts +0 -7
  291. package/src/system-apps/tools.app.ts +0 -7
  292. package/src/system-apps/types.app.ts +0 -7
  293. package/src/system-apps/variables.app.ts +0 -7
  294. package/src/system-apps/workflows.app.ts +0 -7
  295. package/src/tabs-layout/network-status-indicator.test.tsx +0 -799
  296. package/src/tabs-layout/network-status-indicator.tsx +0 -756
  297. package/src/tabs-layout/tabs-layout.tsx +0 -857
  298. package/src/tabs-layout/tabs-state.test.ts +0 -152
  299. package/src/tabs-layout/tabs-state.ts +0 -587
  300. package/src/tabs-layout/use-network-status.test.tsx +0 -58
  301. package/src/tabs-layout/use-network-status.ts +0 -68
  302. package/src/ui-defaults/index.ts +0 -2
  303. package/src/ui-defaults/list-screen.tsx +0 -94
  304. package/src/ui-defaults/markdown-field.tsx +0 -87
  305. package/src/ui-router/routes-loader.ts +0 -193
  306. package/src/ui-router/ui-loader.test.tsx +0 -108
  307. package/src/ui-router/ui-loader.tsx +0 -606
  308. package/src/utils.ts +0 -95
  309. package/tsconfig.json +0 -18
@@ -1,633 +0,0 @@
1
- import { useCallback, useEffect, useState } from "react";
2
- import { LoadingIndicator } from "../../components/loading-indicator";
3
- import { isDesktop } from "../../globals";
4
- import { registerInternalPeersUI } from "../../ui-router/ui-loader";
5
-
6
- interface ITableInfo {
7
- tableName: string;
8
- tableId?: string;
9
- isRegistered: boolean;
10
- sql?: string;
11
- type?: string;
12
- rowCount?: number;
13
- bytes?: number;
14
- }
15
-
16
- interface IDeletedTableInfo {
17
- tableName: string;
18
- tableId: string;
19
- deletedAt: string;
20
- }
21
-
22
- type DataExplorerElectronApi = {
23
- getCurrentContext: () => Promise<{ contextName: string }>;
24
- getAllTables: () => Promise<ITableInfo[]>;
25
- compactDatabase: (beforeTimestamp?: number) => Promise<void>;
26
- resetChangeTracking: () => Promise<void>;
27
- deleteTable: (tableName: string) => Promise<void>;
28
- getDeletedTables: () => Promise<IDeletedTableInfo[]>;
29
- };
30
-
31
- type WindowWithDataExplorer = Window & {
32
- electronAPI?: { dataExplorer?: DataExplorerElectronApi };
33
- };
34
-
35
- function getDataExplorerApi(): DataExplorerElectronApi | undefined {
36
- return (window as WindowWithDataExplorer).electronAPI?.dataExplorer;
37
- }
38
-
39
- function formatRelativeTime(isoString: string): string {
40
- const date = new Date(isoString);
41
- const now = Date.now();
42
- const diffMs = now - date.getTime();
43
- const diffMin = Math.floor(diffMs / 60_000);
44
- if (diffMin < 1) return "just now";
45
- if (diffMin < 60) return `${diffMin}m ago`;
46
- const diffHrs = Math.floor(diffMin / 60);
47
- if (diffHrs < 24) return `${diffHrs}h ago`;
48
- const diffDays = Math.floor(diffHrs / 24);
49
- if (diffDays < 30) return `${diffDays}d ago`;
50
- return date.toLocaleDateString();
51
- }
52
-
53
- function DeleteConfirmModal({
54
- tableName,
55
- onConfirm,
56
- onCancel,
57
- }: {
58
- tableName: string;
59
- onConfirm: () => void;
60
- onCancel: () => void;
61
- }) {
62
- const [confirmText, setConfirmText] = useState("");
63
- const [deleting, setDeleting] = useState(false);
64
-
65
- const handleConfirm = async () => {
66
- setDeleting(true);
67
- try {
68
- await onConfirm();
69
- } finally {
70
- setDeleting(false);
71
- }
72
- };
73
-
74
- return (
75
- <div
76
- className="position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center"
77
- style={{ zIndex: 1050, backgroundColor: "rgba(0,0,0,0.5)" }}
78
- onClick={onCancel}
79
- >
80
- <div
81
- className="card shadow-lg"
82
- style={{ maxWidth: 480, width: "100%" }}
83
- onClick={(e) => e.stopPropagation()}
84
- >
85
- <div className="card-header bg-danger text-white d-flex justify-content-between align-items-center">
86
- <strong>Delete Table</strong>
87
- <button type="button" className="btn-close btn-close-white" onClick={onCancel} />
88
- </div>
89
- <div className="card-body">
90
- <div className="alert alert-danger mb-3">
91
- <i className="bi bi-exclamation-triangle-fill me-2" />
92
- This will permanently delete all data for <strong>{tableName}</strong> on this device
93
- and all synced devices once synced.
94
- </div>
95
- <label className="form-label">
96
- Type <strong>{tableName}</strong> to confirm:
97
- </label>
98
- <input
99
- type="text"
100
- className="form-control"
101
- value={confirmText}
102
- onChange={(e) => setConfirmText(e.target.value)}
103
- placeholder={tableName}
104
- // biome-ignore lint/a11y/noAutofocus: confirmation input needs immediate focus
105
- autoFocus
106
- />
107
- </div>
108
- <div className="card-footer d-flex justify-content-end gap-2">
109
- <button
110
- type="button"
111
- className="btn btn-secondary"
112
- onClick={onCancel}
113
- disabled={deleting}
114
- >
115
- Cancel
116
- </button>
117
- <button
118
- type="button"
119
- className="btn btn-danger"
120
- disabled={confirmText !== tableName || deleting}
121
- onClick={handleConfirm}
122
- >
123
- {deleting ? (
124
- <>
125
- <span className="spinner-border spinner-border-sm me-1" />
126
- Deleting...
127
- </>
128
- ) : (
129
- "Delete Table"
130
- )}
131
- </button>
132
- </div>
133
- </div>
134
- </div>
135
- );
136
- }
137
-
138
- export function DataExplorerList() {
139
- const [tables, setTables] = useState<ITableInfo[]>([]);
140
- const [deletedTables, setDeletedTables] = useState<IDeletedTableInfo[]>([]);
141
- const [loading, setLoading] = useState(true);
142
- const [currentContext, setCurrentContext] = useState<string>("");
143
- const [compacting, setCompacting] = useState(false);
144
- const [deleteTarget, setDeleteTarget] = useState<string | null>(null);
145
-
146
- const formatBytes = (bytes: number | undefined) => {
147
- if (bytes === undefined) return "-";
148
- if (bytes === 0) return "0 B";
149
- const k = 1024;
150
- const sizes = ["B", "KB", "MB", "GB"];
151
- const i = Math.floor(Math.log(bytes) / Math.log(k));
152
- return `${Math.round(bytes / k ** i)} ${sizes[i]}`;
153
- };
154
-
155
- const getBytesColorClass = (bytes: number | undefined): string => {
156
- if (bytes === undefined) return "text-secondary";
157
- const kb = 1024;
158
- const mb = kb * 1024;
159
-
160
- if (bytes < 10 * kb) return "text-secondary";
161
- if (bytes < 10 * mb) return "text-primary";
162
- if (bytes < 100 * mb) return "text-warning";
163
- return "text-danger";
164
- };
165
-
166
- const loadTables = useCallback(async () => {
167
- try {
168
- if (!isDesktop()) return;
169
-
170
- const api = getDataExplorerApi();
171
- if (!api) {
172
- console.warn("Data Explorer API not available");
173
- return;
174
- }
175
-
176
- const contextInfo = await api.getCurrentContext();
177
- setCurrentContext(contextInfo.contextName);
178
-
179
- const allTablesInfo = await api.getAllTables();
180
- allTablesInfo.sort((a: ITableInfo, b: ITableInfo) => {
181
- if (a.isRegistered !== b.isRegistered) {
182
- return a.isRegistered ? -1 : 1;
183
- }
184
- return a.tableName.localeCompare(b.tableName);
185
- });
186
- setTables(allTablesInfo);
187
-
188
- const deleted = await api.getDeletedTables();
189
- deleted.sort((a, b) => a.tableName.localeCompare(b.tableName));
190
- setDeletedTables(deleted);
191
- } catch (error) {
192
- console.error("Error loading tables:", error);
193
- } finally {
194
- setLoading(false);
195
- }
196
- }, []);
197
-
198
- const handleDeleteTable = async () => {
199
- if (!deleteTarget) return;
200
- const api = getDataExplorerApi();
201
- if (!api) return;
202
-
203
- try {
204
- await api.deleteTable(deleteTarget);
205
- setDeleteTarget(null);
206
- setLoading(true);
207
- await loadTables();
208
- } catch (error: unknown) {
209
- console.error("Error deleting table:", error);
210
- alert(`Error deleting table: ${error instanceof Error ? error.message : String(error)}`);
211
- }
212
- };
213
-
214
- const compactDatabase = async (beforeTimestamp?: number) => {
215
- try {
216
- setCompacting(true);
217
- const api = getDataExplorerApi();
218
- if (!api) {
219
- alert("Data Explorer API not available");
220
- return;
221
- }
222
-
223
- const isExtreme = beforeTimestamp !== undefined;
224
- if (isExtreme) {
225
- const confirmed = window.confirm(
226
- "Extreme Compaction will remove ALL change history. This cannot be undone. Continue?",
227
- );
228
- if (!confirmed) {
229
- setCompacting(false);
230
- return;
231
- }
232
- }
233
-
234
- await api.compactDatabase(beforeTimestamp);
235
- alert(`Database compacted successfully!${isExtreme ? " (Extreme mode)" : ""}`);
236
-
237
- setLoading(true);
238
- await loadTables();
239
- } catch (error: unknown) {
240
- console.error("Error compacting database:", error);
241
- alert(`Error compacting database: ${error instanceof Error ? error.message : String(error)}`);
242
- } finally {
243
- setCompacting(false);
244
- }
245
- };
246
-
247
- const resetChangeTracking = async () => {
248
- try {
249
- setCompacting(true);
250
- const api = getDataExplorerApi();
251
- if (!api) {
252
- alert("Data Explorer API not available");
253
- return;
254
- }
255
-
256
- const confirmed = window.confirm(
257
- "Reset Change Tracking will clear all change history and rebuild it from scratch. This may take a while. Continue?",
258
- );
259
- if (!confirmed) {
260
- setCompacting(false);
261
- return;
262
- }
263
-
264
- await api.resetChangeTracking();
265
- alert("Change tracking reset successfully!");
266
-
267
- setLoading(true);
268
- await loadTables();
269
- } catch (error: unknown) {
270
- console.error("Error resetting change tracking:", error);
271
- alert(
272
- `Error resetting change tracking: ${error instanceof Error ? error.message : String(error)}`,
273
- );
274
- } finally {
275
- setCompacting(false);
276
- }
277
- };
278
-
279
- useEffect(() => {
280
- loadTables();
281
- }, [loadTables]);
282
-
283
- if (loading) {
284
- return <LoadingIndicator />;
285
- }
286
-
287
- if (!isDesktop()) {
288
- return (
289
- <div className="container-fluid p-4">
290
- <div className="alert alert-info">
291
- Data Explorer is only available in the desktop application.
292
- </div>
293
- </div>
294
- );
295
- }
296
-
297
- if (!currentContext && tables.length === 0) {
298
- return (
299
- <div className="container-fluid p-4">
300
- <div className="alert alert-warning">Unable to load database information.</div>
301
- </div>
302
- );
303
- }
304
-
305
- const registeredTables = tables.filter((t) => t.isRegistered);
306
- const unregisteredTables = tables.filter((t) => !t.isRegistered);
307
-
308
- return (
309
- <div className="container-fluid p-4">
310
- {deleteTarget && (
311
- <DeleteConfirmModal
312
- tableName={deleteTarget}
313
- onConfirm={handleDeleteTable}
314
- onCancel={() => setDeleteTarget(null)}
315
- />
316
- )}
317
-
318
- {/* Navigation Tabs */}
319
- <ul className="nav nav-tabs mb-4">
320
- <li className="nav-item">
321
- <a className="nav-link active" href="#/data-explorer">
322
- <i className="bi bi-table"></i> Tables
323
- </a>
324
- </li>
325
- <li className="nav-item">
326
- <a className="nav-link" href="#/data-explorer/query">
327
- <i className="bi bi-terminal"></i> Query
328
- </a>
329
- </li>
330
- </ul>
331
-
332
- <div className="d-flex justify-content-between align-items-center mb-4">
333
- <h2>Data Explorer</h2>
334
- <div className="d-flex gap-2">
335
- {/* Split button for Compact Database */}
336
- <div className="btn-group" role="group">
337
- <button
338
- type="button"
339
- className="btn btn-sm btn-warning"
340
- onClick={() => compactDatabase()}
341
- disabled={compacting || loading}
342
- title="Compact database (cleanup changes older than 2 weeks)"
343
- >
344
- {compacting ? (
345
- <>
346
- <span
347
- className="spinner-border spinner-border-sm me-1"
348
- role="status"
349
- aria-hidden="true"
350
- ></span>
351
- Compacting...
352
- </>
353
- ) : (
354
- <>
355
- <i className="bi bi-disc"></i> Compact Database
356
- </>
357
- )}
358
- </button>
359
- <button
360
- type="button"
361
- className="btn btn-sm btn-warning dropdown-toggle dropdown-toggle-split"
362
- data-bs-toggle="dropdown"
363
- aria-expanded="false"
364
- disabled={compacting || loading}
365
- title="More compaction options"
366
- >
367
- <span className="visually-hidden">Toggle Dropdown</span>
368
- </button>
369
- <ul className="dropdown-menu">
370
- <li>
371
- <a
372
- className="dropdown-item"
373
- href="#"
374
- onClick={(e) => {
375
- e.preventDefault();
376
- compactDatabase(Date.now());
377
- }}
378
- >
379
- <i className="bi bi-exclamation-triangle text-danger me-2"></i>
380
- Extreme Compaction
381
- <div className="small text-muted">Remove ALL change history</div>
382
- </a>
383
- </li>
384
- <li>
385
- <hr className="dropdown-divider" />
386
- </li>
387
- <li>
388
- <a
389
- className="dropdown-item"
390
- href="#"
391
- onClick={(e) => {
392
- e.preventDefault();
393
- resetChangeTracking();
394
- }}
395
- >
396
- <i className="bi bi-arrow-clockwise text-warning me-2"></i>
397
- Reset Change Tracking
398
- <div className="small text-muted">Clear and rebuild all change history</div>
399
- </a>
400
- </li>
401
- </ul>
402
- </div>
403
-
404
- <button
405
- className="btn btn-sm btn-primary"
406
- onClick={() => {
407
- setLoading(true);
408
- loadTables();
409
- }}
410
- disabled={compacting}
411
- >
412
- <i className="bi bi-arrow-clockwise"></i> Refresh
413
- </button>
414
- </div>
415
- </div>
416
-
417
- {/* Current Context Info */}
418
- <div className="card mb-4">
419
- <div className="card-body">
420
- <div className="d-flex justify-content-between align-items-center">
421
- <div>
422
- <h5 className="card-title mb-2">Current Data Context</h5>
423
- <p className="mb-0">{currentContext}</p>
424
- </div>
425
- <div className="text-end">
426
- <div className="text-muted small">Total DB Size</div>
427
- <div className="fs-4 fw-bold">
428
- {formatBytes(tables.reduce((sum, t) => sum + (t.bytes || 0), 0))}
429
- </div>
430
- </div>
431
- </div>
432
- </div>
433
- </div>
434
-
435
- {/* Registered Tables */}
436
- <div className="card mb-4">
437
- <div className="card-body">
438
- <h5 className="card-title">
439
- Registered Tables ({registeredTables.length})
440
- <span className="badge bg-success ms-2">Active</span>
441
- </h5>
442
- <p className="text-muted small">
443
- These tables are registered with the TableContainer and actively used by the
444
- application.
445
- </p>
446
- {registeredTables.length === 0 ? (
447
- <p className="text-muted">No registered tables found</p>
448
- ) : (
449
- <div className="table-responsive">
450
- <table className="table table-hover table-sm">
451
- <thead>
452
- <tr>
453
- <th>Table Name</th>
454
- <th>Table ID</th>
455
- <th className="text-end">Row Count</th>
456
- <th className="text-end">Bytes</th>
457
- <th style={{ width: "1%" }}></th>
458
- </tr>
459
- </thead>
460
- <tbody>
461
- {registeredTables.map((table) => (
462
- <tr key={table.tableName}>
463
- <td>
464
- <strong>{table.tableName}</strong>
465
- </td>
466
- <td>
467
- <code className="text-muted small">{table.tableId || "system"}</code>
468
- </td>
469
- <td className="text-end">
470
- {table.rowCount !== undefined ? table.rowCount.toLocaleString() : "-"}
471
- </td>
472
- <td className={`text-end fw-bold ${getBytesColorClass(table.bytes)}`}>
473
- {formatBytes(table.bytes)}
474
- </td>
475
- <td>
476
- <button
477
- type="button"
478
- className="btn btn-sm btn-outline-danger border-0"
479
- title={`Delete ${table.tableName}`}
480
- onClick={() => setDeleteTarget(table.tableName)}
481
- >
482
- <i className="bi bi-trash" />
483
- </button>
484
- </td>
485
- </tr>
486
- ))}
487
- </tbody>
488
- </table>
489
- </div>
490
- )}
491
- </div>
492
- </div>
493
-
494
- {/* Unregistered Tables (Raw SQLite) */}
495
- {unregisteredTables.length > 0 && (
496
- <div className="card mb-4">
497
- <div className="card-body">
498
- <h5 className="card-title">
499
- Unregistered Tables ({unregisteredTables.length})
500
- <span className="badge bg-warning text-dark ms-2">Raw SQLite</span>
501
- </h5>
502
- <p className="text-muted small">
503
- These tables exist in the SQLite database but are not registered with the
504
- TableContainer. They may be system tables, change tracking tables, or legacy tables.
505
- </p>
506
- <div className="table-responsive">
507
- <table className="table table-hover table-sm">
508
- <thead>
509
- <tr>
510
- <th>Table Name</th>
511
- <th>Type</th>
512
- <th className="text-end">Row Count</th>
513
- <th className="text-end">Bytes</th>
514
- <th>SQL Definition</th>
515
- <th style={{ width: "1%" }}></th>
516
- </tr>
517
- </thead>
518
- <tbody>
519
- {unregisteredTables.map((table) => (
520
- <tr key={table.tableName}>
521
- <td>
522
- <strong>{table.tableName}</strong>
523
- </td>
524
- <td>
525
- <span className="badge bg-secondary">{table.type || "table"}</span>
526
- </td>
527
- <td className="text-end">
528
- {table.rowCount !== undefined ? table.rowCount.toLocaleString() : "-"}
529
- </td>
530
- <td className={`text-end fw-bold ${getBytesColorClass(table.bytes)}`}>
531
- {formatBytes(table.bytes)}
532
- </td>
533
- <td>
534
- {table.sql ? (
535
- <details>
536
- <summary
537
- className="cursor-pointer text-primary"
538
- style={{ cursor: "pointer" }}
539
- >
540
- <small>View SQL</small>
541
- </summary>
542
- <pre
543
- className="mt-2 p-2 bg-body-secondary border rounded"
544
- style={{
545
- fontSize: "0.75rem",
546
- maxHeight: "300px",
547
- overflow: "auto",
548
- }}
549
- >
550
- <code className="text-body">{table.sql}</code>
551
- </pre>
552
- </details>
553
- ) : (
554
- <span className="text-muted small">-</span>
555
- )}
556
- </td>
557
- <td>
558
- <button
559
- type="button"
560
- className="btn btn-sm btn-outline-danger border-0"
561
- title={`Delete ${table.tableName}`}
562
- onClick={() => setDeleteTarget(table.tableName)}
563
- >
564
- <i className="bi bi-trash" />
565
- </button>
566
- </td>
567
- </tr>
568
- ))}
569
- </tbody>
570
- </table>
571
- </div>
572
- </div>
573
- </div>
574
- )}
575
-
576
- {/* Deleted Tables */}
577
- {deletedTables.length > 0 && (
578
- <div className="card mb-4">
579
- <div className="card-body">
580
- <h5 className="card-title">
581
- Deleted Tables ({deletedTables.length})
582
- <span className="badge bg-danger ms-2">Deleted</span>
583
- </h5>
584
- <p className="text-muted small">
585
- These tables have been deleted. Their definitions are retained so other devices know
586
- to stop syncing data for them.
587
- </p>
588
- <div className="table-responsive">
589
- <table className="table table-hover table-sm">
590
- <thead>
591
- <tr>
592
- <th>Table Name</th>
593
- <th>Table ID</th>
594
- <th>Deleted At</th>
595
- </tr>
596
- </thead>
597
- <tbody>
598
- {deletedTables.map((table) => (
599
- <tr key={table.tableId}>
600
- <td>
601
- <strong className="text-muted">{table.tableName}</strong>
602
- </td>
603
- <td>
604
- <code className="text-muted small">{table.tableId}</code>
605
- </td>
606
- <td>
607
- <span title={new Date(table.deletedAt).toLocaleString()}>
608
- {formatRelativeTime(table.deletedAt)}
609
- </span>
610
- </td>
611
- </tr>
612
- ))}
613
- </tbody>
614
- </table>
615
- </div>
616
- </div>
617
- </div>
618
- )}
619
- </div>
620
- );
621
- }
622
-
623
- registerInternalPeersUI({
624
- peersUIId: "data-explorer-list-ui",
625
- component: DataExplorerList,
626
- routes: [
627
- {
628
- isMatch: (_props, context) => context.path === "data-explorer",
629
- uiCategory: "screen",
630
- priority: 2,
631
- },
632
- ],
633
- });
@@ -1,6 +0,0 @@
1
- // Import all data explorer screen components to ensure they register their routes
2
- import "./data-explorer";
3
- import "./query-executor";
4
-
5
- export * from "./data-explorer";
6
- export * from "./query-executor";