dsh-remote-bridge 2.5.2 → 2.6.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.
package/lib/client.cjs CHANGED
@@ -149,9 +149,33 @@ window.__ModuleLoader__.load({
149
149
  })
150
150
  });
151
151
  }
152
+ /**
153
+ * 只改名,不动权限。
154
+ *
155
+ * 走同一个 PATCH 但只带 `name` —— 服务端见到没有 scopes/rootIds 就按「纯改名」
156
+ * 处理。分成两个调用点(而不是把 name 塞进 `updateDevice`)是因为它们是两件
157
+ * 不同的事:改名不需要先想清楚权限,也不该因为权限校验失败而失败。
158
+ */
159
+ async renameDevice(deviceId, name) {
160
+ await this.manageJson(`/devices/${encodeURIComponent(deviceId)}`, {
161
+ method: "PATCH",
162
+ body: JSON.stringify({ name })
163
+ });
164
+ }
152
165
  async revokeDevice(deviceId) {
153
166
  await this.manageJson(`/devices/${encodeURIComponent(deviceId)}`, { method: "DELETE" });
154
167
  }
168
+ /**
169
+ * 一键清理「N 天没动过」的设备。天数由用户填,服务端再夹一次 1..3650。
170
+ *
171
+ * 返回真正删掉的条数 —— 0 也是一次合法结果(「没有可清理的」),界面不该把它当失败。
172
+ */
173
+ async pruneInactiveDevices(olderThanDays) {
174
+ return this.manageJson("/devices/prune", {
175
+ method: "POST",
176
+ body: JSON.stringify({ olderThanDays })
177
+ });
178
+ }
155
179
  async trashItems() {
156
180
  return this.json("/trash");
157
181
  }
@@ -22831,7 +22855,7 @@ window.__ModuleLoader__.load({
22831
22855
  key: "1o3tu8"
22832
22856
  }]
22833
22857
  ]);
