@nextclaw/ui 0.16.0 → 0.17.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 (69) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/assets/api-CVjdSvJk.js +13 -0
  3. package/dist/assets/{appearance-settings-page-CfwDf9ag.js → appearance-settings-page-BOorfaUx.js} +1 -1
  4. package/dist/assets/{channels-list-page-Dyn83ZlS.js → channels-list-page-DuZJvYB6.js} +1 -1
  5. package/dist/assets/{chat-page-CL0IMvgF.js → chat-page-8PTMgI0t.js} +1 -1
  6. package/dist/assets/{config-split-page-D4D4HFhq.js → config-split-page-UuhsVcQD.js} +1 -1
  7. package/dist/assets/{confirm-dialog-Cv6-9Nnj.js → confirm-dialog-Bnosa8UF.js} +1 -1
  8. package/dist/assets/{desktop-update-config-Bckgulvm.js → desktop-update-config-CM4lsX4R.js} +1 -1
  9. package/dist/assets/{dist-BrRgjiq1.js → dist-D17RZAsz.js} +1 -1
  10. package/dist/assets/{dist-Bh_tj3FN.js → dist-_zZ8P38T.js} +1 -1
  11. package/dist/assets/{doc-browser-BlWjhmnM.js → doc-browser-CiLvybSC.js} +1 -1
  12. package/dist/assets/{doc-browser-context-NGYa66Xg.js → doc-browser-context-CerkiK_N.js} +1 -1
  13. package/dist/assets/doc-browser-z7vdH3Ez.js +1 -0
  14. package/dist/assets/{form-actions-CeKgh4SQ.js → form-actions-Cmv23dN4.js} +1 -1
  15. package/dist/assets/index-CWdgBpSc.css +1 -0
  16. package/dist/assets/index-DlL8uKXu.js +109 -0
  17. package/dist/assets/loader-circle-vUsFtTfb.js +1 -0
  18. package/dist/assets/mcp-marketplace-page-BV8WB3_L.js +1 -0
  19. package/dist/assets/{mcp-marketplace-page-DfNmMqKs.js → mcp-marketplace-page-DN_fqcLd.js} +1 -1
  20. package/dist/assets/{model-config-page-DHzyDV5v.js → model-config-page-BxaeCMbJ.js} +1 -1
  21. package/dist/assets/{navigation-link-CzGgQGi_.js → navigation-link-k9rsmtC4.js} +1 -1
  22. package/dist/assets/plus-Dc760kHj.js +1 -0
  23. package/dist/assets/{provider-scoped-model-input-CjrHwzFb.js → provider-scoped-model-input-DLSAB6a5.js} +1 -1
  24. package/dist/assets/{providers-config-page-ZPvJWHFN.js → providers-config-page-DM5N0aeS.js} +1 -1
  25. package/dist/assets/{react-BXRf96P-.js → react-BgRLh3ee.js} +1 -1
  26. package/dist/assets/{refresh-cw-ChKuqgPR.js → refresh-cw-axvJLmRG.js} +1 -1
  27. package/dist/assets/remote-Cj1GBMaN.js +1 -0
  28. package/dist/assets/rotate-cw-CFByP2O8.js +1 -0
  29. package/dist/assets/{runtime-config-page-CGpPQD8K.js → runtime-config-page-WNzZyjMW.js} +1 -1
  30. package/dist/assets/{save-BWGNAKV5.js → save-DbR4SGk8.js} +1 -1
  31. package/dist/assets/{search-DFcT_9wJ.js → search-M9lrb8id.js} +1 -1
  32. package/dist/assets/{search-config-page-DBBzVAQZ.js → search-config-page-DmsID8FQ.js} +1 -1
  33. package/dist/assets/{secrets-config-page-bnJ8sIB7.js → secrets-config-page-C10OwI0b.js} +1 -1
  34. package/dist/assets/security-config-CvU5JxDT.js +1 -0
  35. package/dist/assets/{select-BnNrv8si.js → select-D_YBzMdv.js} +1 -1
  36. package/dist/assets/{settings-2-CFHrgKTX.js → settings-2-zy40UwTo.js} +1 -1
  37. package/dist/assets/skeleton-BmAtzjDM.js +1 -0
  38. package/dist/assets/{tag-chip-L5w4xfS7.js → tag-chip-D7QRdcph.js} +1 -1
  39. package/dist/assets/x-D9Y9hf_r.js +1 -0
  40. package/dist/index.html +19 -19
  41. package/package.json +6 -6
  42. package/src/features/app-data/components/app-data-removal-choice.tsx +43 -0
  43. package/src/features/app-data/components/app-retained-data-section.tsx +179 -0
  44. package/src/features/app-data/components/app-storage-usage.tsx +59 -0
  45. package/src/features/app-data/hooks/use-app-data.ts +26 -0
  46. package/src/features/app-data/index.ts +8 -0
  47. package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +72 -1
  48. package/src/features/apps/components/app-package-card.tsx +42 -51
  49. package/src/features/apps/components/app-packages-panel.tsx +19 -2
  50. package/src/features/apps/hooks/use-app-packages.ts +2 -0
  51. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +59 -2
  52. package/src/features/service-apps/components/service-app-delete-dialog.tsx +122 -0
  53. package/src/features/service-apps/components/service-app-list-item.tsx +24 -9
  54. package/src/features/service-apps/components/service-apps-panel.tsx +15 -1
  55. package/src/features/service-apps/hooks/use-service-apps.ts +4 -1
  56. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +23 -1
  57. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +23 -1
  58. package/dist/assets/api-Dket1cmq.js +0 -13
  59. package/dist/assets/doc-browser-Da9hDsoQ.js +0 -1
  60. package/dist/assets/index-Bz5yNMXA.js +0 -109
  61. package/dist/assets/index-DSLK7zgR.css +0 -1
  62. package/dist/assets/loader-circle-DLp2jNIf.js +0 -1
  63. package/dist/assets/mcp-marketplace-page-CIWbjXM8.js +0 -1
  64. package/dist/assets/plus-Dfj3tJ_m.js +0 -1
  65. package/dist/assets/remote-C2enAZbs.js +0 -1
  66. package/dist/assets/rotate-cw-BGkZpcc7.js +0 -1
  67. package/dist/assets/security-config-CfbXSpgX.js +0 -1
  68. package/dist/assets/skeleton-tfWhGuJT.js +0 -1
  69. package/dist/assets/x-BCSE3LCQ.js +0 -1