22834
- const ScrollText = createLucideIcon("ScrollText", [
22858
+ createLucideIcon("ScrollText", [
22835
22859
  ["path", {
22836
22860
  d: "M15 12h-5",
22837
22861
  key: "r7krc0"
@@ -29780,7 +29804,6 @@ window.__ModuleLoader__.load({
29780
29804
  exports.HardDrive = HardDrive;
29781
29805
  exports.Image = Image;
29782
29806
  exports.Languages = Languages;
29783
- exports.ScrollText = ScrollText;
29784
29807
  exports.Smartphone = Smartphone;
29785
29808
  exports.Trash2 = Trash2;
29786
29809
  exports.Upload = Upload;
@@ -29984,6 +30007,12 @@ window.__ModuleLoader__.load({
29984
30007
  pairingCreated: "配对码已生成",
29985
30008
  configCreated: "配置文本已生成",
29986
30009
  revokeConfirm: "吊销后这台手机的令牌立即失效,必须重新配对才能访问。确定吊销「{name}」吗?",
30010
+ pruneInactiveDays: "清理超过(天)未使用",
30011
+ pruneInactiveAction: "清理 {days} 天未使用设备",
30012
+ pruneInactiveBusy: "正在清理…",
30013
+ pruneInactiveConfirm: "将删除 {days} 天没有使用过的设备(它们需要重新配对才能访问)。最近用过的设备不受影响。继续吗?",
30014
+ pruneInactiveDone: "已清理 {count} 台设备",
30015
+ pruneInactiveNone: "没有需要清理的设备",
29987
30016
  removeRootConfirm: "移除根目录「{label}」不会删除磁盘上的文件,但所有手机将立刻失去对它的访问权。确定移除吗?",
29988
30017
  disableRemoteConfirm: "关闭远程访问后,所有手机连接立即断开,需要重新启用并配对。确定关闭吗?",
29989
30018
  rootAdded: "根目录已添加",
@@ -30001,6 +30030,11 @@ window.__ModuleLoader__.load({
30001
30030
  trashEmpty: "回收站是空的",
30002
30031
  deviceLastSeen: "最后使用 {time}",
30003
30032
  deviceNeverSeen: "从未连接",
30033
+ deviceRename: "改名",
30034
+ deviceRenamePlaceholder: "给这台设备起个名字",
30035
+ deviceRenameHint: "手动改过的名字不会被自动覆盖",
30036
+ deviceNameSaved: "设备名已保存",
30037
+ deviceDetectedName: "自动识别",
30004
30038
  imageLoadFailed: "图片加载失败",
30005
30039
  prevImage: "上一张",
30006
30040
  nextImage: "下一张",
@@ -30204,6 +30238,12 @@ window.__ModuleLoader__.load({
30204
30238
  pairingCreated: "Pairing code generated",
30205
30239
  configCreated: "Config text generated",
30206
30240
  revokeConfirm: "Revoking invalidates this phone’s token at once; it must pair again to regain access. Revoke “{name}”?",
30241
+ pruneInactiveDays: "Unused for more than (days)",
30242
+ pruneInactiveAction: "Prune devices unused for {days} days",
30243
+ pruneInactiveBusy: "Pruning…",
30244
+ pruneInactiveConfirm: "This deletes devices unused for {days} days (they must pair again to regain access). Recently used devices are untouched. Continue?",
30245
+ pruneInactiveDone: "Pruned {count} device(s)",
30246
+ pruneInactiveNone: "No devices to prune",
30207
30247
  removeRootConfirm: "Removing “{label}” does not delete files on disk, but every phone immediately loses access to it. Remove it?",
30208
30248
  disableRemoteConfirm: "Disabling remote access drops every phone connection right away; it must be re-enabled and re-paired. Disable it?",
30209
30249
  rootAdded: "Root added",
@@ -30221,6 +30261,11 @@ window.__ModuleLoader__.load({
30221
30261
  trashEmpty: "The recycle bin is empty",
30222
30262
  deviceLastSeen: "Last seen {time}",
30223
30263
  deviceNeverSeen: "Never connected",
30264
+ deviceRename: "Rename",
30265
+ deviceRenamePlaceholder: "Name this device",
30266
+ deviceRenameHint: "A name you set is never overwritten automatically",
30267
+ deviceNameSaved: "Device name saved",
30268
+ deviceDetectedName: "Detected",
30224
30269
  imageLoadFailed: "Image failed to load",
30225
30270
  prevImage: "Previous image",
30226
30271
  nextImage: "Next image",
@@ -30867,6 +30912,23 @@ window.__ModuleLoader__.load({
30867
30912
  "settings.read",
30868
30913
  "settings.write"
30869
30914
  ];
30915
+ /**
30916
+ * 授予新设备时的默认权限(**五个非破坏性权限**)。
30917
+ *
30918
+ * 刻意不含 `files.delete` 与 `settings.write`:这两个是破坏性权限,应当是用户显式
30919
+ * 要求才授予。`settings.write` 尤其危险 —— 拿到它就能改供应商 `baseURL`,把模型
30920
+ * 请求连同真实凭据引到任意地址(SEC-H11),所以它绝不能是默认值。
30921
+ *
30922
+ * 三条路径必须共用这一份,否则「同一个产品里三处默认权限不一样」这种缺陷会反复
30923
+ * 复发:服务端生成配置文本时的缺省、Web UI 配对码面板的初始勾选、隧道一键路径。
30924
+ */
30925
+ const DEFAULT_DEVICE_SCOPES = [
30926
+ "chat.read",
30927
+ "chat.write",
30928
+ "files.read",
30929
+ "files.write",
30930
+ "settings.read"
30931
+ ];
30870
30932
  new Set(DEVICE_SCOPES);
30871
30933
  //#endregion
30872
30934
  //#region src/client/app-qr.ts
@@ -30944,7 +31006,6 @@ window.__ModuleLoader__.load({
30944
31006
  devices: "devicesTabDesc",
30945
31007
  image: "imageTabDesc",
30946
31008
  trash: "trashTabDesc",
30947
- audit: "auditTabDesc",
30948
31009
  "app-download": "appDownloadTabDesc"
30949
31010
  };
30950
31011
  function tabDescKey(tab) {
@@ -31050,7 +31111,6 @@ window.__ModuleLoader__.load({
31050
31111
  const { locale, t } = useWorkspaceI18n();
31051
31112
  const [status, setStatus] = (0, react.useState)();
31052
31113
  const [trash, setTrash] = (0, react.useState)([]);
31053
- const [audit, setAudit] = (0, react.useState)([]);
31054
31114
  const [path, setPath] = (0, react.useState)("");
31055
31115
  const [label, setLabel] = (0, react.useState)("");
31056
31116
  const [listenerHost, setListenerHost] = (0, react.useState)("0.0.0.0");
@@ -31069,8 +31129,8 @@ window.__ModuleLoader__.load({
31069
31129
  const [tunnel, setTunnel] = (0, react.useState)();
31070
31130
  const [tunnelBusy, setTunnelBusy] = (0, react.useState)(false);
31071
31131
  const [activity, setActivity] = (0, react.useState)();
31072
- const [auditLimit, setAuditLimit] = (0, react.useState)(50);
31073
- const [auditLoading, setAuditLoading] = (0, react.useState)(false);
31132
+ const [pruneDays, setPruneDays] = (0, react.useState)(30);
31133
+ const [pruneBusy, setPruneBusy] = (0, react.useState)(false);
31074
31134
  const [now, setNow] = (0, react.useState)(() => Date.now());
31075
31135
  const notify = (0, react.useCallback)((key, params) => {
31076
31136
  setNotice(params === void 0 ? {
@@ -31127,7 +31187,6 @@ window.__ModuleLoader__.load({
31127
31187
  const next = await props.api.status();
31128
31188
  setStatus(next);
31129
31189
  if (openCards.has("trash")) setTrash((await props.api.trashItems()).items);
31130
- if (openCards.has("audit")) setAudit((await props.api.audit()).items);
31131
31190
  if (openCards.has("image")) {
31132
31191
  const settings = await props.api.imageSettings();
31133
31192
  setImage(settings);
@@ -31295,7 +31354,7 @@ window.__ModuleLoader__.load({
31295
31354
  }, [status?.configuredHost, status?.configuredPort]);
31296
31355
  const roots = status?.roots ?? [];
31297
31356
  const managementLocked = tunnel?.running === true;
31298
- const [grantedScopes, setGrantedScopes] = (0, react.useState)([...DEVICE_SCOPES]);
31357
+ const [grantedScopes, setGrantedScopes] = (0, react.useState)([...DEFAULT_DEVICE_SCOPES]);
31299
31358
  const toggleScope = (0, react.useCallback)((scope) => {
31300
31359
  setGrantedScopes((current) => current.includes(scope) ? current.filter((item) => item !== scope) : [...current, scope]);
31301
31360
  }, []);
@@ -31707,13 +31766,41 @@ window.__ModuleLoader__.load({
31707
31766
  configText !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigTextPanel, { result: configText })
31708
31767
  ]
31709
31768
  }, "remote"),
31710
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsCard, {
31769
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SettingsCard, {
31711
31770
  tab: "devices",
31712
31771
  nameKey: tabLabelKey("devices"),
31713
31772
  descKey: tabDescKey("devices"),
31714
31773
  open: isOpen("devices"),
31715
31774
  onToggle: () => toggleCard("devices"),
31716
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31775
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
31776
+ className: "daw-inline-command",
31777
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
31778
+ className: "daw-field",
31779
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("pruneInactiveDays") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
31780
+ className: "daw-input",
31781
+ type: "number",
31782
+ min: 1,
31783
+ max: 3650,
31784
+ value: pruneDays,
31785
+ disabled: managementLocked || pruneBusy,
31786
+ onChange: (event) => setPruneDays(Math.max(1, Math.min(3650, Number(event.target.value) || 1)))
31787
+ })]
31788
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
31789
+ className: "daw-command",
31790
+ disabled: managementLocked || pruneBusy,
31791
+ onClick: () => {
31792
+ if (!confirm(t("pruneInactiveConfirm", { days: String(pruneDays) }))) return;
31793
+ setPruneBusy(true);
31794
+ setError(void 0);
31795
+ props.api.pruneInactiveDevices(pruneDays).then((result) => {
31796
+ if (result.pruned === 0) notify("pruneInactiveNone");
31797
+ else notify("pruneInactiveDone", { count: String(result.pruned) });
31798
+ return refresh();
31799
+ }).catch(setError).finally(() => setPruneBusy(false));
31800
+ },
31801
+ children: pruneBusy ? t("pruneInactiveBusy") : t("pruneInactiveAction", { days: String(pruneDays) })
31802
+ })]
31803
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31717
31804
  className: "daw-list",
31718
31805
  children: (status?.devices ?? []).map((device) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceRow, {
31719
31806
  api: props.api,
@@ -31723,7 +31810,7 @@ window.__ModuleLoader__.load({
31723
31810
  onError: setError,
31724
31811
  onNotice: notify
31725
31812
  }, device.id))
31726
- })
31813
+ })]
31727
31814
  }, "devices"),
31728
31815
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SettingsCard, {
31729
31816
  tab: "image",
@@ -31869,48 +31956,6 @@ window.__ModuleLoader__.load({
31869
31956
  }, item.id))
31870
31957
  })]
31871
31958
  }, "trash"),
31872
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsCard, {
31873
- tab: "audit",
31874
- nameKey: tabLabelKey("audit"),
31875
- descKey: tabDescKey("audit"),
31876
- open: isOpen("audit"),
31877
- onToggle: () => toggleCard("audit"),
31878
- children: audit.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31879
- className: "daw-list-meta daw-empty",
31880
- children: t("auditEmpty")
31881
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31882
- className: "daw-list",
31883
- children: audit.slice(0, auditLimit).map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31884
- className: "daw-list-row",
31885
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31886
- className: "daw-list-title",
31887
- children: String(item.action ?? t("event"))
31888
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
31889
- className: "daw-list-meta",
31890
- children: [
31891
- new Date(Number(item.time ?? 0)).toLocaleString(locale),
31892
- " · ",
31893
- String(item.actorType ?? ""),
31894
- ":",
31895
- String(item.actorId ?? ""),
31896
- " · ",
31897
- String(item.relativePath ?? "")
31898
- ]
31899
- })] })
31900
- }, String(item.id ?? index)))
31901
- }), auditLimit < audit.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
31902
- className: "daw-command daw-inline-command",
31903
- disabled: auditLoading,
31904
- onClick: () => {
31905
- setAuditLoading(true);
31906
- window.setTimeout(() => {
31907
- setAuditLimit((value) => value + 50);
31908
- setAuditLoading(false);
31909
- }, 0);
31910
- },
31911
- children: auditLoading ? t("auditLoading") : t("auditLoadMore")
31912
- })] })
31913
- }, "audit"),
31914
31959
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AppDownloadSection, {
31915
31960
  open: isOpen("app-download"),
31916
31961
  onToggle: () => toggleCard("app-download")
@@ -32098,9 +32143,19 @@ window.__ModuleLoader__.load({
32098
32143
  const [editing, setEditing] = (0, react.useState)(false);
32099
32144
  const [scopes, setScopes] = (0, react.useState)(props.device.scopes);
32100
32145
  const [rootIds, setRootIds] = (0, react.useState)(props.device.rootIds);
32146
+ const [name, setName] = (0, react.useState)(props.device.name);
32101
32147
  const toggle = (list, value) => list.includes(value) ? list.filter((item) => item !== value) : [...list, value];
32102
32148
  const shortId = props.device.id.length > 14 ? `${props.device.id.slice(0, 8)}…${props.device.id.slice(-4)}` : props.device.id;
32103
32149
  const lastSeen = props.device.lastSeenAt === void 0 ? t("deviceNeverSeen") : t("deviceLastSeen", { time: new Date(props.device.lastSeenAt).toLocaleString(locale) });
32150
+ const autoNamed = props.device.nameSource === "default" || props.device.nameSource === "detected";
32151
+ const saveAll = () => {
32152
+ const trimmed = name.trim();
32153
+ const rename = trimmed !== "" && trimmed !== props.device.name;
32154
+ (rename ? props.api.renameDevice(props.device.id, trimmed) : Promise.resolve()).then(() => props.api.updateDevice(props.device.id, scopes, rootIds)).then(props.onChanged).then(() => {
32155
+ setEditing(false);
32156
+ props.onNotice(rename ? "deviceNameSaved" : "permissionsSaved");
32157
+ }).catch(props.onError);
32158
+ };
32104
32159
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
32105
32160
  className: "daw-list-row",
32106
32161
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
@@ -32108,10 +32163,14 @@ window.__ModuleLoader__.load({
32108
32163
  className: "daw-list-title",
32109
32164
  children: [
32110
32165
  props.device.name,
32111
- " ",
32112
32166
  props.device.revokedAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32113
32167
  className: "daw-pill",
32114
32168
  children: t("revoked")
32169
+ }),
32170
+ autoNamed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32171
+ className: "daw-pill",
32172
+ title: t("deviceRenameHint"),
32173
+ children: t("deviceDetectedName")
32115
32174
  })
32116
32175
  ]
32117
32176
  }),
@@ -32122,47 +32181,66 @@ window.__ModuleLoader__.load({
32122
32181
  title: props.device.id,
32123
32182
  children: shortId
32124
32183
  }),
32184
+ props.device.platform !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
32185
+ " · ",
32186
+ props.device.platform,
32187
+ props.device.model === void 0 ? "" : ` · ${props.device.model}`
32188
+ ] }),
32125
32189
  " · ",
32126
32190
  lastSeen,
32127
32191
  " · ",
32128
32192
  props.device.scopes.length === 0 ? t("noScopes") : props.device.scopes.map((scope) => scopeLabel(locale, scope)).join(" · ")
32129
32193
  ]
32130
32194
  }),
32131
- editing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
32132
- className: "daw-scope-grid",
32133
- children: DEVICE_SCOPES.map((scope) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
32134
- className: "daw-check",
32135
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
32136
- type: "checkbox",
32137
- checked: scopes.includes(scope),
32138
- onChange: () => setScopes((current) => toggle(current, scope))
32139
- }), scopeLabel(locale, scope)]
32140
- }, scope))
32141
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
32142
- className: "daw-scope-grid",
32143
- children: props.roots.map((root) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
32144
- className: "daw-check",
32145
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
32146
- type: "checkbox",
32147
- checked: rootIds.includes(root.id),
32148
- onChange: () => setRootIds((current) => toggle(current, root.id))
32149
- }), root.label]
32150
- }, root.id))
32151
- })] })
32195
+ editing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
32196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
32197
+ className: "daw-field",
32198
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("deviceRename") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
32199
+ className: "daw-input",
32200
+ value: name,
32201
+ placeholder: t("deviceRenamePlaceholder"),
32202
+ title: t("deviceRenameHint"),
32203
+ onChange: (event) => setName(event.target.value),
32204
+ onKeyDown: (event) => {
32205
+ if (event.key === "Enter") saveAll();
32206
+ }
32207
+ })]
32208
+ }),
32209
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
32210
+ className: "daw-scope-grid",
32211
+ children: DEVICE_SCOPES.map((scope) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
32212
+ className: "daw-check",
32213
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
32214
+ type: "checkbox",
32215
+ checked: scopes.includes(scope),
32216
+ onChange: () => setScopes((current) => toggle(current, scope))
32217
+ }), scopeLabel(locale, scope)]
32218
+ }, scope))
32219
+ }),
32220
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
32221
+ className: "daw-scope-grid",
32222
+ children: props.roots.map((root) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
32223
+ className: "daw-check",
32224
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
32225
+ type: "checkbox",
32226
+ checked: rootIds.includes(root.id),
32227
+ onChange: () => setRootIds((current) => toggle(current, root.id))
32228
+ }), root.label]
32229
+ }, root.id))
32230
+ })
32231
+ ] })
32152
32232
  ] }), props.device.revokedAt === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