@@ -2,6 +2,7 @@ import { useState } from "react";
2
2
  import type {
3
3
  ServiceActionGrantView,
4
4
  ServiceActionListView,
5
+ AppDataEntry,
5
6
  ServiceAppRecordView,
6
7
  } from "@nextclaw/client-sdk";
7
8
  import {
@@ -20,7 +21,7 @@ import {
20
21
  type LucideIcon,
21
22
  Wrench,
22
23
  } from "lucide-react";
23
- import { ConfirmDialog } from "@/shared/components/ui/confirm-dialog";
24
+ import { ServiceAppDeleteDialog } from "@/features/service-apps/components/service-app-delete-dialog";
24
25
  import {
25
26
  Popover,
26
27
  PopoverContent,
@@ -44,10 +45,14 @@ export function ServiceAppListItem({
44
45
  actionsOpen,
45
46
  grants,
46
47
  deletePending,
48
+ deleteError,
49
+ dataEntry,
50
+ dataLoading,
47
51
  isDiscovering,
48
52
  onActionsOpenChange,
49
53
  onDiscover,
50
54
  onDelete,
55
+ onResetDelete,
51
56
  onRestart,
52
57
  onRevoke,
53
58
  }: {
@@ -56,16 +61,21 @@ export function ServiceAppListItem({
56
61
  actionsOpen: boolean;
57
62
  grants: ServiceActionGrantView[];
58
63
  deletePending: boolean;
64
+ deleteError: unknown;
65
+ dataEntry?: AppDataEntry;
66
+ dataLoading: boolean;
59
67
  isDiscovering: boolean;
60
68
  onActionsOpenChange: (open: boolean) => void;
61
69
  onDiscover: (appId: string) => void;
62
- onDelete: (appId: string) => void;
70
+ onDelete: (appId: string, purgeData: boolean, onSuccess: () => void) => void;
71
+ onResetDelete: () => void;
63
72
  onRestart: (appId: string) => void;
64
73
  onRevoke: (grant: ServiceActionGrantView) => void;
65
74
  }) {
66
75
  const [isMenuOpen, setIsMenuOpen] = useState(false);
67
76
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
68
77
  const [isDiagnosticsOpen, setIsDiagnosticsOpen] = useState(false);
78
+ const [purgeData, setPurgeData] = useState(false);
69
79
  const canConnectAndDiscover =
70
80
  app.status !== "starting" && app.status !== "stopped";
71
81
  const canDisconnectRuntime =
@@ -73,6 +83,8 @@ export function ServiceAppListItem({
73
83
  const diagnostics = getServiceAppDiagnostics(app);
74
84
  const openDeleteDialog = () => {
75
85
  setIsMenuOpen(false);
86
+ setPurgeData(false);
87
+ onResetDelete();
76
88
  setIsDeleteDialogOpen(true);
77
89
  };
78
90
 
@@ -233,15 +245,18 @@ export function ServiceAppListItem({
233
245
  ) : null}
234
246
  </div>
235
247
 
236
- <ConfirmDialog
248
+ <ServiceAppDeleteDialog
249
+ appId={app.id}
250
+ appTitle={app.title}
251
+ dataEntry={dataEntry}
252
+ dataLoading={dataLoading}
253
+ deleteError={deleteError}
254
+ deletePending={deletePending}
237
255
  open={isDeleteDialogOpen}
256
+ purgeData={purgeData}
257
+ onDelete={onDelete}
238
258
  onOpenChange={setIsDeleteDialogOpen}
239
- title={t("serviceAppsDeleteConfirmTitle")}
240
- description={`${t("serviceAppsDeleteConfirmDescription")} ${app.title}`}
241
- confirmLabel={t("delete")}
242
- variant="destructive"
243
- onConfirm={() => onDelete(app.id)}
244
- onCancel={() => undefined}
259
+ onPurgeDataChange={setPurgeData}
245
260
  />
246
261
  </section>
247
262
  </TooltipProvider>
@@ -2,9 +2,11 @@ import { useState } from "react";
2
2
  import type {
3
3
  ServiceActionGrantView,
4
4
  ServiceActionListView,
5
+ AppDataEntry,
5
6
  ServiceAppRecordView,
6
7
  } from "@nextclaw/client-sdk";
7
8
  import { RefreshCw, Server } from "lucide-react";
9
+ import { useAppData } from "@/features/app-data";
8
10
  import { ServiceAppListItem } from "@/features/service-apps/components/service-app-list-item";
9
11
  import {
10
12
  useDeleteServiceApp,
@@ -27,6 +29,7 @@ type ServiceActionView = ServiceActionListView["actions"][number];
27
29
 
28
30
  export function ServiceAppsPanel() {
29
31
  const serviceApps = useServiceApps();
32
+ const appData = useAppData();
30
33
  const serviceActions = useServiceActions();
31
34
  const serviceActionGrants = useServiceActionGrants();
32
35
  const deleteServiceApp = useDeleteServiceApp();
@@ -44,6 +47,7 @@ export function ServiceAppsPanel() {
44
47
  void serviceApps.refetch();
45
48
  void serviceActions.refetch();
46
49
  void serviceActionGrants.refetch();
50
+ void appData.refetch();
47
51
  };
48
52
 
49
53
  if (
@@ -85,6 +89,9 @@ export function ServiceAppsPanel() {
85
89
  setExpandedActionsByApp((current) => ({ ...current, [appId]: true }));
86
90
  });
87
91
  };
92
+ const workspaceDataEntries = (appData.data?.entries ?? [])
93
+ .filter((entry): entry is AppDataEntry =>
94
+ entry.source === "workspace-service" && entry.lifecycle === "active");
88
95
 
89
96
  return (
90
97
  <div className="flex h-full min-h-0 flex-col bg-card text-card-foreground">
@@ -136,6 +143,9 @@ export function ServiceAppsPanel() {
136
143
  actionsOpen={Boolean(expandedActionsByApp[app.id])}
137
144
  grants={grants}
138
145
  deletePending={deleteServiceApp.isPending}
146
+ deleteError={deleteServiceApp.error}
147
+ dataEntry={workspaceDataEntries.find((entry) => entry.appId === app.id)}
148
+ dataLoading={appData.isLoading}
139
149
  isDiscovering={discoverServiceAppActions.isPending}
140
150
  onActionsOpenChange={(open) =>
141
151
  setExpandedActionsByApp((current) => ({
@@ -144,7 +154,11 @@ export function ServiceAppsPanel() {
144
154
  }))
145
155
  }
146
156
  onDiscover={discover}
147
- onDelete={(appId) => void deleteServiceApp.mutate(appId)}
157
+ onDelete={(appId, purgeData, onSuccess) => void deleteServiceApp.mutate(
158
+ { appId, purgeData },
159
+ { onSuccess },
160
+ )}
161
+ onResetDelete={deleteServiceApp.reset}
148
162
  onRestart={(appId) => void restartServiceApp.mutate(appId)}
149
163
  onRevoke={(grant) =>
150
164
  void revokeServiceActionGrant.mutate({
@@ -4,6 +4,7 @@ import { nextclawClient } from '@/shared/lib/api';
4
4
  const SERVICE_APPS_QUERY_KEY = ['service-apps'] as const;
5
5
  const SERVICE_ACTIONS_QUERY_KEY = ['service-actions'] as const;
6
6
  const SERVICE_ACTION_GRANTS_QUERY_KEY = ['service-action-grants'] as const;
7
+ const APP_DATA_QUERY_KEY = ['app-data'] as const;
7
8
 
8
9
  export function useServiceApps() {
9
10
  return useQuery({
@@ -42,12 +43,14 @@ export function useRestartServiceApp() {
42
43
  export function useDeleteServiceApp() {
43
44
  const queryClient = useQueryClient();
44
45
  return useMutation({
45
- mutationFn: (appId: string) => nextclawClient.serviceApps.deleteServiceApp(appId),
46
+ mutationFn: (input: { appId: string; purgeData: boolean }) =>
47
+ nextclawClient.serviceApps.deleteServiceApp(input.appId, input.purgeData),
46
48
  onSuccess: async () => {
47
49
  await Promise.all([
48
50
  queryClient.invalidateQueries({ queryKey: SERVICE_APPS_QUERY_KEY }),
49
51
  queryClient.invalidateQueries({ queryKey: SERVICE_ACTIONS_QUERY_KEY }),
50
52
  queryClient.invalidateQueries({ queryKey: SERVICE_ACTION_GRANTS_QUERY_KEY }),
53
+ queryClient.invalidateQueries({ queryKey: APP_DATA_QUERY_KEY }),
51
54
  ]);
52
55
  },
53
56
  });
@@ -117,6 +117,25 @@
117
117
  "appPackagesRollbackCompleted": "App version switched",
118
118
  "appPackagesUninstallCompleted": "App uninstalled",
119
119
  "appPackagesNextClawRequirement": "Requires NextClaw",
120
+ "appDataRetainedTitle": "Saved app data",
121
+ "appDataRetainedDescription": "Data kept after an app was removed stays here until you reinstall the app or delete the data.",
122
+ "appDataLoadFailed": "Failed to load saved app data",
123
+ "appDataDiagnosticsTitle": "Some app data needs attention",
124
+ "appDataDeleteAction": "Delete data",
125
+ "appDataDeleteTitle": "Permanently delete this app data?",
126
+ "appDataDeleteDescription": "This removes the app's private data from this device. Files you exported or saved outside the app remain untouched.",
127
+ "appDataDeletePermanently": "Permanently delete data",
128
+ "appDataDeleting": "Deleting data…",
129
+ "appDataDeleteCompleted": "App data deleted",
130
+ "appDataDeleteFailed": "Failed to delete app data",
131
+ "appDataStorageTotal": "Total app data",
132
+ "appDataStoragePath": "Managed instance path",
133
+ "appDataClassData": "Personal data",
134
+ "appDataClassConfig": "Settings",
135
+ "appDataClassState": "State",
136
+ "appDataClassCache": "Cache",
137
+ "appDataClassTemporary": "Temporary",
138
+ "appDataClassLogs": "Logs",
120
139
  "panelAppsTitle": "Panel Apps",
121
140
  "panelAppsLoading": "Loading panel apps...",
122
141
  "panelAppsLoadFailed": "Failed to load panel apps",
@@ -164,7 +183,10 @@
164
183
  "serviceAppsMoreActions": "More actions",
165
184
  "serviceAppsDelete": "Delete service app",
166
185
  "serviceAppsDeleteConfirmTitle": "Delete service app?",
167
- "serviceAppsDeleteConfirmDescription": "This will delete the service app directory and cannot be undone.",
186
+ "serviceAppsDeleteConfirmDescription": "The service source will be deleted. Its private data is kept by default.",
187
+ "serviceAppsKeepDataDescription": "Delete the service source but keep its private data for a future copy of the same service.",
188
+ "serviceAppsDeleteDataDescription": "Permanently delete the service source and its managed private data.",
189
+ "serviceAppsDataUnavailable": "Storage details are unavailable. Keep data selected or refresh before deleting.",
168
190
  "serviceAppsStatus_idle": "Not connected",
169
191
  "serviceAppsStatus_starting": "Connecting",
170
192
  "serviceAppsStatus_running": "Connected",
@@ -117,6 +117,25 @@
117
117
  "appPackagesRollbackCompleted": "应用版本已切换",
118
118
  "appPackagesUninstallCompleted": "应用已卸载",
119
119
  "appPackagesNextClawRequirement": "需要 NextClaw",
120
+ "appDataRetainedTitle": "已保留的应用数据",
121
+ "appDataRetainedDescription": "卸载应用时保留的数据会留在这里。重新安装可以继续使用,也可以单独永久删除。",
122
+ "appDataLoadFailed": "已保留的应用数据加载失败",
123
+ "appDataDiagnosticsTitle": "部分应用数据需要处理",
124
+ "appDataDeleteAction": "删除数据",
125
+ "appDataDeleteTitle": "永久删除这些应用数据?",
126
+ "appDataDeleteDescription": "这会从本机移除该应用的私有数据。已导出或保存在应用目录之外的文件不会被删除。",
127
+ "appDataDeletePermanently": "永久删除数据",
128
+ "appDataDeleting": "正在删除数据…",
129
+ "appDataDeleteCompleted": "应用数据已删除",
130
+ "appDataDeleteFailed": "应用数据删除失败",
131
+ "appDataStorageTotal": "应用数据总量",
132
+ "appDataStoragePath": "受管实例路径",
133
+ "appDataClassData": "个人数据",
134
+ "appDataClassConfig": "设置",
135
+ "appDataClassState": "状态",
136
+ "appDataClassCache": "缓存",
137
+ "appDataClassTemporary": "临时文件",
138
+ "appDataClassLogs": "日志",
120
139
  "panelAppsTitle": "面板应用",
121
140
  "panelAppsLoading": "加载面板应用中...",
122
141
  "panelAppsLoadFailed": "面板应用加载失败",
@@ -164,7 +183,10 @@
164
183
  "serviceAppsMoreActions": "更多操作",
165
184
  "serviceAppsDelete": "删除服务应用",
166
185
  "serviceAppsDeleteConfirmTitle": "删除服务应用?",
167
- "serviceAppsDeleteConfirmDescription": "这会删除服务应用目录,且无法撤销。",
186
+ "serviceAppsDeleteConfirmDescription": "服务源码会被删除,私有数据默认保留。",
187
+ "serviceAppsKeepDataDescription": "删除服务源码,但保留私有数据,之后放回同一服务仍可继续使用。",
188
+ "serviceAppsDeleteDataDescription": "永久删除服务源码及其受管私有数据。",
189
+ "serviceAppsDataUnavailable": "暂时无法读取存储详情。请保留数据,或刷新后再删除。",
168
190
  "serviceAppsStatus_idle": "未连接",
169
191
  "serviceAppsStatus_starting": "连接中",
170
192
  "serviceAppsStatus_running": "已连接",