32153
32233
  editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
32154
32234
  className: "daw-command primary",
32155
- onClick: () => {
32156
- props.api.updateDevice(props.device.id, scopes, rootIds).then(props.onChanged).then(() => {
32157
- setEditing(false);
32158
- props.onNotice("permissionsSaved");
32159
- }).catch(props.onError);
32160
- },
32235
+ onClick: saveAll,
32161
32236
  children: t("save")
32162
32237
  }),
32163
32238
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
32164
32239
  className: "daw-command",
32165
- onClick: () => setEditing((value) => !value),
32240
+ onClick: () => {
32241
+ setName(props.device.name);
32242
+ setEditing((value) => !value);
32243
+ },
32166
32244
  children: editing ? t("cancel") : t("permissions")
32167
32245
  }),
32168
32246
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -32183,7 +32261,6 @@ window.__ModuleLoader__.load({
32183
32261
  if (tab === "devices") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Smartphone, { size: 15 });
32184
32262
  if (tab === "image") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Image, { size: 15 });
32185
32263
  if (tab === "trash") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Trash2, { size: 15 });
32186
- if (tab === "audit") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.ScrollText, { size: 15 });
32187
32264
  if (tab === "remote") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Upload, { size: 15 });
32188
32265
  if (tab === "app-download") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Download, { size: 15 });
32189
32266
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.File, { size: 15 });