@senguoyun/dsh-arkme 0.1.82 → 0.1.83

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 (74) hide show
  1. package/docs/ai-points-implementation.md +43 -0
  2. package/docs/interwoven-compact-summary-regression-2026-09-28.md +35 -0
  3. package/docs/interwoven-original-read-receipt-regression-2026-09-28.md +50 -0
  4. package/docs/personal-detail-consistency-regression-2026-09-28.md +40 -0
  5. package/docs/send-to-self-roles-cross-client-api-handoff-2026-09-27.md +9 -0
  6. package/lib/client.js +2181 -1710
  7. package/lib/client.js.map +1 -1
  8. package/lib/harness-model-client.js +123 -37
  9. package/lib/harness-native-selection-client.js +57 -1
  10. package/lib/harness-sidebar-client.js +11 -0
  11. package/lib/index.js +194 -56
  12. package/lib/persistent-extension.js +1 -1
  13. package/lib/{persistent-runtime-DV9Hme-U.js → persistent-runtime-B6vPAaiG.js} +507 -42
  14. package/lib/sdk.js +11 -0
  15. package/lib/types/ai-points.d.ts +61 -0
  16. package/lib/types/ai-points.d.ts.map +1 -0
  17. package/lib/types/arkme-service.d.ts +10 -0
  18. package/lib/types/arkme-service.d.ts.map +1 -1
  19. package/lib/types/billing-gateway.d.ts.map +1 -1
  20. package/lib/types/client/ArkmeAccountUsage.d.ts +1 -3
  21. package/lib/types/client/ArkmeAccountUsage.d.ts.map +1 -1
  22. package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
  23. package/lib/types/client/ArkmeBillingSettings.d.ts +3 -2
  24. package/lib/types/client/ArkmeBillingSettings.d.ts.map +1 -1
  25. package/lib/types/client/ArkmeDataManagementSettings.d.ts.map +1 -1
  26. package/lib/types/client/ArkmeDocumentComposerInput.d.ts.map +1 -1
  27. package/lib/types/client/ArkmeEmojiPicker.d.ts.map +1 -1
  28. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts +12 -0
  29. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts.map +1 -0
  30. package/lib/types/client/ArkmeModelSelect.d.ts.map +1 -1
  31. package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
  32. package/lib/types/client/ArkmePointsConsumption.d.ts +5 -0
  33. package/lib/types/client/ArkmePointsConsumption.d.ts.map +1 -0
  34. package/lib/types/client/ArkmeRelatedQuickNotes.d.ts.map +1 -1
  35. package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
  36. package/lib/types/client/ArkoModelMenu.d.ts.map +1 -1
  37. package/lib/types/client/api.d.ts +1 -1
  38. package/lib/types/client/api.d.ts.map +1 -1
  39. package/lib/types/client/interwoven-moments.d.ts.map +1 -1
  40. package/lib/types/client/interwoven-read-receipt-store.d.ts +32 -0
  41. package/lib/types/client/interwoven-read-receipt-store.d.ts.map +1 -0
  42. package/lib/types/client/locales/actions-en.d.ts.map +1 -1
  43. package/lib/types/client/locales/dynamic-en.d.ts.map +1 -1
  44. package/lib/types/client/self-role-presentation.d.ts +6 -1
  45. package/lib/types/client/self-role-presentation.d.ts.map +1 -1
  46. package/lib/types/client/use-personal-extension-parents.d.ts +4 -0
  47. package/lib/types/client/use-personal-extension-parents.d.ts.map +1 -0
  48. package/lib/types/host-api.d.ts.map +1 -1
  49. package/lib/types/index.d.ts.map +1 -1
  50. package/lib/types/managed-ai/adapter.d.ts +2 -1
  51. package/lib/types/managed-ai/adapter.d.ts.map +1 -1
  52. package/lib/types/managed-ai/operation.d.ts +17 -0
  53. package/lib/types/managed-ai/operation.d.ts.map +1 -0
  54. package/lib/types/managed-ai/transport.d.ts +1 -0
  55. package/lib/types/managed-ai/transport.d.ts.map +1 -1
  56. package/lib/types/record-extension-tree.d.ts +2 -0
  57. package/lib/types/record-extension-tree.d.ts.map +1 -1
  58. package/lib/types/sdk/index.d.ts +4 -0
  59. package/lib/types/sdk/index.d.ts.map +1 -1
  60. package/lib/types/services/ai-points-service.d.ts +13 -0
  61. package/lib/types/services/ai-points-service.d.ts.map +1 -0
  62. package/lib/types/services/arko-service.d.ts.map +1 -1
  63. package/lib/types/services/chat-service.d.ts +9 -1
  64. package/lib/types/services/chat-service.d.ts.map +1 -1
  65. package/lib/types/services/interwoven-service.d.ts +3 -1
  66. package/lib/types/services/interwoven-service.d.ts.map +1 -1
  67. package/lib/types/tools/business/account/ai-points.d.ts +4 -0
  68. package/lib/types/tools/business/account/ai-points.d.ts.map +1 -0
  69. package/lib/types/tools/business/account/index.d.ts.map +1 -1
  70. package/lib/types/tools/ports/profile.d.ts +3 -0
  71. package/lib/types/tools/ports/profile.d.ts.map +1 -1
  72. package/lib/types/types.d.ts +17 -3
  73. package/lib/types/types.d.ts.map +1 -1
  74. package/package.json +5 -5
package/lib/client.js CHANGED
@@ -254,6 +254,17 @@ window.__ModuleLoader__.load({
254
254
  if (capabilities.contractVersion !== 1) throw new Error(`Unsupported Arkme provider contract version ${String(capabilities.contractVersion)}`);
255
255
  return capabilities;
256
256
  }
257
+ async aiPointsAccount(expectedAccountScope, signal) {
258
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
259
+ return this.call("account.points.query", { expectedAccountScope }, signal);
260
+ }
261
+ async aiPointsConsumption(expectedAccountScope, query, signal) {
262
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
263
+ return this.call("account.points.consumption", {
264
+ expectedAccountScope,
265
+ ...query
266
+ }, signal);
267
+ }
257
268
  async state(signal) {
258
269
  return await this.call("provider.state", void 0, signal);
259
270
  }
@@ -33281,7 +33292,7 @@ Agent · 内容由 AI 生成,仅供参考|Agent · AI-generated content; verif
33281
33292
  当前运行的任务预先占用的余额,任务完成后将返还剩余余额。|Credit reserved for running tasks. Unused credit is released when tasks finish.
33282
33293
  充值|Add credit
33283
33294
  余额充值|Add credit
33284
- 充值后可在 DSH 会话中通过 Arkme 调用 AI 模型|Use prepaid credit to access AI models through Arkme in DSH.
33295
+ APP 与 Arkme 3.0 共用积分,充值到账后即可使用|AI points are shared between the app and Arkme 3.0, and available once credited.
33285
33296
  当前余额|Current balance
33286
33297
  刷新|Refresh
33287
33298
  充值套餐|Credit packages
@@ -35069,6 +35080,12 @@ Bot 列表加载失败,点击重试|Could not load Bots. Click to retry
35069
35080
  //#endregion
35070
35081
  //#region src/client/locales/actions-en.ts
35071
35082
  const actionEnglish = {
35083
+ "群聊提及": "Group mention",
35084
+ "群内原消息的已读状态暂不可用": "Read status of the original group message is unavailable",
35085
+ "对方已阅读群内原消息": "They have read the original group message",
35086
+ "对方尚未阅读群内原消息": "They have not read the original group message",
35087
+ "你已阅读群内原消息": "You have read the original group message",
35088
+ "你尚未阅读群内原消息": "You have not read the original group message",
35072
35089
  "绑定邮箱": "Bind email",
35073
35090
  "请输入邮箱地址": "Enter your email address",
35074
35091
  "请输入有效的邮箱地址": "Enter a valid email address",
@@ -35440,6 +35457,51 @@ Arkme 用户 {v0}|Arkme user {v0}
35440
35457
  {v0};录音仍保留在本机,可重试或下载|{v0}; recording remains on this device. Retry or download it.
35441
35458
  参与者: {v0}|Participants: {v0}
35442
35459
  说话人 {v0}|Speaker {v0}
35460
+
35461
+ AI 额度|AI allowance
35462
+ 积分|points
35463
+ 赠送积分|Granted points
35464
+ 充值积分|Purchased points
35465
+ 赠送积分到期时间|Grant expires
35466
+ 任务进行中暂占|Reserved by running tasks:
35467
+ 积分,结束后返还未用部分|points; unused points return when the task finishes
35468
+ 赠送 {v0} · 充值 {v1}|Granted {v0} · Purchased {v1}
35469
+ DSH 对话|DSH chat
35470
+ AI 调用|AI usage
35471
+ (赠送)| (Gift)
35472
+ (充值)| (Purchased)
35473
+ (赠送 {v0} · 充值 {v1})| (Gift {v0} · Purchased {v1})
35474
+ 消费记录|Spending history
35475
+ 模型调用|Model usage
35476
+ 附加服务|Additional service
35477
+ 消费月份|Spending month
35478
+ 该月消费|Spent in selected month
35479
+ 该月暂无积分消费|No point spending in selected month
35480
+ 暂时无法读取|Could not load
35481
+ 暂时无法读取消费明细。|Spending details could not be loaded.
35482
+ 输入 Token|Input tokens
35483
+ 输出 Token|Output tokens
35484
+ 缓存命中|Cache hit
35485
+ 缓存未命中|Cache miss
35486
+ 加载失败,已有明细已保留。|Loading failed. Existing entries have been kept.
35487
+ 积分充值|Buy points
35488
+ 可用积分|Available points
35489
+ 预占积分|Reserved points
35490
+ 预占积分说明|About reserved points
35491
+ 当前运行的任务预先占用的积分,任务完成后将返还未用积分。|Running tasks reserve points. Unused points return when the task finishes.
35492
+ 正在加载积分…|Loading points…
35493
+ 积分读取失败,点击重试|Points could not be loaded. Click to retry.
35494
+ 积分加载中…|Loading points…
35495
+ 积分读取失败|Points could not be loaded
35496
+ 积分到账中,到账后会自动刷新可用积分。|Your points are being credited. Available points will refresh automatically.
35497
+ 已到账,正在刷新可用积分|Credited. Refreshing available points…
35498
+ 可用积分已刷新:|Available points refreshed:
35499
+ 积分暂未刷新:|Points have not refreshed:
35500
+ 刷新积分|Refresh points
35501
+ AI 额度 {v0}|AI allowance {v0}
35502
+ AI 额度充值流程|AI point purchase
35503
+ 次调用|calls
35504
+ 按用量扣积分 · 计费说明|Usage-based points · Pricing details
35443
35505
  `.trim().split("\n").map((line) => {
35444
35506
  const p = line.indexOf("|");
35445
35507
  return [line.slice(0, p), line.slice(p + 1)];
@@ -119721,6 +119783,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
119721
119783
  };
119722
119784
  //#endregion
119723
119785
  //#region src/client/self-role-presentation.ts
119786
+ /** Personal views only: local roles keep their identity; the real self uses today's account avatar.
119787
+ * A device without a local role binding must use its own profile reference, not a historical
119788
+ * asset or another device's local avatar. This never mutates the snapshot kept for later sync.
119789
+ */
119790
+ function arkmePersonalAvatarRef(item, profile) {
119791
+ const recordedAvatar = item.avatarRef?.trim() || void 0;
119792
+ if (!item.isMe) return recordedAvatar;
119793
+ if (item.selfRole !== void 0) return item.selfRole.avatarRef?.trim() || void 0;
119794
+ return profile?.avatarRef.trim() || recordedAvatar;
119795
+ }
119724
119796
  /** Role identity is a local display layer, never a replacement for record ownership. */
119725
119797
  function arkmeSelfRoleForPresentation(item, sourceKind) {
119726
119798
  if (!item.isMe) return void 0;
@@ -121072,7 +121144,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
121072
121144
  const native = nativeSelection();
121073
121145
  const pending = pendingEmojiSelection.current;
121074
121146
  pendingEmojiSelection.current = void 0;
121075
- const selection = native ?? (pending?.doc === editor.state.doc ? pending : editor.state.selection);
121147
+ const selection = (pending?.doc === editor.state.doc ? pending : void 0) ?? native ?? editor.state.selection;
121076
121148
  const anchor = Math.max(0, Math.min(editor.state.doc.content.size, selection.anchor));
121077
121149
  const head = Math.max(0, Math.min(editor.state.doc.content.size, selection.head));
121078
121150
  const previousState = editor.state;
@@ -121151,6 +121223,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
121151
121223
  },
121152
121224
  onFocus: props.onFocus,
121153
121225
  onBlur: props.onBlur,
121226
+ onPointerDownCapture: () => {
121227
+ pendingEmojiSelection.current = void 0;
121228
+ },
121229
+ onMouseDownCapture: () => {
121230
+ pendingEmojiSelection.current = void 0;
121231
+ },
121154
121232
  onCopyCapture: syncNativeTextSelection,
121155
121233
  onCutCapture: syncNativeTextSelection,
121156
121234
  onPasteCapture: (event) => {
@@ -121158,6 +121236,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
121158
121236
  props.onPaste?.(event);
121159
121237
  },
121160
121238
  onKeyDownCapture: (event) => {
121239
+ pendingEmojiSelection.current = void 0;
121161
121240
  if (event.nativeEvent.isComposing || event.keyCode === 229) {
121162
121241
  if (props.format === "text") event.stopPropagation();
121163
121242
  return;
@@ -122067,7 +122146,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
122067
122146
  };
122068
122147
  }
122069
122148
  function ArkmeRelatedQuickNotesCard({ state, onOpen, onRetry }) {
122070
- if (state.kind === "idle" || state.kind === "loading" || state.kind === "empty") return null;
122149
+ if (state.kind === "idle" || state.kind === "empty") return null;
122150
+ if (state.kind === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
122151
+ style: styles$57.compactError,
122152
+ role: "status",
122153
+ "data-arkme-related-quick-notes-loading": true,
122154
+ children: tr$1("正在加载相关快记…")
122155
+ });
122071
122156
  if (state.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
122072
122157
  style: styles$57.compactError,
122073
122158
  "data-arkme-related-quick-notes-error": true,
@@ -123864,11 +123949,12 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
123864
123949
  role
123865
123950
  };
123866
123951
  const ownRecord = personalSource && item.sourceKind === "record_extension" && profile !== void 0 && (item.recordOwnerUserId === void 0 || item.recordOwnerUserId === profile.userId);
123867
- const currentNameFallback = ownRecord && item.senderNameSnapshot !== true && item.senderDisplayName.trim() === "我";
123868
- const currentAvatarFallback = ownRecord && !item.senderAvatarUrl?.trim() && !!profile?.avatarRef.trim();
123869
123952
  return {
123870
- name: currentNameFallback ? profile?.nickname.trim() || profile?.displayName.trim() || detailExtensionSenderName(item) : detailExtensionSenderName(item),
123871
- avatar: currentAvatarFallback ? profile?.avatarRef.trim() ?? "" : item.senderAvatarUrl?.trim() ?? ""
123953
+ name: ownRecord && item.senderNameSnapshot !== true && item.senderDisplayName.trim() === "我" ? profile?.nickname.trim() || profile?.displayName.trim() || detailExtensionSenderName(item) : detailExtensionSenderName(item),
123954
+ avatar: arkmePersonalAvatarRef({
123955
+ isMe: ownRecord,
123956
+ ...item.senderAvatarUrl === void 0 ? {} : { avatarRef: item.senderAvatarUrl }
123957
+ }, profile) ?? ""
123872
123958
  };
123873
123959
  }
123874
123960
  function detailExtensionTimelineItem$1(item, author) {
@@ -124116,6 +124202,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
124116
124202
  const historyTarget = `${normalizedSourceRef}:${item.itemUid}`;
124117
124203
  const historyOpen = editHistoryTarget === historyTarget && messageActionRef !== "";
124118
124204
  const quickNoteDetailsSupported = item.quickNoteDetailsSupported !== false;
124205
+ const extensionParent = extensionState.kind === "success" ? extensionState.context.extensionParent ?? item.extensionParent : item.extensionParent;
124119
124206
  const loadRelated = (0, react$1.useCallback)(() => {
124120
124207
  listAbortRef.current?.abort();
124121
124208
  if (!quickNoteDetailsSupported || normalizedSourceRef === "" || messageActionRef === "") {
@@ -124124,7 +124211,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
124124
124211
  }
124125
124212
  const controller = new AbortController();
124126
124213
  listAbortRef.current = controller;
124127
- setRelatedState({ kind: "loading" });
124214
+ setRelatedState((current) => current.kind === "success" ? current : { kind: "loading" });
124128
124215
  callArkme("source.related-quick-notes.from-message", {
124129
124216
  sourceRef: normalizedSourceRef,
124130
124217
  messageActionRef
@@ -124276,14 +124363,13 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
124276
124363
  const canToggle = item.aiPolish?.state === "polished" && item.aiPolish.originalText !== void 0 && item.aiPolish.polishedText !== void 0;
124277
124364
  const personalSource = sourceKind === "send_to_self" || sourceKind === "topic" || sourceKind === "default_category";
124278
124365
  const currentNameFallback = personalSource && item.isMe && item.avatarSnapshot === true && item.senderNameSnapshot !== true && currentSelfProfile !== void 0;
124279
- const currentAvatarFallback = personalSource && item.isMe && item.avatarSnapshot === true && !item.avatarRef?.trim() && !!currentSelfProfile?.avatarRef.trim();
124280
124366
  const selfRole = sourceKind === void 0 ? void 0 : arkmeSelfRoleForPresentation(item, sourceKind);
124281
124367
  const authorName = selfRole?.name ?? (currentNameFallback ? currentSelfProfile?.nickname.trim() || currentSelfProfile?.displayName.trim() || item.senderName : arkmeTimelineDetailSenderText(item, conversationMembers));
124282
- const authorAvatarRef = selfRole === void 0 ? currentAvatarFallback ? currentSelfProfile?.avatarRef : item.avatarRef : selfRole.avatarRef;
124368
+ const authorAvatarRef = personalSource ? arkmePersonalAvatarRef(item, currentSelfProfile) : item.avatarRef;
124283
124369
  const roleAvatarFallback = selfRole === void 0 ? void 0 : arkmeSelfRoleAvatarFallback(selfRole);
124284
124370
  const topicTitle = selfTopicPath?.trim() || item.selfTopic?.title?.trim() || tr$1("未指定主题");
124285
124371
  const canOpenTopic = selfTopicSource?.kind === "topic" && onOpenSelfTopic !== void 0;
124286
- const showTopicBadge = personalSource && (sourceKind !== "topic" || selfTopicSource?.kind === "topic");
124372
+ const showTopicBadge = personalSource;
124287
124373
  const extensionFooter = !quickNoteDetailsSupported || !canExtend || normalizedSourceRef === "" || messageActionRef === "" ? void 0 : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DetailExtensionComposer, {
124288
124374
  sourceRef: normalizedSourceRef,
124289
124375
  sourceKind,
@@ -124391,8 +124477,8 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
124391
124477
  messageActionRef,
124392
124478
  author: item
124393
124479
  }, historyTarget) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
124394
- quickNoteDetailsSupported && item.extensionParent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DetailExtensionParent, {
124395
- parent: item.extensionParent,
124480
+ quickNoteDetailsSupported && extensionParent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DetailExtensionParent, {
124481
+ parent: extensionParent,
124396
124482
  onOpen: onOpenExtensionParent
124397
124483
  }),
124398
124484
  canToggle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -125926,7 +126012,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
125926
126012
  String(date.getDate()).padStart(2, "0")
125927
126013
  ].join("-");
125928
126014
  }
125929
- function monthLabel$2(date) {
126015
+ function monthLabel$1(date) {
125930
126016
  if (getArkmeLocale() === "en") return new Intl.DateTimeFormat("en-US", {
125931
126017
  month: "short",
125932
126018
  year: "numeric"
@@ -125943,7 +126029,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
125943
126029
  year: "numeric"
125944
126030
  }).format(date) + (sameDay(date, today) ? " · Today" : "");
125945
126031
  const suffix = sameDay(date, today) ? " · 今天" : "";
125946
- return `${monthLabel$2(date)}${String(date.getDate())}日${suffix}`;
126032
+ return `${monthLabel$1(date)}${String(date.getDate())}日${suffix}`;
125947
126033
  }
125948
126034
  function timeLabel$4(value) {
125949
126035
  return Number.isFinite(value) && value > 0 ? new Intl.DateTimeFormat(arkmeIntlLocale(), {
@@ -126009,7 +126095,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
126009
126095
  }),
126010
126096
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
126011
126097
  style: styles$55.monthTitle,
126012
- children: monthLabel$2(visibleMonth)
126098
+ children: monthLabel$1(visibleMonth)
126013
126099
  }),
126014
126100
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
126015
126101
  "data-arkme-feedback": "neutral",
@@ -126112,7 +126198,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
126112
126198
  const known = resource.value !== void 0;
126113
126199
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
126114
126200
  ref: element,
126115
- "aria-label": monthLabel$2(month),
126201
+ "aria-label": monthLabel$1(month),
126116
126202
  "data-calendar-month": dateKey$1(month).slice(0, 7),
126117
126203
  style: { paddingBottom: 12 },
126118
126204
  children: [
@@ -126156,7 +126242,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
126156
126242
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
126157
126243
  type: "button",
126158
126244
  "data-arkme-feedback": "neutral",
126159
- "aria-label": tr$1("跳转月份:{v0}", { v0: monthLabel$2(month) }),
126245
+ "aria-label": tr$1("跳转月份:{v0}", { v0: monthLabel$1(month) }),
126160
126246
  title: tr$1("跳转年月"),
126161
126247
  onClick: () => setEditingMonth(true),
126162
126248
  style: {
@@ -126170,7 +126256,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
126170
126256
  font: "inherit",
126171
126257
  cursor: "pointer"
126172
126258
  },
126173
- children: monthLabel$2(month)
126259
+ children: monthLabel$1(month)
126174
126260
  })
126175
126261
  }),
126176
126262
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -153955,7 +154041,7 @@ body:has([data-arkme-self-topic-menu]) > [role="menu"] { z-index: 10030; }
153955
154041
  };
153956
154042
  //#endregion
153957
154043
  //#region node_modules/@rc-component/util/es/hooks/useMemo.js
153958
- function useMemo$35(getValue, condition, shouldUpdate) {
154044
+ function useMemo$36(getValue, condition, shouldUpdate) {
153959
154045
  const cacheRef = react.useRef({});
153960
154046
  if (!("value" in cacheRef.current) || shouldUpdate(cacheRef.current.condition, condition)) {
153961
154047
  cacheRef.current.value = getValue();
@@ -154068,7 +154154,7 @@ body:has([data-arkme-self-topic-menu]) > [role="menu"] { z-index: 10030; }
154068
154154
  };
154069
154155
  };
154070
154156
  const useComposeRef = (...refs) => {
154071
- return useMemo$35(() => composeRef(...refs), refs, (prev, next) => prev.length !== next.length || prev.every((ref, i) => ref !== next[i]));
154157
+ return useMemo$36(() => composeRef(...refs), refs, (prev, next) => prev.length !== next.length || prev.every((ref, i) => ref !== next[i]));
154072
154158
  };
154073
154159
  const supportRef = (nodeOrComponent) => {
154074
154160
  if (!nodeOrComponent) return false;
@@ -155266,7 +155352,7 @@ html body {
155266
155352
  RefResizeObserver.Collection = Collection;
155267
155353
  //#endregion
155268
155354
  //#region node_modules/@rc-component/motion/es/context.js
155269
- const Context$1 = /*#__PURE__*/ react.createContext({});
155355
+ const Context$2 = /*#__PURE__*/ react.createContext({});
155270
155356
  //#endregion
155271
155357
  //#region node_modules/@rc-component/motion/es/interface.js
155272
155358
  const STATUS_NONE = "none";
@@ -155562,7 +155648,7 @@ html body {
155562
155648
  }
155563
155649
  const CSSMotion = /*#__PURE__*/ react.forwardRef((props, ref) => {
155564
155650
  const { visible = true, removeOnLeave = true, forceRender, children, motionName, leavedClassName, eventProps } = props;
155565
- const { motion: contextMotion } = react.useContext(Context$1);
155651
+ const { motion: contextMotion } = react.useContext(Context$2);
155566
155652
  const supportMotion = isSupportTransition(props, contextMotion);
155567
155653
  const nodeRef = (0, react.useRef)();
155568
155654
  function getDomElement() {
@@ -171782,7 +171868,7 @@ html body {
171782
171868
  const n$6 = o$11;
171783
171869
  //#endregion
171784
171870
  //#region src/client/arkme-model-select.css?inline
171785
- var arkme_model_select_default = ".arkme-model-select {\n min-width: 0;\n font-family: inherit;\n position: relative;\n}\n\n.arkme-model-select button {\n font: inherit;\n cursor: pointer;\n}\n\n.arkme-model-select button:disabled {\n opacity: .5;\n cursor: default;\n}\n\n.arkme-model-select button:focus-visible {\n outline-offset: -2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-trigger {\n max-width: min(360px, 45vw);\n height: 28px;\n color: var(--dsw-alias-label-secondary, #626772);\n background: none;\n border: 0;\n border-radius: 14px;\n align-items: center;\n gap: 5px;\n padding: 0 8px;\n display: flex;\n font-size: 13px !important;\n}\n\n.arkme-model-trigger > span:first-child {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.arkme-model-trigger small {\n flex-shrink: 0;\n}\n\n.arkme-model-menu {\n z-index: 30;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n background: var(--dsw-specific-menu, #fff);\n width: max-content;\n min-width: min(280px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(400px, 100vh - 96px);\n color: var(--dsw-alias-label-primary, #20232c);\n border-radius: 12px;\n padding: 5px;\n position: absolute;\n bottom: calc(100% + 8px);\n right: 0;\n overflow-y: auto;\n box-shadow: 0 8px 30px #0002;\n}\n\n.arkme-model-group-heading {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 7px 9px 4px;\n font-size: 12px;\n display: flex;\n}\n\n.arkme-model-balance-actions {\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n.arkme-model-balance-actions button {\n color: #3478e5;\n white-space: nowrap;\n background: none;\n border: 0;\n padding: 2px 0;\n}\n\n.arkme-model-balance-actions button:hover {\n text-decoration: underline;\n}\n\n.arkme-model-option {\n width: 100%;\n min-height: 38px;\n color: inherit;\n text-align: left;\n background: none;\n border: 0;\n border-radius: 8px;\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 8px 10px;\n display: flex;\n font-size: 14px !important;\n}\n\n.arkme-model-option:hover, .arkme-model-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover, #f3f4f6);\n}\n\n.arkme-model-option > span:first-child {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n.arkme-model-option small {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n font-size: 12px;\n display: block;\n}\n\n.arkme-model-status, .arkme-model-error {\n padding: 8px 10px;\n font-size: 12px;\n}\n\n.arkme-model-error {\n color: var(--dsw-alias-state-error-primary, #b54841);\n}\n\n.arkme-model-error button {\n color: inherit;\n background: none;\n border: 0;\n text-decoration: underline;\n}\n";
171871
+ var arkme_model_select_default = ".arkme-model-select {\n min-width: 0;\n font-family: inherit;\n position: relative;\n}\n\n.arkme-model-select button {\n font: inherit;\n cursor: pointer;\n}\n\n.arkme-model-select button:disabled {\n opacity: .5;\n cursor: default;\n}\n\n.arkme-model-select button:focus-visible {\n outline-offset: -2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-trigger {\n max-width: min(360px, 45vw);\n height: 28px;\n color: var(--dsw-alias-label-secondary, #626772);\n background: none;\n border: 0;\n border-radius: 14px;\n align-items: center;\n gap: 5px;\n padding: 0 8px;\n display: flex;\n font-size: 13px !important;\n}\n\n.arkme-model-trigger > span:first-child {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.arkme-model-trigger small {\n flex-shrink: 0;\n}\n\n.arkme-model-menu {\n z-index: 30;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n background: var(--dsw-specific-menu, #fff);\n width: max-content;\n min-width: min(280px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(400px, 100vh - 96px);\n color: var(--dsw-alias-label-primary, #20232c);\n border-radius: 12px;\n padding: 5px;\n position: absolute;\n bottom: calc(100% + 8px);\n right: 0;\n overflow-y: auto;\n box-shadow: 0 8px 30px #0002;\n}\n\n.arkme-model-group-heading {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 7px 9px 4px;\n font-size: 12px;\n display: flex;\n}\n\n.arkme-model-balance-actions {\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n.arkme-model-balance-actions button {\n color: #3478e5;\n white-space: nowrap;\n background: none;\n border: 0;\n padding: 2px 0;\n}\n\n.arkme-model-balance-actions button:hover {\n text-decoration: underline;\n}\n\n.arkme-model-option {\n width: 100%;\n min-height: 38px;\n color: inherit;\n text-align: left;\n background: none;\n border: 0;\n border-radius: 8px;\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 8px 10px;\n display: flex;\n font-size: 14px !important;\n}\n\n.arkme-model-option:hover, .arkme-model-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover, #f3f4f6);\n}\n\n.arkme-model-option > span:first-child {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n.arkme-model-option small {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n font-size: 12px;\n display: block;\n}\n\n.arkme-model-status, .arkme-model-error {\n padding: 8px 10px;\n font-size: 12px;\n}\n\n.arkme-model-error {\n color: var(--dsw-alias-state-error-primary, #b54841);\n}\n\n.arkme-model-error button {\n color: inherit;\n background: none;\n border: 0;\n text-decoration: underline;\n}\n\n.arkme-model-price {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n padding: 0 10px 8px;\n font-size: 12px;\n}\n\n.arkme-model-price summary {\n cursor: pointer;\n}\n\n.arkme-model-price small {\n overflow-wrap: anywhere;\n padding-top: 6px;\n line-height: 1.6;\n display: block;\n}\n";
171786
171872
  //#endregion
171787
171873
  //#region src/client/ArkoModelMenu.tsx
171788
171874
  function ArkoModelMenu({ anchor, catalog, busy, error, onSelect, onClose }) {
@@ -171871,7 +171957,7 @@ html body {
171871
171957
  children: [
171872
171958
  catalog.options.map((option) => {
171873
171959
  const selected = option.routeKey === catalog.effectiveRouteKey;
171874
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
171960
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
171875
171961
  type: "button",
171876
171962
  className: "arkme-model-option",
171877
171963
  role: "menuitemradio",
@@ -171891,7 +171977,10 @@ html body {
171891
171977
  style: { flex: "none" },
171892
171978
  "aria-hidden": true
171893
171979
  })]
171894
- }, option.routeKey);
171980
+ }), option.costDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
171981
+ className: "arkme-model-price",
171982
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: tr$1("按用量扣积分 · 计费说明") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: option.costDescription })]
171983
+ })] }, option.routeKey);
171895
171984
  }),
171896
171985
  busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
171897
171986
  className: "arkme-model-status",
@@ -172538,6 +172627,7 @@ html body {
172538
172627
  const hostRef = (0, react$1.useRef)(null);
172539
172628
  const panelRef = (0, react$1.useRef)(null);
172540
172629
  const stickerInputRef = (0, react$1.useRef)(null);
172630
+ const pointerSelectionCaptured = (0, react$1.useRef)(false);
172541
172631
  const [open, setOpen] = (0, react$1.useState)(false);
172542
172632
  const [tab, setTab] = (0, react$1.useState)("emoji");
172543
172633
  const [stickers, setStickers] = (0, react$1.useState)([]);
@@ -172889,11 +172979,17 @@ html body {
172889
172979
  "aria-haspopup": "dialog",
172890
172980
  "aria-expanded": open,
172891
172981
  "data-arkme-composer-tool": "emoji",
172892
- onMouseDown: (event) => {
172982
+ onPointerDown: () => {
172893
172983
  onBeforeToggle?.();
172984
+ pointerSelectionCaptured.current = true;
172985
+ },
172986
+ onMouseDown: (event) => {
172987
+ if (!pointerSelectionCaptured.current) onBeforeToggle?.();
172988
+ pointerSelectionCaptured.current = false;
172894
172989
  event.preventDefault();
172895
172990
  },
172896
172991
  onClick: () => {
172992
+ pointerSelectionCaptured.current = false;
172897
172993
  setOpen((value) => !value);
172898
172994
  },
172899
172995
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -174729,6 +174825,7 @@ html body {
174729
174825
  }
174730
174826
  }
174731
174827
  function selectedModelName(catalog) {
174828
+ if (catalog?.selectionSource === "unavailable") return "原模型已下线,请重新选择";
174732
174829
  return catalog?.options.find((option) => option.routeKey === catalog.effectiveRouteKey)?.displayName ?? "模型目录暂不可用";
174733
174830
  }
174734
174831
  function ArkmeArkoSurface() {
@@ -175166,7 +175263,7 @@ html body {
175166
175263
  sending
175167
175264
  ]);
175168
175265
  const interactionLocked = sending || pendingTurn !== void 0 || activeRun !== void 0;
175169
- const sendDisabled = loading || interactionLocked || clearing || selectingModel || session === void 0 || profileUserId === void 0;
175266
+ const sendDisabled = loading || interactionLocked || clearing || selectingModel || catalog?.selectionSource === "unavailable" || session === void 0 || profileUserId === void 0;
175170
175267
  const inputDisabled = loading || interactionLocked || session === void 0 || profileUserId === void 0;
175171
175268
  const insertEmoji = (0, react$1.useCallback)((emoji) => {
175172
175269
  if (inputDisabled || composerDraftKey === void 0) return false;
@@ -175297,7 +175394,7 @@ html body {
175297
175394
  ]);
175298
175395
  const displayName = arkoPresentationName(profile);
175299
175396
  const selectedModel = catalog === void 0 && modelError === "" ? tr$1("正在加载模型…") : selectedModelName(catalog);
175300
- const canChooseModel = (catalog?.options.length ?? 0) > 1;
175397
+ const canChooseModel = (catalog?.options.length ?? 0) > 0;
175301
175398
  const continuation = (0, react$1.useMemo)(() => latestContinuation(messages, session?.sessionId), [messages, session?.sessionId]);
175302
175399
  (0, react$1.useEffect)(() => {
175303
175400
  if (!pendingComposerFocusRef.current || loading || interactionLocked || session === void 0 || profileUserId === void 0) return;
@@ -210561,7 +210658,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
210561
210658
  const c$3 = e$20;
210562
210659
  //#endregion
210563
210660
  //#region package.json
210564
- var version = "0.1.82";
210661
+ var version = "0.1.83";
210565
210662
  //#endregion
210566
210663
  //#region src/client/arkme-membership.ts
210567
210664
  function membershipLabel(state) {
@@ -210835,6 +210932,249 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
210835
210932
  }), document.body);
210836
210933
  }
210837
210934
  //#endregion
210935
+ //#region src/ai-points.ts
210936
+ function pointsUnits(value) {
210937
+ if (!/^(?:0|[1-9]\d*)(?:\.\d{1,7})?$/.test(value)) throw new TypeError("Invalid exact AI points");
210938
+ const [whole = "0", fraction = ""] = value.split(".");
210939
+ const units = BigInt(whole) * 10000000n + BigInt(fraction.padEnd(7, "0"));
210940
+ if (units > 9223372036854775807n) throw new TypeError("AI points exceed accounting range");
210941
+ return units;
210942
+ }
210943
+ /** Display floors only; a rounded label can never overpromise spendable points. */
210944
+ function formatAiPoints(value) {
210945
+ const units = pointsUnits(value);
210946
+ if (units > 0n && units < 100000n) return "< 0.01";
210947
+ const hundredths = units / 100000n;
210948
+ const whole = (hundredths / 100n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
210949
+ const fraction = (hundredths % 100n).toString().padStart(2, "0").replace(/0+$/, "");
210950
+ return fraction ? `${whole}.${fraction}` : whole;
210951
+ }
210952
+ /** Existing recharge values retain their nano-CNY meaning: ¥1 = 100 points. */
210953
+ function nanoCnyToPoints(value) {
210954
+ if (!/^(?:0|[1-9]\d*)$/.test(value)) throw new TypeError("Invalid nano-CNY");
210955
+ const units = BigInt(value);
210956
+ const whole = units / 10000000n;
210957
+ const fraction = (units % 10000000n).toString().padStart(7, "0").replace(/0+$/, "");
210958
+ return fraction ? `${whole}.${fraction}` : whole.toString();
210959
+ }
210960
+ /** The server pages whole operations. Call-level charges remain the only facts. */
210961
+ function groupPointsConsumption(items) {
210962
+ const groups = /* @__PURE__ */ new Map();
210963
+ for (const item of items) {
210964
+ const key = item.businessCode === "agent" && item.operationUid ? `agent:${item.operationUid}` : `request:${item.requestUid}`;
210965
+ const calls = groups.get(key) ?? [];
210966
+ calls.push(item);
210967
+ groups.set(key, calls);
210968
+ }
210969
+ return [...groups].map(([key, calls]) => ({
210970
+ key,
210971
+ calls,
210972
+ chargedPoints: nanoCnyToPoints(calls.reduce((sum, call) => sum + pointsUnits(call.chargedPoints), 0n).toString())
210973
+ }));
210974
+ }
210975
+ //#endregion
210976
+ //#region src/client/ArkmePointsConsumption.tsx
210977
+ const calendarMonth = () => new Intl.DateTimeFormat("sv-SE", {
210978
+ year: "numeric",
210979
+ month: "2-digit",
210980
+ timeZone: "Asia/Shanghai"
210981
+ }).format(/* @__PURE__ */ new Date());
210982
+ function ArkmePointsConsumption({ scope, revision }) {
210983
+ useArkmeLocale();
210984
+ const [month, setMonth] = (0, react$1.useState)(calendarMonth);
210985
+ const [monthCount, setMonthCount] = (0, react$1.useState)(24);
210986
+ const [year, currentMonth] = calendarMonth().split("-").map(Number);
210987
+ const latestMonth = year * 12 + currentMonth - 1;
210988
+ const months = Array.from({ length: Math.min(monthCount, latestMonth - 11) }, (_, offset) => {
210989
+ const index = latestMonth - offset;
210990
+ return `${String(Math.floor(index / 12)).padStart(4, "0")}-${String(index % 12 + 1).padStart(2, "0")}`;
210991
+ });
210992
+ const [retry, setRetry] = (0, react$1.useState)(0);
210993
+ const [state, setState] = (0, react$1.useState)();
210994
+ const request = (0, react$1.useRef)();
210995
+ const key = `${scope}:${month}:${revision}:${retry}`;
210996
+ const pending = (0, react$1.useRef)("");
210997
+ const currentKey = (0, react$1.useRef)(key);
210998
+ currentKey.current = key;
210999
+ const read = async (cursor = "") => {
211000
+ const pendingKey = `${key}:${cursor}`;
211001
+ if (pending.current === pendingKey && !request.current?.signal.aborted) return;
211002
+ pending.current = pendingKey;
211003
+ request.current?.abort();
211004
+ const controller = new AbortController();
211005
+ request.current = controller;
211006
+ if (!cursor) setState({
211007
+ key,
211008
+ status: "loading",
211009
+ items: [],
211010
+ total: "0",
211011
+ next: "",
211012
+ more: "idle"
211013
+ });
211014
+ else setState((previous) => previous?.key === key ? {
211015
+ ...previous,
211016
+ more: "loading"
211017
+ } : previous);
211018
+ try {
211019
+ const page = await callArkme("account.points.consumption", {
211020
+ expectedAccountScope: scope,
211021
+ month,
211022
+ ...cursor ? { beforeId: cursor } : {}
211023
+ }, controller.signal);
211024
+ if (controller.signal.aborted || currentKey.current !== key) return;
211025
+ if (page.accountScope !== scope || page.month !== month || cursor && page.nextBeforeId && BigInt(page.nextBeforeId) >= BigInt(cursor)) throw new Error("stale points page");
211026
+ setState((previous) => ({
211027
+ key,
211028
+ status: "ready",
211029
+ items: [...new Map([...cursor && previous?.key === key ? previous.items : [], ...page.items].map((item) => [item.requestUid, item])).values()],
211030
+ total: page.chargedPoints,
211031
+ next: page.nextBeforeId,
211032
+ more: "idle"
211033
+ }));
211034
+ } catch {
211035
+ if (controller.signal.aborted || currentKey.current !== key) return;
211036
+ setState((previous) => previous?.key === key ? {
211037
+ ...previous,
211038
+ ...cursor ? { more: "error" } : { status: "error" }
211039
+ } : previous);
211040
+ } finally {
211041
+ if (!controller.signal.aborted) pending.current = "";
211042
+ }
211043
+ };
211044
+ (0, react$1.useEffect)(() => {
211045
+ read();
211046
+ return () => request.current?.abort();
211047
+ }, [key]);
211048
+ const current = state?.key === key ? state : void 0;
211049
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211050
+ className: "arkme-usage-breakdown",
211051
+ "data-usage-detail": "points",
211052
+ children: [
211053
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211054
+ className: "arkme-points-toolbar",
211055
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
211056
+ "aria-label": tr$1("消费月份"),
211057
+ value: month,
211058
+ onChange: (event) => {
211059
+ const value = event.target.value;
211060
+ if (value === "earlier") setMonthCount((count) => count + 12);
211061
+ else if (months.includes(value)) setMonth(value);
211062
+ },
211063
+ children: [months.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
211064
+ value,
211065
+ children: new Intl.DateTimeFormat(arkmeIntlLocale(), {
211066
+ year: "numeric",
211067
+ month: "long",
211068
+ timeZone: "UTC"
211069
+ }).format(/* @__PURE__ */ new Date(`${value}-01T00:00:00Z`))
211070
+ }, value)), months.length < latestMonth - 11 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
211071
+ value: "earlier",
211072
+ children: tr$1("更早月份")
211073
+ })]
211074
+ }), current?.status === "ready" && current.items.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
211075
+ tr$1("该月消费"),
211076
+ " ",
211077
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatAiPoints(current.total) }),
211078
+ " ",
211079
+ tr$1("积分")
211080
+ ] })]
211081
+ }),
211082
+ (!current || current.status === "loading") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
211083
+ role: "status",
211084
+ children: tr$1("读取中…")
211085
+ }),
211086
+ current?.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
211087
+ role: "alert",
211088
+ children: [
211089
+ tr$1("暂时无法读取消费明细。"),
211090
+ " ",
211091
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211092
+ type: "button",
211093
+ onClick: () => setRetry((value) => value + 1),
211094
+ children: tr$1("重试")
211095
+ })
211096
+ ]
211097
+ }),
211098
+ current?.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
211099
+ current.items.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("该月暂无积分消费") }),
211100
+ groupPointsConsumption(current.items).map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: consumptionLabel(group.calls[0].businessCode) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: new Intl.DateTimeFormat(arkmeIntlLocale(), {
211101
+ month: "2-digit",
211102
+ day: "2-digit",
211103
+ hour: "2-digit",
211104
+ minute: "2-digit",
211105
+ timeZone: "Asia/Shanghai"
211106
+ }).format(group.calls[group.calls.length - 1].createdAt) })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
211107
+ className: "arkme-points-record-amount",
211108
+ children: [
211109
+ "−",
211110
+ formatAiPoints(group.chargedPoints),
211111
+ " ",
211112
+ tr$1("积分"),
211113
+ " ",
211114
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
211115
+ className: "arkme-points-chevron",
211116
+ "aria-hidden": true,
211117
+ children: "›"
211118
+ })
211119
+ ]
211120
+ })] }), group.calls.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PointsCallDetails, { item }, item.requestUid))] }, group.key)),
211121
+ current.more === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
211122
+ role: "alert",
211123
+ children: tr$1("加载失败,已有明细已保留。")
211124
+ }),
211125
+ current.next && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211126
+ type: "button",
211127
+ disabled: current.more === "loading",
211128
+ onClick: () => void read(current.next),
211129
+ children: tr$1(current.more === "loading" ? "读取中…" : current.more === "error" ? "重试" : "加载更多")
211130
+ })
211131
+ ] })
211132
+ ]
211133
+ });
211134
+ }
211135
+ function consumptionLabel(businessCode) {
211136
+ if (businessCode === "agent") return "Agent";
211137
+ if (businessCode === "arkme") return tr$1("DSH 对话");
211138
+ return tr$1("AI 调用");
211139
+ }
211140
+ function PointsCallDetails({ item }) {
211141
+ const granted = pointsUnits(item.grantedPoints) > 0n;
211142
+ const purchased = pointsUnits(item.purchasedPoints) > 0n;
211143
+ const funding = granted && purchased ? tr$1("(赠送 {v0} · 充值 {v1})", {
211144
+ v0: formatAiPoints(item.grantedPoints),
211145
+ v1: formatAiPoints(item.purchasedPoints)
211146
+ }) : granted ? tr$1("(赠送)") : purchased ? tr$1("(充值)") : "";
211147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211148
+ className: "arkme-points-call",
211149
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211150
+ className: "arkme-usage-call-title",
211151
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: item.model }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
211152
+ formatAiPoints(item.chargedPoints),
211153
+ " ",
211154
+ tr$1("积分"),
211155
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
211156
+ className: "arkme-points-funding",
211157
+ children: funding
211158
+ })
211159
+ ] })]
211160
+ }), item.services.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
211161
+ tr$1("模型调用"),
211162
+ " ",
211163
+ formatAiPoints(item.modelPoints),
211164
+ " ",
211165
+ tr$1("积分"),
211166
+ item.services.map((service) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
211167
+ " · ",
211168
+ tr$1(service.code === "web_search" || service.code === "bailian.web_search.turbo" ? "联网搜索" : "附加服务"),
211169
+ " ",
211170
+ formatAiPoints(service.chargedPoints),
211171
+ " ",
211172
+ tr$1("积分")
211173
+ ] }, service.code))
211174
+ ] }) })]
211175
+ });
211176
+ }
211177
+ //#endregion
210838
211178
  //#region src/client/arkme-billing.css?inline
210839
211179
  var arkme_billing_default = ".arkme-billing-modal-host {\n background: none;\n border: 0;\n width: 100%;\n max-width: none;\n height: 100%;\n max-height: none;\n margin: 0;\n padding: 0;\n position: fixed;\n inset: 0;\n}\n\n.arkme-billing-modal-host::backdrop {\n background: none;\n}\n\n.arkme-billing-backdrop {\n z-index: 120;\n backdrop-filter: blur(3px);\n background: #181b223d;\n place-items: center;\n padding: 28px;\n display: grid;\n position: fixed;\n inset: 0;\n}\n\n.arkme-billing-recharge-dialog, .arkme-billing-payment-dialog {\n color: #20232c;\n background: #fff;\n border: 1px solid #dedfe3;\n border-radius: 20px;\n width: min(620px, 100%);\n max-height: min(720px, 100vh - 56px);\n overflow-y: auto;\n box-shadow: 0 24px 72px #191c232e;\n}\n\n.arkme-billing-payment-dialog {\n width: min(420px, 100%);\n}\n\n.arkme-billing-dialog-header {\n border-bottom: 1px solid #ececef;\n justify-content: space-between;\n align-items: flex-start;\n gap: 18px;\n min-height: 78px;\n padding: 20px 22px 16px;\n display: flex;\n}\n\n.arkme-billing-dialog-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n line-height: 25px;\n}\n\n.arkme-billing-dialog-header p {\n overflow-wrap: anywhere;\n color: #8a8e96;\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-dialog-header > button {\n color: #777c85;\n width: 32px;\n height: 32px;\n font: inherit;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 9px;\n flex: none;\n place-items: center;\n font-size: 22px;\n display: grid;\n}\n\n.arkme-billing-dialog-header > button:hover {\n color: #20232c;\n background: #f3f3f5;\n}\n\n.arkme-billing-dialog-body {\n padding: 18px 22px 22px;\n}\n\n.arkme-billing-dialog-balance {\n border-bottom: 1px solid #ececef;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n column-gap: 12px;\n min-height: 48px;\n padding: 0 2px 16px;\n display: grid;\n}\n\n.arkme-billing-dialog-balance > span {\n color: #8a8e96;\n grid-column: 1;\n font-size: 11px;\n line-height: 16px;\n}\n\n.arkme-billing-dialog-balance > strong {\n grid-column: 1;\n font-size: 22px;\n font-weight: 600;\n line-height: 28px;\n}\n\n.arkme-billing-dialog-balance > button, .arkme-billing-error > button {\n color: #626772;\n height: 30px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 9px;\n grid-area: 1 / 2 / span 2;\n padding: 0 12px;\n font-size: 11px;\n}\n\n.arkme-billing-products-section, .arkme-billing-payment-section {\n padding-top: 17px;\n}\n\n.arkme-billing-products-section h3, .arkme-billing-payment-section h3 {\n color: #747984;\n margin: 0 0 11px;\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n\n.arkme-billing-product-grid {\n width: 100%;\n}\n\n.arkme-billing-product-grid > button {\n color: #20232c;\n min-width: 0;\n min-height: 62px;\n font: inherit;\n text-align: left;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 11px;\n align-content: center;\n gap: 4px;\n padding: 9px 11px;\n display: grid;\n}\n\n.arkme-billing-product-grid > button:hover {\n background: #f8f8f9;\n border-color: #cfd2d8;\n}\n\n.arkme-billing-product-grid > button.is-selected {\n border-color: #75839e;\n box-shadow: 0 0 0 1px #75839e;\n}\n\n.arkme-billing-product-grid > button > span {\n white-space: nowrap;\n text-overflow: ellipsis;\n font-size: 12px;\n font-weight: 500;\n line-height: 17px;\n overflow: hidden;\n}\n\n.arkme-billing-product-grid > button > strong {\n font-size: 14px;\n font-weight: 600;\n line-height: 19px;\n}\n\n.arkme-billing-payment-actions {\n flex-wrap: wrap;\n gap: 10px;\n display: flex;\n}\n\n.arkme-billing-payment-actions > button {\n color: #333842;\n min-width: 154px;\n height: 38px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 10px;\n justify-content: center;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.arkme-billing-payment-actions > button:hover {\n background: #f7f7f8;\n border-color: #cfd3da;\n}\n\n.arkme-billing-payment-actions > button:disabled, .arkme-billing-product-grid > button:disabled {\n opacity: .48;\n cursor: default;\n}\n\n.arkme-billing-platform-icon {\n flex: none;\n width: 18px;\n height: 18px;\n}\n\n.arkme-billing-platform-icon.is-alipay {\n color: #1677ff;\n}\n\n.arkme-billing-platform-icon.is-wechat {\n color: #07c160;\n}\n\n.arkme-billing-state {\n color: #858992;\n margin: 12px 0 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-error {\n color: #b54841;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n margin-top: 10px;\n font-size: 12px;\n line-height: 18px;\n display: flex;\n}\n\n.arkme-billing-error.is-purchase {\n justify-content: flex-start;\n}\n\n.arkme-billing-payment-content {\n text-align: center;\n justify-items: center;\n gap: 10px;\n padding: 28px 24px 18px;\n display: grid;\n}\n\n.arkme-billing-payment-content > .arkme-billing-platform-icon {\n width: 38px;\n height: 38px;\n margin-bottom: 4px;\n}\n\n.arkme-billing-payment-content > img {\n border-radius: 10px;\n width: 210px;\n height: 210px;\n}\n\n.arkme-billing-payment-content > strong {\n font-size: 14px;\n font-weight: 600;\n line-height: 21px;\n}\n\n.arkme-billing-payment-content > p {\n color: #858992;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-payment-content.is-paid > strong {\n color: #16794f;\n font-size: 18px;\n line-height: 25px;\n}\n\n.arkme-billing-payment-content.is-paid > .arkme-billing-error {\n justify-content: center;\n}\n\n.arkme-billing-payment-content.is-crediting > strong {\n color: #335f9e;\n}\n\n.arkme-billing-dialog-actions {\n flex-wrap: wrap;\n justify-content: center;\n gap: 9px;\n padding: 0 22px 20px;\n display: flex;\n}\n\n.arkme-billing-dialog-actions > button, .arkme-billing-primary-action {\n color: #3c424d;\n height: 34px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 9px;\n padding: 0 14px;\n font-size: 12px;\n}\n\n.arkme-billing-dialog-actions > .arkme-billing-primary-action, .arkme-billing-payment-content > .arkme-billing-primary-action {\n color: #fff;\n background: #20232d;\n border-color: #20232d;\n}\n";
210840
211180
  //#endregion
@@ -211033,18 +211373,14 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211033
211373
  function formatArkmeBillingPrice(priceMinor, _currency) {
211034
211374
  return `¥${(priceMinor / 100).toFixed(2)}`;
211035
211375
  }
211036
- function formatArkmeNanoCny(value) {
211037
- if (!/^(?:0|[1-9]\d*)$/.test(value)) return "—";
211038
- const roundedCents = (BigInt(value) + 5000000n) / 10000000n;
211039
- const whole = roundedCents / 100n;
211040
- const fraction = (roundedCents % 100n).toString().padStart(2, "0");
211041
- return `¥${whole.toLocaleString(arkmeIntlLocale())}.${fraction}`;
211376
+ function formatArkmePoints(value) {
211377
+ return `${formatAiPoints(nanoCnyToPoints(value))} ${tr$1("积分")}`;
211042
211378
  }
211043
211379
  function errorMessage$2(error) {
211044
211380
  return error instanceof Error && error.message.trim() !== "" ? error.message : String(error);
211045
211381
  }
211046
211382
  function ArkmeBalanceSettingsRowView(props) {
211047
- const description = props.quotaState.kind === "ready" ? formatArkmeNanoCny(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? "正在加载余额…" : "余额读取失败,点击重试";
211383
+ const description = props.quotaState.kind === "ready" ? formatArkmePoints(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? "正在加载积分…" : "积分读取失败,点击重试";
211048
211384
  const reservedNanoCny = props.quotaState.kind === "ready" ? props.quotaState.quota.reservedNanoCny : void 0;
211049
211385
  const showReserved = reservedNanoCny !== void 0 && /^(?:0|[1-9]\d*)$/.test(reservedNanoCny) && BigInt(reservedNanoCny) > 0n;
211050
211386
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -211053,7 +211389,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211053
211389
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211054
211390
  type: "button",
211055
211391
  className: "arkme-redesign-balance-main",
211056
- "aria-label": tr$1("账户余额 {v0}", { v0: description }),
211392
+ "aria-label": tr$1("AI 额度 {v0}", { v0: description }),
211057
211393
  onClick: props.onOpen,
211058
211394
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: description })
211059
211395
  }),
@@ -211062,21 +211398,21 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211062
211398
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
211063
211399
  className: "arkme-redesign-reserved-title",
211064
211400
  children: [
211065
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("预占余额") }),
211401
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("预占积分") }),
211066
211402
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
211067
211403
  className: "arkme-redesign-reserved-help",
211068
211404
  tabIndex: 0,
211069
- "aria-label": tr$1("预占余额说明"),
211405
+ "aria-label": tr$1("预占积分说明"),
211070
211406
  "aria-describedby": "arkme-reserved-balance-tooltip",
211071
211407
  children: "?"
211072
211408
  }),
211073
211409
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
211074
211410
  id: "arkme-reserved-balance-tooltip",
211075
211411
  role: "tooltip",
211076
- children: tr$1("当前运行的任务预先占用的余额,任务完成后将返还剩余余额。")
211412
+ children: tr$1("当前运行的任务预先占用的积分,任务完成后将返还未用积分。")
211077
211413
  })
211078
211414
  ]
211079
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: formatArkmeNanoCny(reservedNanoCny) })]
211415
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: formatArkmePoints(reservedNanoCny) })]
211080
211416
  }),
211081
211417
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211082
211418
  type: "button",
@@ -211123,11 +211459,11 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211123
211459
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
211124
211460
  role: "dialog",
211125
211461
  "aria-modal": "true",
211126
- "aria-label": tr$1("余额充值"),
211462
+ "aria-label": tr$1("积分充值"),
211127
211463
  className: "arkme-billing-recharge-dialog",
211128
211464
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
211129
211465
  className: "arkme-billing-dialog-header",
211130
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: tr$1("余额充值") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("充值后可在 DSH 会话中通过 Arkme 调用 AI 模型") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211466
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: tr$1("积分充值") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("APP 与 Arkme 3.0 共用积分,充值到账后即可使用") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211131
211467
  type: "button",
211132
211468
  "aria-label": tr$1("关闭充值弹窗"),
211133
211469
  onClick: props.onClose,
@@ -211139,8 +211475,8 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211139
211475
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211140
211476
  className: "arkme-billing-dialog-balance",
211141
211477
  children: [
211142
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("当前余额") }),
211143
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.quotaState.kind === "ready" ? formatArkmeNanoCny(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? tr$1("正在加载…") : "读取失败" }),
211478
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("可用积分") }),
211479
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.quotaState.kind === "ready" ? formatArkmePoints(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? tr$1("正在加载…") : "读取失败" }),
211144
211480
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211145
211481
  type: "button",
211146
211482
  onClick: props.onRefreshQuota,
@@ -211184,10 +211520,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211184
211520
  role: "radio",
211185
211521
  "aria-checked": product.productId === props.selectedProductId,
211186
211522
  className: product.productId === props.selectedProductId ? "is-selected" : "",
211187
- title: product.title,
211523
+ title: `${formatArkmePoints(product.creditNanoCny)} · ${formatArkmeBillingPrice(product.priceMinor, product.currency)}`,
211188
211524
  disabled: creating,
211189
211525
  onClick: () => props.onSelectProduct(product.productId),
211190
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: product.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatArkmeBillingPrice(product.priceMinor, product.currency) })]
211526
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatArkmePoints(product.creditNanoCny) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatArkmeBillingPrice(product.priceMinor, product.currency) })]
211191
211527
  }, product.productId))
211192
211528
  })
211193
211529
  ]
@@ -211230,7 +211566,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211230
211566
  const paymentAction = screen === "pending" ? props.order.paymentAction : void 0;
211231
211567
  const qrDataUrl = paymentAction?.type === "display_qr" ? billingQrDataUrl(paymentAction.qrContent) : "";
211232
211568
  const openUrl = paymentAction?.type === "open_url" ? paymentAction.url : "";
211233
- const paidAmount = formatArkmeBillingPrice(props.order.amountMinor, props.order.currency);
211569
+ const paidAmount = formatArkmePoints(props.order.creditNanoCny);
211234
211570
  const statusProblem = props.statusError !== "" && (screen === "pending" || screen === "crediting");
211235
211571
  const title = statusProblem ? "正在确认支付" : screen === "crediting" ? "支付已确认" : screen === "pending" ? "完成支付" : screen === "paid" ? "支付成功" : screen === "expired" ? "支付未完成" : "订单状态";
211236
211572
  (0, react$1.useEffect)(() => {
@@ -211315,19 +211651,19 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211315
211651
  " ",
211316
211652
  countdownText(props.order.expiresAtMillis - props.nowMillis)
211317
211653
  ] }),
211318
- !statusProblem && screen === "crediting" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("支付已确认,无需重复支付") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("余额到账中,到账后会自动刷新当前余额。") })] }),
211654
+ !statusProblem && screen === "crediting" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("支付已确认,无需重复支付") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("积分到账中,到账后会自动刷新可用积分。") })] }),
211319
211655
  screen === "paid" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
211320
211656
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
211321
211657
  paidAmount,
211322
211658
  " ",
211323
211659
  tr$1("已到账")
211324
211660
  ] }),
211325
- props.quotaState.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("已到账,正在刷新当前余额") }),
211326
- props.quotaState.kind === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [tr$1("当前余额已刷新:"), formatArkmeNanoCny(props.quotaState.quota.availableNanoCny)] }),
211661
+ props.quotaState.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("已到账,正在刷新可用积分") }),
211662
+ props.quotaState.kind === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [tr$1("可用积分已刷新:"), formatArkmePoints(props.quotaState.quota.availableNanoCny)] }),
211327
211663
  props.quotaState.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
211328
211664
  className: "arkme-billing-error",
211329
211665
  role: "alert",
211330
- children: [tr$1("余额暂未刷新:"), props.quotaState.message]
211666
+ children: [tr$1("积分暂未刷新:"), props.quotaState.message]
211331
211667
  })
211332
211668
  ] }),
211333
211669
  screen === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("支付凭据已过期,请重新生成。") }),
@@ -211352,7 +211688,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211352
211688
  screen === "paid" && props.quotaState.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211353
211689
  type: "button",
211354
211690
  onClick: props.onRefreshQuota,
211355
- children: tr$1("刷新余额")
211691
+ children: tr$1("刷新积分")
211356
211692
  }),
211357
211693
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211358
211694
  type: "button",
@@ -211393,7 +211729,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211393
211729
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
211394
211730
  ref,
211395
211731
  className: "arkme-billing-modal-host",
211396
- "aria-label": tr$1("AI 余额充值流程"),
211732
+ "aria-label": tr$1("AI 额度充值流程"),
211397
211733
  onCancel: (event) => {
211398
211734
  event.preventDefault();
211399
211735
  event.stopPropagation();
@@ -211402,7 +211738,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211402
211738
  children
211403
211739
  });
211404
211740
  }
211405
- function ArkmeBillingSettings({ active = true, renderTrigger, modal = false } = {}) {
211741
+ function ArkmeBillingSettings({ active = true, renderTrigger, modal = false, onCreditsChanged } = {}) {
211406
211742
  useArkmeLocale();
211407
211743
  const [open, setOpen] = (0, react$1.useState)(false);
211408
211744
  const [quotaState, setQuotaState] = (0, react$1.useState)({ kind: "loading" });
@@ -211511,7 +211847,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211511
211847
  setOrderStatusRetryable(false);
211512
211848
  setOrderStatusRetryInMillis(void 0);
211513
211849
  checkoutAttemptRef.current = checkoutAttemptAfterOrder(checkoutAttemptRef.current, latest.status);
211514
- if (latest.status === "paid") loadQuota();
211850
+ if (latest.status === "paid") {
211851
+ loadQuota();
211852
+ onCreditsChanged?.();
211853
+ }
211515
211854
  },
211516
211855
  onError: (error, retry) => {
211517
211856
  setOrderStatusError(errorMessage$2(error));
@@ -211525,7 +211864,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211525
211864
  });
211526
211865
  pollerRef.current = poller;
211527
211866
  poller.start(nextOrder.orderId, nextOrder.expiresAtMillis, nextOrder.pollIntervalMillis, nextOrder.status);
211528
- }, [loadQuota]);
211867
+ }, [loadQuota, onCreditsChanged]);
211529
211868
  const createPayment = (0, react$1.useCallback)(async (paymentMethod, forceNew = false) => {
211530
211869
  if (productsState.kind !== "ready") return;
211531
211870
  const product = productsState.products.find((item) => item.enabled && item.productId === selectedProductIdRef.current);
@@ -211543,8 +211882,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211543
211882
  setNowMillis(Date.now());
211544
211883
  activateBillingPaymentAction(nextOrder.paymentAction, openPaymentUrl);
211545
211884
  setOrder(nextOrder);
211546
- if (nextOrder.status === "paid") loadQuota();
211547
- else startPolling(nextOrder);
211885
+ if (nextOrder.status === "paid") {
211886
+ loadQuota();
211887
+ onCreditsChanged?.();
211888
+ } else startPolling(nextOrder);
211548
211889
  } catch (error) {
211549
211890
  setPurchaseError(errorMessage$2(error));
211550
211891
  } finally {
@@ -211552,6 +211893,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211552
211893
  }
211553
211894
  }, [
211554
211895
  loadQuota,
211896
+ onCreditsChanged,
211555
211897
  openPaymentUrl,
211556
211898
  productsState,
211557
211899
  startPolling
@@ -211677,29 +212019,6 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211677
212019
  }
211678
212020
  //#endregion
211679
212021
  //#region src/client/ArkmeUsageBreakdown.tsx
211680
- const count = (value) => new Intl.NumberFormat(arkmeIntlLocale()).format(value);
211681
- function time(value, timezone) {
211682
- return value > 0 ? new Intl.DateTimeFormat(arkmeIntlLocale(), {
211683
- month: "2-digit",
211684
- day: "2-digit",
211685
- hour: "2-digit",
211686
- minute: "2-digit",
211687
- second: "2-digit",
211688
- ...timezone ? { timeZone: timezone } : {}
211689
- }).format(value) : tr$1("未知");
211690
- }
211691
- function monthLabel$1(value) {
211692
- return new Intl.DateTimeFormat(arkmeIntlLocale(), {
211693
- year: "numeric",
211694
- month: "long",
211695
- timeZone: "UTC"
211696
- }).format(/* @__PURE__ */ new Date(`${value}-01T00:00:00Z`));
211697
- }
211698
- const cacheLabel = (value) => tr$1({
211699
- 2: "未命中",
211700
- 3: "已命中",
211701
- 4: "混合命中"
211702
- }[value] ?? "未知");
211703
212022
  function ArkmeStorageUsageBreakdown({ usage, formatBytes }) {
211704
212023
  useArkmeLocale();
211705
212024
  const labels = {
@@ -211730,293 +212049,6 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
211730
212049
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("占比按已用空间计算。文字、快记短语音和缩略图不计入存储空间。") })]
211731
212050
  });
211732
212051
  }
211733
- function Retry({ onRetry, more = false }) {
211734
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
211735
- role: "alert",
211736
- className: "arkme-usage-detail-error",
211737
- children: [
211738
- tr$1(more ? "明细加载失败,已有结果保留。" : "暂时无法读取用量明细。"),
211739
- " ",
211740
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211741
- type: "button",
211742
- onClick: onRetry,
211743
- children: tr$1("重试")
211744
- })
211745
- ]
211746
- });
211747
- }
211748
- function TokenNumbers({ tokens }) {
211749
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
211750
- className: "arkme-usage-detail-meta",
211751
- children: tr$1("输入 {input} · 输出 {output}", {
211752
- input: count(tokens.promptTokens),
211753
- output: count(tokens.completionTokens)
211754
- })
211755
- });
211756
- }
211757
- /** One controller per query; navigation/closing cancels reads and ignores late responses. */
211758
- function usePages(operation, scope, params, identity) {
211759
- const query = JSON.stringify(params), key = `${scope}:${operation}:${query}`;
211760
- const [revision, setRevision] = (0, react$1.useState)(0);
211761
- const [state, setState] = (0, react$1.useState)();
211762
- const request = (0, react$1.useRef)();
211763
- const [pageRequest, setPageRequest] = (0, react$1.useState)();
211764
- (0, react$1.useEffect)(() => {
211765
- const current = {
211766
- key,
211767
- controller: new AbortController(),
211768
- busy: true
211769
- };
211770
- request.current = current;
211771
- const cursor = pageRequest?.key === key ? pageRequest.cursor : "";
211772
- if (!cursor) setState({
211773
- key,
211774
- items: [],
211775
- nextCursor: "",
211776
- status: "loading",
211777
- more: "idle"
211778
- });
211779
- else setState((old) => old?.key === key ? {
211780
- ...old,
211781
- more: "loading"
211782
- } : old);
211783
- callArkme(operation, {
211784
- ...JSON.parse(query),
211785
- expectedAccountScope: scope,
211786
- cursor
211787
- }, current.controller.signal).then((page) => {
211788
- if (current.controller.signal.aborted || request.current !== current) return;
211789
- if (page.accountScope !== scope || page.nextCursor && page.nextCursor === cursor) throw new Error("stale usage page");
211790
- setState((old) => {
211791
- const combined = cursor && old?.key === key ? [...old.items, ...page.items] : page.items;
211792
- const items = identity ? [...new Map(combined.map((item) => [identity(item), item])).values()] : combined;
211793
- return {
211794
- key,
211795
- items,
211796
- nextCursor: page.nextCursor,
211797
- status: "ready",
211798
- more: "idle"
211799
- };
211800
- });
211801
- }).catch(() => {
211802
- if (current.controller.signal.aborted || request.current !== current) return;
211803
- setState((old) => cursor && old?.key === key ? {
211804
- ...old,
211805
- more: "error"
211806
- } : {
211807
- key,
211808
- items: [],
211809
- nextCursor: "",
211810
- status: "error",
211811
- more: "idle"
211812
- });
211813
- }).finally(() => {
211814
- current.busy = false;
211815
- });
211816
- return () => current.controller.abort();
211817
- }, [
211818
- key,
211819
- query,
211820
- scope,
211821
- operation,
211822
- revision,
211823
- pageRequest
211824
- ]);
211825
- const load = (cursor) => {
211826
- if (request.current?.key !== key || request.current.busy) return;
211827
- request.current.busy = true;
211828
- setPageRequest({
211829
- key,
211830
- cursor
211831
- });
211832
- setRevision((value) => value + 1);
211833
- };
211834
- return {
211835
- state: state?.key === key ? state : void 0,
211836
- load
211837
- };
211838
- }
211839
- const operationKey = (item) => `${item.operationUid}:${item.bizCode}`;
211840
- function CallDetails({ scope, monthKey, timezone, operation }) {
211841
- const { state, load } = usePages("account.usage.token.calls", scope, {
211842
- monthKey,
211843
- timezone,
211844
- operationUid: operation.operationUid,
211845
- bizCode: operation.bizCode
211846
- });
211847
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211848
- className: "arkme-usage-calls",
211849
- "aria-label": tr$1("逐次调用明细"),
211850
- children: [
211851
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TokenNumbers, { tokens: operation.tokens }),
211852
- operation.partialUsage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("部分用量字段不可用") }),
211853
- !state || state.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
211854
- role: "status",
211855
- children: tr$1("读取中…")
211856
- }) : state.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Retry, { onRetry: () => load("") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
211857
- state.items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("暂无逐次调用记录") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", { children: state.items.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
211858
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211859
- className: "arkme-usage-call-title",
211860
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: item.model || tr$1("未知模型") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", { children: time(item.occurredAtMs, timezone) })]
211861
- }),
211862
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [count(item.tokens.totalTokens), " Token"] }),
211863
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TokenNumbers, { tokens: item.tokens }),
211864
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
211865
- className: "arkme-usage-detail-meta",
211866
- children: [tr$1("缓存:{status} · 命中 {hit} · 未命中 {miss}", {
211867
- status: cacheLabel(item.cacheStatus),
211868
- hit: count(item.tokens.cachedTokens),
211869
- miss: count(item.tokens.cacheMissTokens)
211870
- }), item.tokens.cacheCreationInputTokens > 0 && tr$1(" · 缓存创建 {value}", { value: count(item.tokens.cacheCreationInputTokens) })]
211871
- }),
211872
- item.usageStatus !== 3 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("部分用量字段不可用") })
211873
- ] }, index)) }),
211874
- state.more === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Retry, {
211875
- more: true,
211876
- onRetry: () => load(state.nextCursor)
211877
- }),
211878
- state.nextCursor && state.more !== "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211879
- type: "button",
211880
- disabled: state.more === "loading",
211881
- onClick: () => load(state.nextCursor),
211882
- children: tr$1(state.more === "loading" ? "读取中…" : "加载更多调用")
211883
- })
211884
- ] })
211885
- ]
211886
- });
211887
- }
211888
- function OperationList({ scope, summary }) {
211889
- const { state, load } = usePages("account.usage.token.operations", scope, {
211890
- monthKey: summary.monthKey,
211891
- timezone: summary.timezone
211892
- }, operationKey);
211893
- const [selected, setSelected] = (0, react$1.useState)("");
211894
- if (!state || state.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
211895
- role: "status",
211896
- children: tr$1("读取中…")
211897
- });
211898
- if (state.status === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Retry, { onRetry: () => load("") });
211899
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
211900
- state.items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("该月份暂无 Token 用量记录") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
211901
- className: "arkme-token-operations",
211902
- children: state.items.map((item) => {
211903
- const key = operationKey(item), open = selected === key;
211904
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
211905
- className: "arkme-token-operation",
211906
- type: "button",
211907
- "aria-expanded": open,
211908
- "aria-label": tr$1("查看 {name} 的调用明细", { name: item.displayName }),
211909
- onClick: () => setSelected(open ? "" : key),
211910
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: item.displayName }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
211911
- time(item.occurredAtMs, summary.timezone),
211912
- " · ",
211913
- tr$1("{count} 次模型调用", { count: count(item.callCount) }),
211914
- " · ",
211915
- tr$1("缓存:{status}", { status: cacheLabel(item.cacheStatus) })
211916
- ] })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
211917
- count(item.tokens.totalTokens),
211918
- " Token ",
211919
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
211920
- "aria-hidden": true,
211921
- children: open ? "⌄" : "›"
211922
- })
211923
- ] })]
211924
- }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CallDetails, {
211925
- scope,
211926
- monthKey: summary.monthKey,
211927
- timezone: summary.timezone,
211928
- operation: item
211929
- }, key)] }, key);
211930
- })
211931
- }),
211932
- state.more === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Retry, {
211933
- more: true,
211934
- onRetry: () => load(state.nextCursor)
211935
- }),
211936
- state.nextCursor && state.more !== "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
211937
- type: "button",
211938
- disabled: state.more === "loading",
211939
- onClick: () => load(state.nextCursor),
211940
- children: tr$1(state.more === "loading" ? "读取中…" : "加载更多")
211941
- })
211942
- ] });
211943
- }
211944
- function ArkmeTokenUsageBreakdown({ scope, revision }) {
211945
- useArkmeLocale();
211946
- const [month, setMonth] = (0, react$1.useState)(""), [retry, setRetry] = (0, react$1.useState)(0);
211947
- const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai";
211948
- const key = `${scope}:${month}:${revision}:${retry}`;
211949
- const [state, setState] = (0, react$1.useState)();
211950
- const [months, setMonths] = (0, react$1.useState)([]);
211951
- (0, react$1.useEffect)(() => {
211952
- const controller = new AbortController();
211953
- callArkme("account.usage.token.summary", {
211954
- expectedAccountScope: scope,
211955
- monthKey: month,
211956
- timezone
211957
- }, controller.signal).then((value) => {
211958
- if (controller.signal.aborted) return;
211959
- if (value.accountScope !== scope || month && value.monthKey !== month) throw new Error("stale usage summary");
211960
- setMonths([.../* @__PURE__ */ new Set([value.monthKey, ...value.availableMonths])].sort().reverse());
211961
- setState({
211962
- key,
211963
- status: "ready",
211964
- value
211965
- });
211966
- }).catch(() => {
211967
- if (!controller.signal.aborted) setState({
211968
- key,
211969
- status: "error"
211970
- });
211971
- });
211972
- return () => controller.abort();
211973
- }, [
211974
- key,
211975
- scope,
211976
- month,
211977
- timezone
211978
- ]);
211979
- const ready = state?.key === key && state.status === "ready" ? state.value : void 0;
211980
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211981
- className: "arkme-usage-breakdown",
211982
- "data-usage-detail": "tokens",
211983
- children: [
211984
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211985
- className: "arkme-token-detail-toolbar",
211986
- children: [months.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
211987
- tr$1("月份"),
211988
- " ",
211989
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
211990
- "aria-label": tr$1("选择用量月份"),
211991
- value: month || ready?.monthKey || months[0],
211992
- onChange: (event) => setMonth(event.target.value),
211993
- children: months.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
211994
- value,
211995
- children: monthLabel$1(value)
211996
- }, value))
211997
- })
211998
- ] }), ready && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
211999
- tr$1("该月已记录"),
212000
- " ",
212001
- count(ready.tokens.totalTokens),
212002
- " Token"
212003
- ] })]
212004
- }),
212005
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("模型实际调用用量,不等同于月度额度扣减或充值消费。") }),
212006
- !state || state.key !== key ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
212007
- role: "status",
212008
- children: tr$1("读取中…")
212009
- }) : state.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Retry, { onRetry: () => setRetry((value) => value + 1) }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212010
- ready.partialUsage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("部分用量字段不可用") }),
212011
- ready.availableFromMs > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("明细可查询起点:{time}", { time: time(ready.availableFromMs, ready.timezone) }) }),
212012
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OperationList, {
212013
- scope,
212014
- summary: ready
212015
- }, key)
212016
- ] })
212017
- ]
212018
- });
212019
- }
212020
212052
  //#endregion
212021
212053
  //#region src/client/ArkmeAccountUsage.tsx
212022
212054
  function useUsage(operation, scope, revision) {
@@ -212052,15 +212084,6 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212052
212084
  return result?.scope === scope && result.revision === revision ? result.state : { status: "loading" };
212053
212085
  }
212054
212086
  const numberFormat = new Intl.NumberFormat(arkmeIntlLocale(), { maximumFractionDigits: 0 });
212055
- function formatCompactTokens(count) {
212056
- if (getArkmeLocale() === "en") return new Intl.NumberFormat("en-US", {
212057
- notation: "compact",
212058
- maximumFractionDigits: 1
212059
- }).format(count);
212060
- if (count < 1e4) return numberFormat.format(count);
212061
- if (count < 1e8) return `${count % 1e4 === 0 ? "" : "约 "}${numberFormat.format(count / 1e4)} 万`;
212062
- return `${count % 1e6 === 0 ? "" : "约 "}${new Intl.NumberFormat(arkmeIntlLocale(), { maximumFractionDigits: 2 }).format(count / 1e8)} 亿`;
212063
- }
212064
212087
  function formatUsageBytes(bytes) {
212065
212088
  if (bytes === 0) return "0 B";
212066
212089
  const index = Math.min(4, Math.floor(Math.log(bytes) / Math.log(1024)));
@@ -212107,10 +212130,18 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212107
212130
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${percent}%` } })
212108
212131
  });
212109
212132
  }
212110
- function Pending({ status }) {
212133
+ function Pending({ status, onRetry }) {
212111
212134
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
212112
212135
  className: "arkme-usage-muted",
212113
- children: status === "loading" ? tr$1("读取中…") : tr$1("暂时无法读取,请刷新重试")
212136
+ children: status === "loading" ? tr$1("读取中…") : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212137
+ tr$1("暂时无法读取"),
212138
+ " ",
212139
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
212140
+ type: "button",
212141
+ onClick: onRetry,
212142
+ children: tr$1("重试")
212143
+ })
212144
+ ] })
212114
212145
  });
212115
212146
  }
212116
212147
  function UsageSummaryRow({ label, kind, measurement, pending, description }) {
@@ -212145,7 +212176,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212145
212176
  /** Four compact rows; only authoritative measured quantities get progress values. */
212146
212177
  function ArkmeAccountUsage({ accountScope, onOpenDetails }) {
212147
212178
  useArkmeLocale();
212148
- const tokens = useUsage("account.usage.tokens", accountScope, 0);
212179
+ const points = useUsage("account.points.query", accountScope, 0);
212149
212180
  const storage = useUsage("account.usage.storage", accountScope, 0);
212150
212181
  const voice = useUsage("account.usage.voice", accountScope, 0);
212151
212182
  const status = (state) => state.status === "loading" ? "读取中…" : "暂不可用";
@@ -212161,20 +212192,16 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212161
212192
  className: "arkme-usage-summary-rows",
212162
212193
  "aria-live": "polite",
212163
212194
  children: [
212164
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSummaryRow, {
212165
- label: tr$1("月度 Token"),
212166
- kind: "tokens",
212167
- pending: status(tokens),
212168
- measurement: tokens.status === "ready" ? {
212169
- used: tokens.value.used,
212170
- total: tokens.value.used + tokens.value.remaining,
212171
- totalText: formatCompactTokens(tokens.value.used + tokens.value.remaining),
212172
- description: tr$1("本月已用 {v0} / 剩余 {v1} / 共 {v2} Token", {
212173
- v0: numberFormat.format(tokens.value.used),
212174
- v1: numberFormat.format(tokens.value.remaining),
212175
- v2: numberFormat.format(tokens.value.used + tokens.value.remaining)
212176
- })
212177
- } : void 0
212195
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
212196
+ className: "arkme-usage-summary-row",
212197
+ "data-usage-kind": "ai-points",
212198
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
212199
+ className: "arkme-usage-summary-label",
212200
+ children: tr$1("AI 额度")
212201
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
212202
+ className: "arkme-usage-summary-total",
212203
+ children: points.status === "ready" ? `${formatAiPoints(points.value.availablePoints)} ${tr$1("积分")}` : status(points)
212204
+ })]
212178
212205
  }),
212179
212206
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSummaryRow, {
212180
212207
  label: tr$1("云端存储"),
@@ -212217,27 +212244,27 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212217
212244
  });
212218
212245
  }
212219
212246
  function ArkmeAccountUsageDetails(props) {
212247
+ const [creditsRevision, setCreditsRevision] = (0, react$1.useState)(0);
212220
212248
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeBillingSettings, {
212249
+ active: false,
212221
212250
  modal: true,
212222
- renderTrigger: ({ quotaState, onOpen, onRefresh }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageDetailsContent, {
212251
+ onCreditsChanged: (0, react$1.useCallback)(() => setCreditsRevision((value) => value + 1), []),
212252
+ renderTrigger: ({ onOpen }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageDetailsContent, {
212223
212253
  ...props,
212224
- balance: quotaState,
212225
- onRecharge: onOpen,
212226
- onRefreshBalance: onRefresh
212254
+ creditsRevision,
212255
+ onRecharge: onOpen
212227
212256
  })
212228
212257
  }, props.accountScope);
212229
212258
  }
212230
- function UsageDetailsContent({ accountScope, onViewMembership, onRefreshMembership, balance, onRecharge, onRefreshBalance }) {
212259
+ function UsageDetailsContent({ accountScope, onViewMembership, onRecharge, creditsRevision }) {
212231
212260
  useArkmeLocale();
212232
212261
  const [revision, setRevision] = (0, react$1.useState)(0);
212233
- const [tokensOpen, setTokensOpen] = (0, react$1.useState)(false), [storageOpen, setStorageOpen] = (0, react$1.useState)(false);
212234
- const tokensId = (0, react$1.useId)(), storageId = (0, react$1.useId)();
212235
- const tokens = useUsage("account.usage.tokens", accountScope, revision);
212262
+ const [pointsOpen, setPointsOpen] = (0, react$1.useState)(false), [storageOpen, setStorageOpen] = (0, react$1.useState)(false);
212263
+ const pointsId = (0, react$1.useId)(), storageId = (0, react$1.useId)();
212264
+ const points = useUsage("account.points.query", accountScope, revision + creditsRevision);
212236
212265
  const storage = useUsage("account.usage.storage", accountScope, revision);
212237
212266
  const voice = useUsage("account.usage.voice", accountScope, revision);
212238
- const loading = tokens.status === "loading" || storage.status === "loading" || voice.status === "loading" || balance.kind === "loading";
212239
- const tokenTotal = tokens.status === "ready" ? tokens.value.used + tokens.value.remaining : 0;
212240
- const tokenLevel = tokens.status === "ready" ? usageLevel(tokens.value.used, tokenTotal) : "normal";
212267
+ const retry = () => setRevision((value) => value + 1);
212241
212268
  const storageLevel = storage.status === "ready" ? usageLevel(storage.value.usedBytes, storage.value.totalBytes) : "normal";
212242
212269
  const voiceTotal = voice.status === "ready" ? voice.value.usedSeconds + voice.value.remainingSeconds : 0;
212243
212270
  const voiceLevel = voice.status === "ready" ? usageLevel(voice.value.usedSeconds, voiceTotal) : "normal";
@@ -212245,105 +212272,70 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212245
212272
  className: "arkme-account-usage",
212246
212273
  "aria-label": tr$1("用量与额度"),
212247
212274
  children: [
212248
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("用量与额度") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
212249
- type: "button",
212250
- "aria-label": tr$1("刷新用量与额度"),
212251
- disabled: loading,
212252
- onClick: () => {
212253
- setRevision((value) => value + 1);
212254
- onRefreshMembership();
212255
- onRefreshBalance();
212256
- },
212257
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(m$5, {
212258
- size: 13,
212259
- "aria-hidden": true
212260
- }), loading ? tr$1("读取中") : tr$1("刷新")]
212261
- })] }),
212262
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
212263
- className: "arkme-usage-metric",
212264
- "data-usage-level": tokenLevel,
212265
- "aria-live": "polite",
212266
- children: [
212267
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
212268
- className: "arkme-usage-label",
212269
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("月度赠送 Token") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
212270
- className: "arkme-usage-label-actions",
212271
- children: [tokens.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1(tokenLevel === "exhausted" ? "暂无可用额度" : tokenLevel === "low" ? "余量较少" : "可用") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
212272
- type: "button",
212273
- "aria-expanded": tokensOpen,
212274
- "aria-controls": tokensId,
212275
- onClick: () => setTokensOpen((value) => !value),
212276
- children: [
212277
- tr$1(tokensOpen ? "收起 Token 明细" : "查看 Token 明细"),
212278
- " ",
212279
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
212280
- "aria-hidden": true,
212281
- children: tokensOpen ? "⌄" : "›"
212282
- })
212283
- ]
212284
- })]
212285
- })]
212286
- }),
212287
- tokens.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, { status: tokens.status }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212288
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
212289
- tr$1("已用"),
212290
- " ",
212291
- numberFormat.format(tokens.value.used),
212292
- " ",
212293
- tr$1("/ 剩余"),
212294
- " ",
212295
- numberFormat.format(tokens.value.remaining)
212296
- ] }),
212297
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBar, {
212298
- used: tokens.value.used,
212299
- total: tokenTotal,
212300
- label: tr$1("Token 额度已用比例")
212301
- }),
212302
- tokenLevel !== "normal" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
212303
- type: "button",
212304
- className: "arkme-usage-action",
212305
- onClick: onViewMembership,
212306
- children: tr$1("查看会员 Token 权益 ›")
212307
- })
212308
- ] }),
212309
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("月度额度与充值余额分开计量,不合并折算") }),
212310
- tokensOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
212311
- id: tokensId,
212312
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeTokenUsageBreakdown, {
212313
- scope: accountScope,
212314
- revision
212315
- }, accountScope)
212316
- })
212317
- ]
212318
- }),
212275
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("用量与额度") }) }),
212319
212276
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
212320
212277
  className: "arkme-usage-metric",
212321
- "data-usage-kind": "ai-balance",
212278
+ "data-usage-kind": "ai-points",
212322
212279
  "aria-live": "polite",
212323
212280
  children: [
212324
212281
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
212325
212282
  className: "arkme-usage-label",
212326
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("AI 充值余额") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
212283
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("AI 额度") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
212327
212284
  type: "button",
212328
212285
  className: "arkme-usage-action",
212329
212286
  onClick: onRecharge,
212330
212287
  children: tr$1("充值 ›")
212331
212288
  })]
212332
212289
  }),
212333
- balance.kind !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, { status: balance.kind }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
212334
- className: "arkme-usage-balance-amount",
212335
- children: [
212290
+ points.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, {
212291
+ status: points.status,
212292
+ onRetry: retry
212293
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
212294
+ className: "arkme-usage-points-balance",
212295
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
212336
212296
  tr$1("可用"),
212337
212297
  " ",
212338
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatArkmeNanoCny(balance.quota.availableNanoCny) })
212339
- ]
212340
- }), BigInt(balance.quota.reservedNanoCny) > 0n && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
212341
- tr$1("任务预占"),
212298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatAiPoints(points.value.availablePoints) }),
212299
+ " ",
212300
+ tr$1("积分")
212301
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
212302
+ className: "arkme-usage-points-sources",
212303
+ children: tr$1("赠送 {v0} · 充值 {v1}", {
212304
+ v0: formatAiPoints(points.value.grantedPoints),
212305
+ v1: formatAiPoints(points.value.purchasedPoints)
212306
+ })
212307
+ })]
212308
+ }), points.value.grants.some((grant) => grant.expiresAt > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
212309
+ tr$1("赠送积分到期时间"),
212342
212310
  " ",
212343
- formatArkmeNanoCny(balance.quota.reservedNanoCny),
212344
- tr$1(",结算后释放未用部分")
212311
+ new Intl.DateTimeFormat(arkmeIntlLocale(), {
212312
+ month: "numeric",
212313
+ day: "numeric",
212314
+ timeZone: "Asia/Shanghai"
212315
+ }).format(Math.min(...points.value.grants.filter((grant) => grant.expiresAt > 0).map((grant) => grant.expiresAt - 1)))
212345
212316
  ] })] }),
212346
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("用于按余额计费的 AI 功能,不代表月度 Token 用尽后自动接续") })
212317
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
212318
+ type: "button",
212319
+ className: "arkme-points-disclosure",
212320
+ "aria-expanded": pointsOpen,
212321
+ "aria-controls": pointsId,
212322
+ onClick: () => setPointsOpen((value) => !value),
212323
+ children: [
212324
+ tr$1("消费记录"),
212325
+ " ",
212326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
212327
+ "aria-hidden": true,
212328
+ children: pointsOpen ? "⌄" : "›"
212329
+ })
212330
+ ]
212331
+ }),
212332
+ pointsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
212333
+ id: pointsId,
212334
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmePointsConsumption, {
212335
+ scope: accountScope,
212336
+ revision: revision + creditsRevision
212337
+ }, accountScope)
212338
+ })
212347
212339
  ]
212348
212340
  }),
212349
212341
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -212371,7 +212363,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212371
212363
  })]
212372
212364
  })]
212373
212365
  }),
212374
- storage.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, { status: storage.status }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212366
+ storage.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, {
212367
+ status: storage.status,
212368
+ onRetry: retry
212369
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212375
212370
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
212376
212371
  tr$1("已用"),
212377
212372
  " ",
@@ -212398,7 +212393,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212398
212393
  children: storage.status === "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeStorageUsageBreakdown, {
212399
212394
  usage: storage.value,
212400
212395
  formatBytes: formatUsageBytes
212401
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, { status: storage.status })
212396
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, {
212397
+ status: storage.status,
212398
+ onRetry: retry
212399
+ })
212402
212400
  })
212403
212401
  ]
212404
212402
  }),
@@ -212412,7 +212410,10 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
212412
212410
  className: "arkme-usage-label",
212413
212411
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr$1("语音转文字") }), voice.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: voiceLevel === "exhausted" ? "本月额度已用尽" : voiceLevel === "low" ? "余量较少" : tr$1("每月 {v0}", { v0: formatUsageSeconds(voiceTotal) }) })]
212414
212412
  }),
212415
- voice.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, { status: voice.status }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212413
+ voice.status !== "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pending, {
212414
+ status: voice.status,
212415
+ onRetry: retry
212416
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212416
212417
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
212417
212418
  tr$1("已用"),
212418
212419
  " ",
@@ -216163,7 +216164,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
216163
216164
  return nextRect ? nextRect.top - (currentRect.top + currentRect.height) : previousRect ? currentRect.top - (previousRect.top + previousRect.height) : 0;
216164
216165
  }
216165
216166
  const ID_PREFIX = "Sortable";
216166
- const Context = /*#__PURE__*/ react.default.createContext({
216167
+ const Context$1 = /*#__PURE__*/ react.default.createContext({
216167
216168
  activeIndex: -1,
216168
216169
  containerId: ID_PREFIX,
216169
216170
  disableTransforms: false,
@@ -216223,7 +216224,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
216223
216224
  useDragOverlay,
216224
216225
  strategy
216225
216226
  ]);
216226
- return react.default.createElement(Context.Provider, { value: contextValue }, children);
216227
+ return react.default.createElement(Context$1.Provider, { value: contextValue }, children);
216227
216228
  }
216228
216229
  const defaultNewIndexGetter = (_ref) => {
216229
216230
  let { id, items, activeIndex, overIndex } = _ref;
@@ -216279,7 +216280,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
216279
216280
  }
216280
216281
  function useSortable(_ref) {
216281
216282
  let { animateLayoutChanges = defaultAnimateLayoutChanges, attributes: userDefinedAttributes, disabled: localDisabled, data: customData, getNewIndex = defaultNewIndexGetter, id, strategy: localStrategy, resizeObserverConfig, transition = defaultTransition } = _ref;
216282
- const { items, containerId, activeIndex, disabled: globalDisabled, disableTransforms, sortedRects, overIndex, useDragOverlay, strategy: globalStrategy } = (0, react.useContext)(Context);
216283
+ const { items, containerId, activeIndex, disabled: globalDisabled, disableTransforms, sortedRects, overIndex, useDragOverlay, strategy: globalStrategy } = (0, react.useContext)(Context$1);
216283
216284
  const disabled = normalizeLocalDisabled(localDisabled, globalDisabled);
216284
216285
  const index = items.indexOf(id);
216285
216286
  const data = (0, react.useMemo)(() => ({
@@ -222811,6 +222812,243 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
222811
222812
  });
222812
222813
  }
222813
222814
  //#endregion
222815
+ //#region src/client/interwoven-read-receipt-store.ts
222816
+ /** One private-conversation/account lifetime. Visible rows only; no read acknowledgements. */
222817
+ var InterwovenReadReceiptStore = class {
222818
+ load;
222819
+ targets = /* @__PURE__ */ new Map();
222820
+ entries = /* @__PURE__ */ new Map();
222821
+ listeners = /* @__PURE__ */ new Set();
222822
+ timer;
222823
+ controller;
222824
+ foreground = true;
222825
+ disposed = false;
222826
+ generation = 0;
222827
+ failures = 0;
222828
+ constructor(sourceRef, load = (momentRefs, signal) => callArkme("source.interwoven-read-receipts", {
222829
+ sourceRef,
222830
+ momentRefs
222831
+ }, signal)) {
222832
+ this.load = load;
222833
+ }
222834
+ subscribe = (listener) => {
222835
+ this.listeners.add(listener);
222836
+ return () => {
222837
+ this.listeners.delete(listener);
222838
+ };
222839
+ };
222840
+ get = (ref) => this.entries.get(ref);
222841
+ register(momentId, momentRef) {
222842
+ const key = Symbol();
222843
+ this.targets.set(key, {
222844
+ momentId,
222845
+ momentRef,
222846
+ visible: false
222847
+ });
222848
+ return {
222849
+ setVisible: (visible) => {
222850
+ const target = this.targets.get(key);
222851
+ if (!target || target.visible === visible) return;
222852
+ target.visible = visible;
222853
+ if (visible) this.refresh();
222854
+ else if (!this.visible().length) this.cancel();
222855
+ },
222856
+ dispose: () => {
222857
+ this.targets.delete(key);
222858
+ if (![...this.targets.values()].some((item) => item.momentRef === momentRef)) this.entries.delete(momentRef);
222859
+ if (!this.visible().length) this.cancel();
222860
+ }
222861
+ };
222862
+ }
222863
+ visible() {
222864
+ return [...new Map([...this.targets.values()].filter((item) => item.visible).map((item) => [item.momentRef, item])).values()];
222865
+ }
222866
+ cancel() {
222867
+ this.generation++;
222868
+ clearTimeout(this.timer);
222869
+ this.timer = void 0;
222870
+ this.controller?.abort();
222871
+ this.controller = void 0;
222872
+ }
222873
+ schedule(delay) {
222874
+ clearTimeout(this.timer);
222875
+ if (!this.disposed && this.foreground && this.visible().length) this.timer = setTimeout(() => {
222876
+ this.flush();
222877
+ }, delay);
222878
+ }
222879
+ refresh = () => {
222880
+ this.cancel();
222881
+ this.schedule(100);
222882
+ };
222883
+ activate() {
222884
+ this.disposed = false;
222885
+ this.refresh();
222886
+ }
222887
+ setForeground(value) {
222888
+ if (this.foreground === value) return;
222889
+ this.foreground = value;
222890
+ this.cancel();
222891
+ if (value) this.schedule(0);
222892
+ }
222893
+ dispose() {
222894
+ this.disposed = true;
222895
+ this.cancel();
222896
+ this.targets.clear();
222897
+ this.entries.clear();
222898
+ this.listeners.clear();
222899
+ }
222900
+ async flush() {
222901
+ if (this.disposed || !this.foreground) return;
222902
+ this.timer = void 0;
222903
+ const targets = this.visible();
222904
+ const generation = this.generation;
222905
+ const controller = new AbortController();
222906
+ this.controller = controller;
222907
+ let failed = false;
222908
+ for (let start = 0; start < targets.length; start += 20) {
222909
+ if (controller.signal.aborted) return;
222910
+ const batch = targets.slice(start, start + 20);
222911
+ try {
222912
+ const result = await this.load(batch.map((item) => item.momentRef), controller.signal);
222913
+ if (controller.signal.aborted || generation !== this.generation || this.disposed) return;
222914
+ for (const target of batch) {
222915
+ const matching = result.items.filter((item) => item.momentId === target.momentId);
222916
+ const item = matching.length === 1 ? matching[0] : void 0;
222917
+ if (item && [
222918
+ "read",
222919
+ "unread",
222920
+ "unknown"
222921
+ ].includes(item.status)) this.entries.set(target.momentRef, item);
222922
+ else this.entries.delete(target.momentRef);
222923
+ }
222924
+ } catch {
222925
+ if (controller.signal.aborted) return;
222926
+ failed = true;
222927
+ for (const target of batch) this.entries.delete(target.momentRef);
222928
+ }
222929
+ for (const listener of this.listeners) listener();
222930
+ }
222931
+ if (generation !== this.generation || this.disposed) return;
222932
+ this.controller = void 0;
222933
+ this.failures = failed ? this.failures + 1 : 0;
222934
+ if (this.visible().some((target) => this.entries.get(target.momentRef)?.status !== "read")) this.schedule(failed ? Math.min(6e4, 15e3 * 2 ** this.failures) : this.visible().every((target) => this.entries.get(target.momentRef)?.status === "unknown") ? 6e4 : 15e3);
222935
+ }
222936
+ };
222937
+ //#endregion
222938
+ //#region src/client/ArkmeInterwovenReadReceipt.tsx
222939
+ const Context = (0, react$1.createContext)(void 0);
222940
+ const noopSubscribe = () => () => {};
222941
+ function ArkmeInterwovenReadProvider({ sourceRef, scope, enabled, children }) {
222942
+ const store = (0, react$1.useMemo)(() => enabled ? new InterwovenReadReceiptStore(sourceRef) : void 0, [
222943
+ sourceRef,
222944
+ scope,
222945
+ enabled
222946
+ ]);
222947
+ (0, react$1.useEffect)(() => {
222948
+ if (!store || typeof document === "undefined" || typeof window === "undefined") return;
222949
+ store.activate();
222950
+ const syncVisibility = () => {
222951
+ store.setForeground(document.visibilityState !== "hidden");
222952
+ };
222953
+ syncVisibility();
222954
+ const release = arkmeInterwovenInvalidation.subscribe(store.refresh);
222955
+ document.addEventListener("visibilitychange", syncVisibility);
222956
+ window.addEventListener("focus", store.refresh);
222957
+ return () => {
222958
+ release();
222959
+ store.dispose();
222960
+ document.removeEventListener("visibilitychange", syncVisibility);
222961
+ window.removeEventListener("focus", store.refresh);
222962
+ };
222963
+ }, [store]);
222964
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Context.Provider, {
222965
+ value: store,
222966
+ children
222967
+ });
222968
+ }
222969
+ function ArkmeInterwovenReadReceipt({ moment }) {
222970
+ useArkmeLocale();
222971
+ const store = (0, react$1.useContext)(Context);
222972
+ const ref = (0, react$1.useRef)(null);
222973
+ const receipt = (0, react$1.useSyncExternalStore)(store?.subscribe ?? noopSubscribe, () => store?.get(moment.momentRef), () => void 0);
222974
+ const [anchor, setAnchor] = (0, react$1.useState)();
222975
+ const close = (0, react$1.useCallback)(() => {
222976
+ setAnchor(void 0);
222977
+ }, []);
222978
+ const id = (0, react$1.useId)();
222979
+ (0, react$1.useEffect)(() => {
222980
+ if (!store || !ref.current) return;
222981
+ const registration = store.register(moment.momentId, moment.momentRef);
222982
+ const observer = typeof IntersectionObserver === "undefined" ? void 0 : new IntersectionObserver((entries) => {
222983
+ registration.setVisible(entries.some((entry) => entry.isIntersecting));
222984
+ }, { rootMargin: "80px" });
222985
+ if (observer) observer.observe(ref.current);
222986
+ else registration.setVisible(true);
222987
+ return () => {
222988
+ observer?.disconnect();
222989
+ registration.dispose();
222990
+ };
222991
+ }, [
222992
+ store,
222993
+ moment.momentId,
222994
+ moment.momentRef
222995
+ ]);
222996
+ if (!store) return null;
222997
+ const expectedReader = moment.senderIsMe ? "peer" : "self";
222998
+ const status = receipt?.reader === expectedReader ? receipt.status : "unknown";
222999
+ const label = status === "unknown" ? tr$1("群内原消息的已读状态暂不可用") : moment.senderIsMe ? status === "read" ? tr$1("对方已阅读群内原消息") : tr$1("对方尚未阅读群内原消息") : status === "read" ? tr$1("你已阅读群内原消息") : tr$1("你尚未阅读群内原消息");
223000
+ const timestamp = status === "read" && receipt?.readAtMillis && receipt.readAtMillis > 0 ? new Intl.DateTimeFormat(arkmeIntlLocale(), {
223001
+ month: "2-digit",
223002
+ day: "2-digit",
223003
+ hour: "2-digit",
223004
+ minute: "2-digit",
223005
+ hour12: false
223006
+ }).format(receipt.readAtMillis) : "";
223007
+ const text = timestamp ? `${label} · ${timestamp}` : label;
223008
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
223009
+ ref,
223010
+ "data-arkme-interwoven-receipt": status,
223011
+ "aria-label": text,
223012
+ "aria-describedby": anchor ? id : void 0,
223013
+ tabIndex: 0,
223014
+ onMouseEnter: () => {
223015
+ const button = ref.current?.closest("button");
223016
+ if (button) setAnchor(button);
223017
+ },
223018
+ onMouseLeave: close,
223019
+ onFocus: () => {
223020
+ const button = ref.current?.closest("button");
223021
+ if (button) setAnchor(button);
223022
+ },
223023
+ onBlur: close,
223024
+ style: {
223025
+ display: "inline-grid",
223026
+ placeItems: "center",
223027
+ width: 14,
223028
+ height: 18,
223029
+ flex: "none"
223030
+ },
223031
+ children: [status === "read" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeReadReceiptIcon, {
223032
+ checked: true,
223033
+ style: { opacity: .4 }
223034
+ }) : status === "unread" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
223035
+ "aria-hidden": true,
223036
+ style: {
223037
+ width: 6,
223038
+ height: 6,
223039
+ borderRadius: "50%",
223040
+ background: arkmeTheme.info,
223041
+ opacity: .65
223042
+ }
223043
+ }) : null, anchor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeCalendarDateTooltip, {
223044
+ anchor,
223045
+ id,
223046
+ text,
223047
+ onClose: close
223048
+ })]
223049
+ });
223050
+ }
223051
+ //#endregion
222814
223052
  //#region src/client/interwoven-moments.tsx
222815
223053
  /** Pure deterministic merge; each authority keeps its own identity and duplicate policy. */
222816
223054
  function mergeConversationRows(messages, moments, memberEvents = []) {
@@ -222974,6 +223212,21 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
222974
223212
  whiteSpace: "nowrap",
222975
223213
  textAlign: "left"
222976
223214
  },
223215
+ originLabel: {
223216
+ minWidth: 0,
223217
+ maxWidth: "min(9em, 24%)",
223218
+ flex: "0 0 auto",
223219
+ boxSizing: "border-box",
223220
+ overflow: "hidden",
223221
+ textOverflow: "ellipsis",
223222
+ whiteSpace: "nowrap",
223223
+ padding: "0 5px",
223224
+ borderRadius: 4,
223225
+ fontSize: 11,
223226
+ lineHeight: "18px",
223227
+ background: "var(--dsw-alias-bg-layer-2, #f3f4f6)",
223228
+ color: "var(--dsw-alias-label-tertiary, #9097a1)"
223229
+ },
222977
223230
  chevron: {
222978
223231
  width: 15,
222979
223232
  height: 15,
@@ -223101,58 +223354,124 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
223101
223354
  })
223102
223355
  });
223103
223356
  }
223357
+ /** Inline identity only; keep the row distinct from a regular chat bubble. */
223358
+ function InterwovenSenderAvatar({ avatarRef, name }) {
223359
+ const src = useArkmeAvatarImage(avatarRef);
223360
+ const [failedSrc, setFailedSrc] = (0, react$1.useState)();
223361
+ const initial = Array.from(name.trim())[0] || "?";
223362
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
223363
+ "data-arkme-interwoven-avatar": true,
223364
+ "aria-hidden": true,
223365
+ style: {
223366
+ ...styles$12.avatar,
223367
+ width: 20,
223368
+ height: 20,
223369
+ minWidth: 20,
223370
+ flex: "none",
223371
+ fontSize: 11,
223372
+ lineHeight: "20px",
223373
+ fontWeight: 500,
223374
+ color: "var(--dsw-alias-label-secondary, #737982)"
223375
+ },
223376
+ children: src && src !== failedSrc ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
223377
+ src,
223378
+ alt: "",
223379
+ draggable: false,
223380
+ style: styles$12.avatarImage,
223381
+ onError: () => {
223382
+ setFailedSrc(src);
223383
+ }
223384
+ }, src) : initial
223385
+ });
223386
+ }
223104
223387
  function ArkmeInterwovenMentionCard({ moment, rowId, onOpen, highlighted = false }) {
223105
- const summary = moment.summary.trim() || "群聊提及";
223388
+ useArkmeLocale();
223389
+ const [hintAnchor, setHintAnchor] = (0, react$1.useState)();
223390
+ const hintId = (0, react$1.useId)();
223391
+ const closeHint = (0, react$1.useCallback)(() => {
223392
+ setHintAnchor(void 0);
223393
+ }, []);
223394
+ (0, react$1.useEffect)(closeHint, [moment.momentRef, closeHint]);
223395
+ const summary = moment.summary.trim() || tr$1("群聊提及");
223106
223396
  const accessible = `${moment.groupName},${moment.senderName}:${summary}`;
223107
223397
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
223108
223398
  style: styles$12.momentRow,
223109
223399
  "data-arkme-interwoven-card": moment.momentId,
223110
223400
  "data-arkme-conversation-row": rowId,
223111
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
223112
- style: styles$12.momentTime,
223113
- dateTime: new Date(moment.occurredAtMillis).toISOString(),
223114
- children: interwovenTimeLabel(moment.occurredAtMillis)
223115
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
223116
- type: "button",
223117
- style: {
223118
- ...styles$12.card,
223119
- ...highlighted ? {
223120
- background: "var(--dsw-alias-bg-active, #eef0fa)",
223121
- outline: "1px solid var(--dsw-alias-state-business-primary, #a5acff)"
223122
- } : {}
223123
- },
223124
- "aria-label": tr$1("打开快记详情:{v0}", { v0: accessible }),
223125
- title: accessible,
223126
- onFocus: (event) => {
223127
- event.currentTarget.style.boxShadow = "0 0 0 2px var(--dsw-alias-state-business-primary, #3964fe)";
223128
- },
223129
- onBlur: (event) => {
223130
- event.currentTarget.style.boxShadow = "none";
223131
- },
223132
- onClick: () => {
223133
- onOpen(moment);
223134
- },
223135
- children: [
223136
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OpaqueAvatar, { ...moment.senderAvatarRef === void 0 ? {} : { avatarRef: moment.senderAvatarRef } }),
223137
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
223138
- style: styles$12.cardText,
223139
- children: accessible
223140
- }),
223141
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
223142
- viewBox: "0 0 16 16",
223143
- style: styles$12.chevron,
223144
- "aria-hidden": true,
223145
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
223146
- d: "m6 3 5 5-5 5",
223147
- fill: "none",
223148
- stroke: "currentColor",
223149
- strokeWidth: "1.8",
223150
- strokeLinecap: "round",
223151
- strokeLinejoin: "round"
223401
+ children: [
223402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
223403
+ style: styles$12.momentTime,
223404
+ dateTime: new Date(moment.occurredAtMillis).toISOString(),
223405
+ children: interwovenTimeLabel(moment.occurredAtMillis)
223406
+ }),
223407
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
223408
+ type: "button",
223409
+ "data-arkme-interwoven-summary": true,
223410
+ style: {
223411
+ ...styles$12.card,
223412
+ ...highlighted ? {
223413
+ background: "var(--dsw-alias-bg-active, #eef0fa)",
223414
+ outline: "1px solid var(--dsw-alias-state-business-primary, #a5acff)"
223415
+ } : {}
223416
+ },
223417
+ "aria-label": tr$1("打开快记详情:{v0}", { v0: accessible }),
223418
+ "aria-describedby": hintAnchor ? hintId : void 0,
223419
+ onMouseOver: (event) => {
223420
+ if (event.target.closest?.("[data-arkme-interwoven-receipt]")) closeHint();
223421
+ else setHintAnchor(event.currentTarget);
223422
+ },
223423
+ onMouseLeave: closeHint,
223424
+ onFocus: (event) => {
223425
+ event.currentTarget.style.boxShadow = "0 0 0 2px var(--dsw-alias-state-business-primary, #3964fe)";
223426
+ if (event.target === event.currentTarget) setHintAnchor(event.currentTarget);
223427
+ else closeHint();
223428
+ },
223429
+ onBlur: (event) => {
223430
+ event.currentTarget.style.boxShadow = "none";
223431
+ closeHint();
223432
+ },
223433
+ onClick: () => {
223434
+ closeHint();
223435
+ onOpen(moment);
223436
+ },
223437
+ children: [
223438
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InterwovenSenderAvatar, {
223439
+ avatarRef: moment.senderAvatarRef,
223440
+ name: moment.senderName
223441
+ }, moment.senderAvatarRef || moment.senderName),
223442
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
223443
+ "data-arkme-interwoven-content": true,
223444
+ style: styles$12.cardText,
223445
+ children: summary
223446
+ }),
223447
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
223448
+ "data-arkme-interwoven-origin": true,
223449
+ style: styles$12.originLabel,
223450
+ children: moment.groupName || tr$1("群聊")
223451
+ }),
223452
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeInterwovenReadReceipt, { moment }),
223453
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
223454
+ viewBox: "0 0 16 16",
223455
+ style: styles$12.chevron,
223456
+ "aria-hidden": true,
223457
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
223458
+ d: "m6 3 5 5-5 5",
223459
+ fill: "none",
223460
+ stroke: "currentColor",
223461
+ strokeWidth: "1.8",
223462
+ strokeLinecap: "round",
223463
+ strokeLinejoin: "round"
223464
+ })
223152
223465
  })
223153
- })
223154
- ]
223155
- })]
223466
+ ]
223467
+ }),
223468
+ hintAnchor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeCalendarDateTooltip, {
223469
+ anchor: hintAnchor,
223470
+ id: hintId,
223471
+ text: accessible,
223472
+ onClose: closeHint
223473
+ })
223474
+ ]
223156
223475
  });
223157
223476
  }
223158
223477
  function ArkmeInterwovenDetailAside({ state, relatedView = "source-detail", relatedState = { kind: "idle" }, relatedDetailState = { kind: "idle" }, onClose, onRetry, onOpenGroup, onOpenRelated, onSelectRelated, onBackRelated, onRetryRelated, onRetryRelatedDetail, sourceRef, shareWebsite }) {
@@ -224888,6 +225207,81 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
224888
225207
  return typeof document === "undefined" ? detail : (0, react_dom$1.createPortal)(detail, document.body);
224889
225208
  }
224890
225209
  //#endregion
225210
+ //#region src/client/use-personal-extension-parents.ts
225211
+ const EMPTY_PARENTS = /* @__PURE__ */ new Map();
225212
+ /** Topic projections can omit a cross-topic edge. Enrich visible rows, not the whole history. */
225213
+ function usePersonalExtensionParents(scope, sourceRef, items) {
225214
+ const [snapshot, setSnapshot] = (0, react$1.useState)({
225215
+ scope: "",
225216
+ parents: /* @__PURE__ */ new Map()
225217
+ });
225218
+ const completed = (0, react$1.useRef)({
225219
+ scope: "",
225220
+ keys: /* @__PURE__ */ new Set()
225221
+ });
225222
+ if (completed.current.scope !== scope) completed.current = {
225223
+ scope,
225224
+ keys: /* @__PURE__ */ new Set()
225225
+ };
225226
+ (0, react$1.useEffect)(() => {
225227
+ if (!sourceRef || typeof IntersectionObserver === "undefined") return;
225228
+ const controller = new AbortController();
225229
+ const done = completed.current.keys;
225230
+ const byUid = new Map(items.filter((item) => item.messageActionRef && item.extensionParent === void 0 && item.status === 1 && !item.itemUid.includes("-operation:")).map((item) => [item.itemUid, item]));
225231
+ const queued = /* @__PURE__ */ new Set();
225232
+ const queue = [];
225233
+ let active = 0;
225234
+ const keyOf = (item) => `${item.itemUid}:${item.recordVersion ?? item.version ?? 0}`;
225235
+ const drain = () => {
225236
+ while (!controller.signal.aborted && active < 2 && queue.length > 0) {
225237
+ const item = queue.shift();
225238
+ active += 1;
225239
+ callArkme("source.message-extension.parent", {
225240
+ sourceRef,
225241
+ messageActionRef: item.messageActionRef
225242
+ }, controller.signal).then((result) => {
225243
+ if (controller.signal.aborted || result.recordUid !== item.itemUid) return;
225244
+ done.add(keyOf(item));
225245
+ setSnapshot((current) => {
225246
+ if (result.extensionParent === void 0 && !current.parents.has(item.itemUid)) return current;
225247
+ const parents = new Map(current.scope === scope ? current.parents : []);
225248
+ if (result.extensionParent === void 0) parents.delete(item.itemUid);
225249
+ else parents.set(item.itemUid, result.extensionParent);
225250
+ return {
225251
+ scope,
225252
+ parents
225253
+ };
225254
+ });
225255
+ }).catch(() => {}).finally(() => {
225256
+ active -= 1;
225257
+ drain();
225258
+ });
225259
+ }
225260
+ };
225261
+ const observer = new IntersectionObserver((entries) => {
225262
+ for (const entry of entries) {
225263
+ if (!entry.isIntersecting) continue;
225264
+ const uid = entry.target.getAttribute("data-arkme-message-item-uid") ?? "";
225265
+ const item = byUid.get(uid);
225266
+ if (item === void 0 || done.has(keyOf(item)) || queued.has(uid)) continue;
225267
+ queued.add(uid);
225268
+ queue.push(item);
225269
+ }
225270
+ drain();
225271
+ }, { rootMargin: "100px" });
225272
+ for (const element of document.querySelectorAll("[data-arkme-message-item-uid]")) observer.observe(element);
225273
+ return () => {
225274
+ controller.abort();
225275
+ observer.disconnect();
225276
+ };
225277
+ }, [
225278
+ scope,
225279
+ sourceRef,
225280
+ items
225281
+ ]);
225282
+ return snapshot.scope === scope ? snapshot.parents : EMPTY_PARENTS;
225283
+ }
225284
+ //#endregion
224891
225285
  //#region node_modules/@phosphor-icons/react/dist/defs/BatteryHigh.es.js
224892
225286
  const e$15 = /* @__PURE__ */ new Map([
224893
225287
  ["bold", /* @__PURE__ */ react$1.createElement(react$1.Fragment, null, /* @__PURE__ */ react$1.createElement("path", { d: "M196,52H28A28,28,0,0,0,0,80v96a28,28,0,0,0,28,28H196a28,28,0,0,0,28-28V80A28,28,0,0,0,196,52Zm4,124a4,4,0,0,1-4,4H28a4,4,0,0,1-4-4V80a4,4,0,0,1,4-4H196a4,4,0,0,1,4,4Zm-56-72v48a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm-40,0v48a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm-40,0v48a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm192,0v48a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Z" }))],
@@ -233956,9 +234350,14 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
233956
234350
  setError(errorMessage$1(caught));
233957
234351
  }
233958
234352
  };
233959
- const detailItem = items.find((item) => item.itemUid === detailItemUid);
234353
+ const personalExtensionParents = usePersonalExtensionParents(`${authenticatedAccountKey}:${conversationKey}:${sourceProjectionRevision}`, activeConversation && source !== void 0 && isArkmeSelfWorkspaceSource(source) ? source.sourceRef : void 0, items);
234354
+ const detailRow = items.find((item) => item.itemUid === detailItemUid);
234355
+ const detailItem = detailRow === void 0 ? void 0 : personalExtensionParents.has(detailRow.itemUid) ? {
234356
+ ...detailRow,
234357
+ extensionParent: personalExtensionParents.get(detailRow.itemUid)
234358
+ } : detailRow;
233960
234359
  const detailTopicPresentation = detailItem === void 0 ? void 0 : arkmeTimelineSelfTopicPresentation(detailItem, source, selfSources);
233961
- const detailTopicPath = detailItem === void 0 ? void 0 : detailTopicPresentation?.displayLabel ?? (source?.kind === "send_to_self" ? detailItem.selfTopic?.title : void 0);
234360
+ const detailTopicPath = detailItem === void 0 ? void 0 : detailTopicPresentation?.displayLabel ?? detailItem.selfTopic?.title ?? (source?.kind === "topic" ? source.displayName : void 0);
233962
234361
  const openExtensionParentDetail = (parent) => {
233963
234362
  if (source === void 0 || detailItem === void 0 || parent.itemUid === detailItem.itemUid) return;
233964
234363
  const from = {
@@ -233981,7 +234380,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
233981
234380
  from
233982
234381
  };
233983
234382
  };
233984
- if (source.kind !== "topic") {
234383
+ if (source.kind !== "topic" && source.kind !== "default_category") {
233985
234384
  navigate(source);
233986
234385
  return;
233987
234386
  }
@@ -233998,6 +234397,26 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
233998
234397
  setMessageActionStatus(errorMessage$1(caught) || "暂时无法打开延展源");
233999
234398
  });
234000
234399
  };
234400
+ const openTimelineExtensionParent = (parent) => {
234401
+ if (source === void 0) return;
234402
+ if (!isArkmeSelfWorkspaceSource(source)) {
234403
+ arkmeUi.showConversationTarget(source, parent.itemUid, parent.sendAtMillis ?? 0, parent.recordOwnerUserId);
234404
+ return;
234405
+ }
234406
+ const navigate = (target) => arkmeUi.showConversationTarget(target, parent.itemUid, parent.sendAtMillis ?? 0, parent.recordOwnerUserId, void 0, false, true);
234407
+ if (items.some((item) => item.itemUid === parent.itemUid)) {
234408
+ navigate(source);
234409
+ return;
234410
+ }
234411
+ const target = aggregateSource ?? selfSources.find((candidate) => candidate.kind === "send_to_self");
234412
+ if (target !== void 0) {
234413
+ navigate(target);
234414
+ return;
234415
+ }
234416
+ callArkme("sources.self-target", {}).then((target) => {
234417
+ if (arkmeUi.getSnapshot().selectedSource?.sourceRef === source.sourceRef) navigate(target);
234418
+ }, (caught) => setMessageActionStatus(errorMessage$1(caught) || "暂时无法打开延展源"));
234419
+ };
234001
234420
  const detailSharedRecording = detailItem === void 0 ? void 0 : arkmeRelatedRecordingItemFromSharedRecording(detailItem);
234002
234421
  const acceptDetailExtension = (0, react$1.useCallback)((result) => {
234003
234422
  const targetSource = source;
@@ -236444,6 +236863,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
236444
236863
  retryAiPolish,
236445
236864
  toggleSelectedMessage,
236446
236865
  updateComposerText,
236866
+ openTimelineExtensionParent,
236447
236867
  refreshFiles: fileTasks.refresh,
236448
236868
  refreshReedits: reeditSubmissions.refresh
236449
236869
  };
@@ -236527,13 +236947,16 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
236527
236947
  onOpen: (...args) => timelineActions.current.openMomentDetail(...args),
236528
236948
  highlighted: highlightedTargetUid === row.id
236529
236949
  })] }, row.id);
236530
- const item = row.item;
236950
+ const item = personalExtensionParents.has(row.item.itemUid) ? {
236951
+ ...row.item,
236952
+ extensionParent: personalExtensionParents.get(row.item.itemUid)
236953
+ } : row.item;
236531
236954
  const selfTopicPresentation = arkmeTimelineSelfTopicPresentation(item, source, selfSources);
236532
236955
  const selfWorkspace = isArkmeSelfWorkspaceSource(source);
236533
236956
  const role = arkmeSelfRoleForPresentation(item, source.kind);
236534
236957
  const presentationIsMe = item.isMe && role === void 0;
236535
236958
  const roleFallback = role === void 0 ? void 0 : arkmeSelfRoleAvatarFallback(role);
236536
- const avatarRef = role === void 0 ? arkmeTimelineAvatarRef(item, selfWorkspace ? void 0 : selfProfile) ?? (selfWorkspace && item.isMe && item.avatarSnapshot === true ? selfProfile?.avatarRef.trim() : void 0) : role.avatarRef;
236959
+ const avatarRef = selfWorkspace ? arkmePersonalAvatarRef(item, selfProfile) : arkmeTimelineAvatarRef(item, selfProfile);
236537
236960
  const messageMember = item.memberRef === void 0 ? item.isMe ? selfConversationMember : void 0 : conversationMemberByRef.get(item.memberRef);
236538
236961
  const messageHeader = presentationIsMe || source.kind === "private_chat" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeTimelineMessageHeader, {
236539
236962
  item,
@@ -236842,7 +237265,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
236842
237265
  parent: item.extensionParent,
236843
237266
  isMe: presentationIsMe,
236844
237267
  onSelect: () => {
236845
- arkmeUi.showConversationTarget(source, item.extensionParent?.itemUid ?? "", item.extensionParent?.sendAtMillis ?? 0, item.extensionParent?.recordOwnerUserId);
237268
+ if (item.extensionParent !== void 0) timelineActions.current.openTimelineExtensionParent(item.extensionParent);
236846
237269
  }
236847
237270
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
236848
237271
  "data-arkme-extension-child-line": "true",
@@ -236872,6 +237295,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
236872
237295
  });
236873
237296
  }, [
236874
237297
  displayRows,
237298
+ personalExtensionParents,
236875
237299
  source,
236876
237300
  selfSources,
236877
237301
  selfProfile,
@@ -237602,990 +238026,995 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
237602
238026
  style: styles$7.loading,
237603
238027
  children: tr$1("正在加载发给自己的内容…")
237604
238028
  })
237605
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ArkmeWideConversation, {
238029
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeWideConversation, {
237606
238030
  enabled: active && activeConversation && (source.kind === "private_chat" || source.kind === "group_chat"),
237607
238031
  scopeKey: conversationKey,
237608
238032
  viewportRef: bodyRef,
237609
238033
  controlsHidden: activeSelectMode !== void 0,
237610
- children: [
237611
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237612
- style: {
237613
- position: "relative",
237614
- display: "flex",
237615
- flex: 1,
237616
- minHeight: 0
237617
- },
237618
- children: [
237619
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237620
- className: "arkme-conversation-body",
237621
- "data-arkme-width-viewport": true,
237622
- ref: bodyRef,
237623
- style: {
237624
- ...styles$7.body,
237625
- ...displayRows.length === 0 && interwovenWindow.prelude.length === 0 ? {
237626
- display: "flex",
237627
- flexDirection: "column"
237628
- } : {}
237629
- },
237630
- onScroll: handleConversationScroll,
237631
- children: [
237632
- error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237633
- style: styles$7.error,
237634
- children: error
237635
- }),
237636
- error !== "" && displayRows.length === 0 && timelineLoadingKey !== conversationKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
237637
- "data-arkme-feedback": "neutral",
237638
- type: "button",
237639
- style: styles$7.retry,
237640
- onClick: () => {
237641
- setError("");
237642
- setTimelineLoadingKey(conversationKey);
237643
- setForegroundReadRevision((value) => value + 1);
237644
- },
237645
- children: tr$1("重新加载")
237646
- }),
237647
- interwovenWindow.prelude.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeInterwovenPrelude, {
237648
- moments: interwovenWindow.prelude,
237649
- onOpen: openMomentDetail
237650
- }, conversationKey),
237651
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237652
- ref: sentinelRef,
237653
- style: styles$7.sentinel
237654
- }),
237655
- hasMore && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237656
- style: styles$7.loading,
237657
- children: [(olderLoadError !== "" || nextCursor === void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237658
- role: "alert",
237659
- children: olderLoadError || "暂时无法继续加载,请刷新会话后重试"
237660
- }), nextCursor !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
237661
- "data-arkme-feedback": "neutral",
237662
- type: "button",
237663
- style: styles$7.retry,
237664
- disabled: loadingOlder,
237665
- onClick: () => {
237666
- loadOlderHistory();
237667
- },
237668
- children: loadingOlder ? tr$1("正在加载更早内容…") : olderLoadError === "" ? "继续加载更早消息" : "重试加载更早消息"
237669
- })]
237670
- }),
237671
- timelineSkeletonKey === conversationKey && displayRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237672
- role: "status",
237673
- "aria-label": tr$1("正在加载会话内容"),
237674
- style: styles$7.timelineSkeleton,
237675
- children: [
237676
- 58,
237677
- 44,
237678
- 66,
237679
- 50,
237680
- 61
237681
- ].map((width, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237682
- "aria-hidden": true,
237683
- style: {
237684
- ...styles$7.timelineSkeletonRow,
237685
- ...index % 3 === 1 ? styles$7.timelineSkeletonRowMe : {}
237686
- },
237687
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: styles$7.timelineSkeletonAvatar }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
237688
- ...styles$7.timelineSkeletonBubble,
237689
- width: `${width}%`
237690
- } })]
237691
- }, `${width}:${index}`))
237692
- }),
237693
- displayRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
237694
- ref: recordsRef,
237695
- className: `arkme-conversation-records${timelineRevealKey === conversationKey ? " arkme-conversation-records-reveal" : ""}`,
237696
- style: styles$7.records,
237697
- children: renderedMessageRows
237698
- }),
237699
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237700
- ref: newerSentinelRef,
237701
- style: styles$7.sentinel
237702
- }),
237703
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237704
- ref: endAccessoryRef,
237705
- "data-arkme-conversation-end-accessory": true,
237706
- "aria-hidden": activeSelectMode !== void 0 || void 0,
237707
- style: {
237708
- flexShrink: 0,
237709
- visibility: activeSelectMode === void 0 ? "visible" : "hidden",
237710
- ...displayRows.length === 0 ? { marginTop: "auto" } : {}
237711
- },
237712
- children: activeConversation && (source?.kind === "private_chat" || source?.kind === "group_chat") && source.sourceKey !== void 0 && authenticatedAccountKey !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMessagePreparingIndicator, {
237713
- sourceKey: source.sourceKey,
237714
- accountScope: authenticatedAccountKey
237715
- })
237716
- })
237717
- ]
237718
- }),
237719
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RegionMarquee, {
237720
- getStartArea: () => selectionStartAreaRef.current && composerRef.current ? {
237721
- element: selectionStartAreaRef.current,
237722
- boundary: composerRef.current
237723
- } : void 0,
237724
- viewportRef: bodyRef,
237725
- scopeKey: `${authenticatedAccountKey}:${conversationKey}`,
237726
- enabled: active && activeConversation && timelineStateKey === conversationKey && messageActionBusy === void 0 && forwardTargetPicker === void 0 && topicAssignment === void 0 && drawer === void 0,
237727
- getItems: () => [...bodyRef.current?.querySelectorAll("[data-arkme-selection-key]") ?? []].map((element) => ({
237728
- key: element.dataset.arkmeSelectionKey,
237729
- element
237730
- })),
237731
- onCommit: commitMarqueeSelection,
237732
- style: {
237733
- border: `1px solid ${arkmeTheme.accent}`,
237734
- background: `color-mix(in srgb, ${arkmeTheme.accent} 16%, transparent)`
237735
- }
237736
- }),
237737
- active && activeConversation && timelineStateKey === conversationKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeConversationBottomControl, {
237738
- showBackToBottom: bottomVisibility.visible || timelineMode === "around" || newerHasMore,
237739
- newMessageCount,
237740
- onReturnToLatest: returnToLatest
237741
- }, `${authenticatedAccountKey}:${conversationKey}`)
237742
- ]
237743
- }),
237744
- isArkmeOfficialAuthor(source) && timelineStateKey === conversationKey && timelineLoadingKey !== conversationKey && error === "" && conversationCacheRef.current.getTimeline(conversationKey) !== void 0 && displayRows.length === 0 && !hasMore && !newerHasMore && (source?.latestSequence ?? 0) === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeOfficialAuthorGuide, {}),
237745
- activeConversation && forwardSuccessFeedback !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237746
- style: styles$7.forwardSuccessBannerWrap,
237747
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
237748
- type: "button",
237749
- style: styles$7.forwardSuccessBanner,
237750
- "aria-label": forwardSuccessFeedback.message,
237751
- onClick: () => {
237752
- if (forwardSuccessTimerRef.current !== void 0) {
237753
- window.clearTimeout(forwardSuccessTimerRef.current);
237754
- forwardSuccessTimerRef.current = void 0;
237755
- }
237756
- const target = forwardSuccessFeedback.targets[0];
237757
- setForwardSuccessFeedback(void 0);
237758
- if (target !== void 0) activateSource(target);
238034
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ArkmeInterwovenReadProvider, {
238035
+ sourceRef: source.sourceRef,
238036
+ scope: `${authenticatedAccountKey}:${conversationKey}`,
238037
+ enabled: activeConversation && authenticated && source.kind === "private_chat",
238038
+ children: [
238039
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238040
+ style: {
238041
+ position: "relative",
238042
+ display: "flex",
238043
+ flex: 1,
238044
+ minHeight: 0
237759
238045
  },
237760
238046
  children: [
237761
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238047
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238048
+ className: "arkme-conversation-body",
238049
+ "data-arkme-width-viewport": true,
238050
+ ref: bodyRef,
237762
238051
  style: {
237763
- ...styles$7.forwardSuccessAvatarStack,
237764
- width: Math.min(30 + Math.max(0, forwardSuccessFeedback.targets.length - 1) * 15, 75)
238052
+ ...styles$7.body,
238053
+ ...displayRows.length === 0 && interwovenWindow.prelude.length === 0 ? {
238054
+ display: "flex",
238055
+ flexDirection: "column"
238056
+ } : {}
237765
238057
  },
237766
- children: forwardSuccessFeedback.targets.slice(0, 4).map((target, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
237767
- style: {
237768
- position: "absolute",
237769
- left: index * 15,
237770
- top: 0
237771
- },
237772
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeDirectorySourceAvatar, {
237773
- source: target,
237774
- size: 30
237775
- })
237776
- }, target.sourceRef))
237777
- }),
237778
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
237779
- style: styles$7.forwardSuccessText,
237780
- children: forwardSuccessFeedback.message
237781
- }),
237782
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
237783
- style: styles$7.forwardSuccessAction,
237784
- children: tr$1("去看看")
237785
- })
237786
- ]
237787
- })
237788
- }),
237789
- (activeSelectMode === void 0 && askDsh.status || messageActionStatus) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237790
- role: "status",
237791
- "aria-live": "polite",
237792
- style: styles$7.messageActionToast,
237793
- children: activeSelectMode === void 0 && askDsh.status || messageActionStatus
237794
- }),
237795
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237796
- ref: selectionStartAreaRef,
237797
- className: "arkme-conversation-input-slot",
237798
- style: {
237799
- position: "relative",
237800
- flex: "none",
237801
- ...activeSelectMode === void 0 ? {} : { minHeight: askDsh.status ? 160 : 130 }
237802
- },
237803
- children: [
237804
- archiveReadOnly && source !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237805
- "aria-hidden": activeSelectMode !== void 0 || void 0,
237806
- ...activeSelectMode === void 0 ? {} : { inert: "" },
237807
- style: { visibility: activeSelectMode === void 0 ? "visible" : "hidden" },
237808
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeTopicReadOnlyNotice, {})
237809
- }),
237810
- (!archiveReadOnly || activeRecordReeditComposer !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
237811
- "data-arkme-width-composer": true,
237812
- className: "arkme-conversation-composer",
237813
- "aria-hidden": activeSelectMode !== void 0 || void 0,
237814
- ...activeSelectMode === void 0 ? {} : { inert: "" },
237815
- style: {
237816
- ...styles$7.composer,
237817
- ...activeSelectMode === void 0 ? {} : {
237818
- visibility: "hidden",
237819
- pointerEvents: "none"
237820
- }
237821
- },
237822
- onClick: (event) => {
237823
- focusArkmeComposerFromClick(textareaRef.current, event);
237824
- },
237825
- onDragOver: (event) => {
237826
- if (!composerFileAddingDisabled && Array.from(event.dataTransfer.types).includes("Files")) {
237827
- event.preventDefault();
237828
- event.dataTransfer.dropEffect = "copy";
237829
- }
237830
- },
237831
- onDrop: (event) => {
237832
- if (!composerFileAddingDisabled && event.dataTransfer.files.length > 0) {
237833
- event.preventDefault();
237834
- selectFiles(event.dataTransfer.files);
237835
- }
237836
- },
237837
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237838
- style: styles$7.composerStack,
238058
+ onScroll: handleConversationScroll,
237839
238059
  children: [
237840
- activeRecordReeditComposer !== void 0 && activeRecordReeditComposer.error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237841
- role: "alert",
238060
+ error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237842
238061
  style: styles$7.error,
237843
- children: activeRecordReeditComposer.error
238062
+ children: error
237844
238063
  }),
237845
- activeRecordReeditComposer !== void 0 && (activeRecordReeditComposer.conflict !== void 0 || activeRecordReeditComposer.snapshot?.draft !== void 0 && activeRecordReeditComposer.snapshot.draft.baseVersion !== void 0 && activeRecordReeditComposer.snapshot.draft.baseVersion !== activeRecordReeditComposer.snapshot.version) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238064
+ error !== "" && displayRows.length === 0 && timelineLoadingKey !== conversationKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
237846
238065
  "data-arkme-feedback": "neutral",
237847
238066
  type: "button",
237848
238067
  style: styles$7.retry,
237849
- disabled: composerFilesDisabled,
237850
- "aria-label": activeRecordReeditComposer.conflict === "draft" ? "重新载入草稿" : "放弃草稿并重新载入",
237851
- onClick: () => setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) ? {
237852
- ...current,
237853
- recoveryConfirmation: true
237854
- } : current),
237855
- children: activeRecordReeditComposer.conflict === "draft" ? "重新载入草稿" : "放弃草稿并重新载入"
238068
+ onClick: () => {
238069
+ setError("");
238070
+ setTimelineLoadingKey(conversationKey);
238071
+ setForegroundReadRevision((value) => value + 1);
238072
+ },
238073
+ children: tr$1("重新加载")
237856
238074
  }),
237857
- activeRecordReeditComposer?.recoveryConfirmation && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeConfirmDialog, {
237858
- titleId: "arkme-reedit-recovery-title",
237859
- title: activeRecordReeditComposer.conflict === "draft" ? "重新载入最新草稿?" : "放弃草稿并重新载入?",
237860
- description: activeRecordReeditComposer.conflict === "draft" ? "当前输入区将替换为其他入口保存的最新草稿。不会删除草稿或修改已保存的快记。" : "本机这份重新编辑草稿中的正文和附件改动将被放弃,重新载入已保存的快记。此操作不会删除线上附件。",
237861
- busy: activeRecordReeditComposer.busy,
237862
- error: activeRecordReeditComposer.error,
237863
- confirmTone: activeRecordReeditComposer.conflict === "draft" ? "primary" : "danger",
237864
- confirmLabel: activeRecordReeditComposer.conflict === "draft" ? "重新载入" : "放弃并重新载入",
237865
- busyLabel: tr$1("正在重新载入…"),
237866
- onClose: () => setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) && !current.busy ? {
237867
- ...current,
237868
- recoveryConfirmation: false
237869
- } : current),
237870
- onConfirm: () => {
237871
- recoverRecordReedit();
237872
- }
238075
+ interwovenWindow.prelude.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeInterwovenPrelude, {
238076
+ moments: interwovenWindow.prelude,
238077
+ onOpen: openMomentDetail
238078
+ }, conversationKey),
238079
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238080
+ ref: sentinelRef,
238081
+ style: styles$7.sentinel
237873
238082
  }),
237874
- composerInfoRow,
237875
- activeComposerTargetItem !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237876
- style: styles$7.composerExtensionTarget,
237877
- ...activeRecordReeditComposer === void 0 ? { "data-arkme-composer-extension-target": "true" } : { "data-arkme-composer-reedit-target": "true" },
237878
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237879
- style: styles$7.composerExtensionTargetBody,
237880
- children: [
237881
- activeRecordReeditComposer !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237882
- style: styles$7.composerReeditLabel,
237883
- children: tr$1("重新编辑:")
237884
- }),
237885
- (activeComposerTargetItem.textContent.trim() || activeComposerTargetItem.title.trim()) !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237886
- style: styles$7.composerExtensionTargetText,
237887
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeRichText, {
237888
- text: activeComposerTargetItem.textContent.trim() || activeComposerTargetItem.title.trim(),
237889
- presentation: "preview"
237890
- })
237891
- }),
237892
- (activeComposerTargetItem.contentBlocks?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237893
- style: styles$7.composerExtensionTargetFiles,
237894
- children: activeComposerTargetItem.contentBlocks?.slice(0, 3).map((block, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
237895
- style: styles$7.composerExtensionTargetFile,
237896
- title: block.fileName || "附件",
237897
- children: block.kind === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
237898
- style: styles$7.composerExtensionTargetImage,
237899
- src: createArkmeSdk().mediaUrl(block.mediaRef),
237900
- alt: block.fileName || "图片附件"
237901
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
237902
- hidden: true,
237903
- children: block.fileName || "附件"
237904
- })] }) : block.fileName || "附件"
237905
- }, `${block.mediaRef}:${String(index)}`))
237906
- })
237907
- ]
237908
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238083
+ hasMore && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238084
+ style: styles$7.loading,
238085
+ children: [(olderLoadError !== "" || nextCursor === void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238086
+ role: "alert",
238087
+ children: olderLoadError || "暂时无法继续加载,请刷新会话后重试"
238088
+ }), nextCursor !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
237909
238089
  "data-arkme-feedback": "neutral",
237910
238090
  type: "button",
237911
- style: styles$7.composerExtensionTargetCancel,
237912
- "aria-label": activeRecordReeditComposer === void 0 ? "取消延展" : "关闭重新编辑",
237913
- disabled: activeRecordReeditComposer?.busy === true || preparingReeditFiles,
238091
+ style: styles$7.retry,
238092
+ disabled: loadingOlder,
237914
238093
  onClick: () => {
237915
- if (activeRecordReeditComposer === void 0) {
237916
- setComposerExtensionTarget(void 0);
237917
- textareaRef.current?.focus();
237918
- } else closeRecordReedit();
238094
+ loadOlderHistory();
237919
238095
  },
237920
- children: "×"
238096
+ children: loadingOlder ? tr$1("正在加载更早内容…") : olderLoadError === "" ? "继续加载更早消息" : "重试加载更早消息"
237921
238097
  })]
237922
238098
  }),
237923
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237924
- ref: composerRef,
237925
- className: "arkme-conversation-composer-inner",
237926
- "data-arkme-primary-composer": "true",
237927
- "data-arkme-composer-focused": composerInputFocused ? "true" : "false",
237928
- "data-arkme-composer-resize-highlighted": composerResize.highlighted ? "true" : void 0,
238099
+ timelineSkeletonKey === conversationKey && displayRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238100
+ role: "status",
238101
+ "aria-label": tr$1("正在加载会话内容"),
238102
+ style: styles$7.timelineSkeleton,
238103
+ children: [
238104
+ 58,
238105
+ 44,
238106
+ 66,
238107
+ 50,
238108
+ 61
238109
+ ].map((width, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238110
+ "aria-hidden": true,
238111
+ style: {
238112
+ ...styles$7.timelineSkeletonRow,
238113
+ ...index % 3 === 1 ? styles$7.timelineSkeletonRowMe : {}
238114
+ },
238115
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: styles$7.timelineSkeletonAvatar }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
238116
+ ...styles$7.timelineSkeletonBubble,
238117
+ width: `${width}%`
238118
+ } })]
238119
+ }, `${width}:${index}`))
238120
+ }),
238121
+ displayRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
238122
+ ref: recordsRef,
238123
+ className: `arkme-conversation-records${timelineRevealKey === conversationKey ? " arkme-conversation-records-reveal" : ""}`,
238124
+ style: styles$7.records,
238125
+ children: renderedMessageRows
238126
+ }),
238127
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238128
+ ref: newerSentinelRef,
238129
+ style: styles$7.sentinel
238130
+ }),
238131
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238132
+ ref: endAccessoryRef,
238133
+ "data-arkme-conversation-end-accessory": true,
238134
+ "aria-hidden": activeSelectMode !== void 0 || void 0,
237929
238135
  style: {
237930
- ...styles$7.composerInner,
237931
- ...composerInputFocused ? styles$7.composerInnerFocused : {},
237932
- ...arkmeConversationComposerBorder(composerInputFocused || composerHasTarget ? colors.border : "transparent", composerHasTarget, composerResize.highlighted)
238136
+ flexShrink: 0,
238137
+ visibility: activeSelectMode === void 0 ? "visible" : "hidden",
238138
+ ...displayRows.length === 0 ? { marginTop: "auto" } : {}
237933
238139
  },
237934
- children: [
237935
- composerResize.handle,
237936
- addMenuOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeActionMenu, {
237937
- label: tr$1("添加内容"),
237938
- side: "top",
237939
- getAnchorRect: () => addMenuTriggerRef.current?.getBoundingClientRect() ?? null,
237940
- onClose: () => setAddMenuOpen(false),
237941
- actions: [{
237942
- id: "files",
237943
- label: "添加附件",
237944
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, {}),
237945
- onSelect: () => {
237946
- setAddMenuOpen(false);
237947
- fileInputRef.current?.click();
237948
- }
237949
- }, activeRecordReeditComposer === void 0 && {
237950
- id: "article",
237951
- label: sourceIsChat ? "添加长文" : "写长文",
237952
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {}),
237953
- disabled: pendingArticle?.sending === true,
237954
- onSelect: () => {
237955
- if (pendingArticle?.sending) return;
237956
- if (sourceIsChat) setArticlePickerScope(captureComposerAsyncScope());
237957
- else createLongArticle();
237958
- setAddMenuOpen(false);
237959
- }
237960
- }]
237961
- }),
237962
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
237963
- ref: fileInputRef,
237964
- type: "file",
237965
- multiple: true,
237966
- hidden: true,
237967
- onChange: (event) => {
237968
- selectFiles(event.currentTarget.files);
237969
- }
237970
- }),
237971
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237972
- className: "arkme-conversation-input-card",
238140
+ children: activeConversation && (source?.kind === "private_chat" || source?.kind === "group_chat") && source.sourceKey !== void 0 && authenticatedAccountKey !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMessagePreparingIndicator, {
238141
+ sourceKey: source.sourceKey,
238142
+ accountScope: authenticatedAccountKey
238143
+ })
238144
+ })
238145
+ ]
238146
+ }),
238147
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RegionMarquee, {
238148
+ getStartArea: () => selectionStartAreaRef.current && composerRef.current ? {
238149
+ element: selectionStartAreaRef.current,
238150
+ boundary: composerRef.current
238151
+ } : void 0,
238152
+ viewportRef: bodyRef,
238153
+ scopeKey: `${authenticatedAccountKey}:${conversationKey}`,
238154
+ enabled: active && activeConversation && timelineStateKey === conversationKey && messageActionBusy === void 0 && forwardTargetPicker === void 0 && topicAssignment === void 0 && drawer === void 0,
238155
+ getItems: () => [...bodyRef.current?.querySelectorAll("[data-arkme-selection-key]") ?? []].map((element) => ({
238156
+ key: element.dataset.arkmeSelectionKey,
238157
+ element
238158
+ })),
238159
+ onCommit: commitMarqueeSelection,
238160
+ style: {
238161
+ border: `1px solid ${arkmeTheme.accent}`,
238162
+ background: `color-mix(in srgb, ${arkmeTheme.accent} 16%, transparent)`
238163
+ }
238164
+ }),
238165
+ active && activeConversation && timelineStateKey === conversationKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeConversationBottomControl, {
238166
+ showBackToBottom: bottomVisibility.visible || timelineMode === "around" || newerHasMore,
238167
+ newMessageCount,
238168
+ onReturnToLatest: returnToLatest
238169
+ }, `${authenticatedAccountKey}:${conversationKey}`)
238170
+ ]
238171
+ }),
238172
+ isArkmeOfficialAuthor(source) && timelineStateKey === conversationKey && timelineLoadingKey !== conversationKey && error === "" && conversationCacheRef.current.getTimeline(conversationKey) !== void 0 && displayRows.length === 0 && !hasMore && !newerHasMore && (source?.latestSequence ?? 0) === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeOfficialAuthorGuide, {}),
238173
+ activeConversation && forwardSuccessFeedback !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238174
+ style: styles$7.forwardSuccessBannerWrap,
238175
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238176
+ type: "button",
238177
+ style: styles$7.forwardSuccessBanner,
238178
+ "aria-label": forwardSuccessFeedback.message,
238179
+ onClick: () => {
238180
+ if (forwardSuccessTimerRef.current !== void 0) {
238181
+ window.clearTimeout(forwardSuccessTimerRef.current);
238182
+ forwardSuccessTimerRef.current = void 0;
238183
+ }
238184
+ const target = forwardSuccessFeedback.targets[0];
238185
+ setForwardSuccessFeedback(void 0);
238186
+ if (target !== void 0) activateSource(target);
238187
+ },
238188
+ children: [
238189
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238190
+ style: {
238191
+ ...styles$7.forwardSuccessAvatarStack,
238192
+ width: Math.min(30 + Math.max(0, forwardSuccessFeedback.targets.length - 1) * 15, 75)
238193
+ },
238194
+ children: forwardSuccessFeedback.targets.slice(0, 4).map((target, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238195
+ style: {
238196
+ position: "absolute",
238197
+ left: index * 15,
238198
+ top: 0
238199
+ },
238200
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeDirectorySourceAvatar, {
238201
+ source: target,
238202
+ size: 30
238203
+ })
238204
+ }, target.sourceRef))
238205
+ }),
238206
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238207
+ style: styles$7.forwardSuccessText,
238208
+ children: forwardSuccessFeedback.message
238209
+ }),
238210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238211
+ style: styles$7.forwardSuccessAction,
238212
+ children: tr$1("去看看")
238213
+ })
238214
+ ]
238215
+ })
238216
+ }),
238217
+ (activeSelectMode === void 0 && askDsh.status || messageActionStatus) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238218
+ role: "status",
238219
+ "aria-live": "polite",
238220
+ style: styles$7.messageActionToast,
238221
+ children: activeSelectMode === void 0 && askDsh.status || messageActionStatus
238222
+ }),
238223
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238224
+ ref: selectionStartAreaRef,
238225
+ className: "arkme-conversation-input-slot",
238226
+ style: {
238227
+ position: "relative",
238228
+ flex: "none",
238229
+ ...activeSelectMode === void 0 ? {} : { minHeight: askDsh.status ? 160 : 130 }
238230
+ },
238231
+ children: [
238232
+ archiveReadOnly && source !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238233
+ "aria-hidden": activeSelectMode !== void 0 || void 0,
238234
+ ...activeSelectMode === void 0 ? {} : { inert: "" },
238235
+ style: { visibility: activeSelectMode === void 0 ? "visible" : "hidden" },
238236
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeTopicReadOnlyNotice, {})
238237
+ }),
238238
+ (!archiveReadOnly || activeRecordReeditComposer !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
238239
+ "data-arkme-width-composer": true,
238240
+ className: "arkme-conversation-composer",
238241
+ "aria-hidden": activeSelectMode !== void 0 || void 0,
238242
+ ...activeSelectMode === void 0 ? {} : { inert: "" },
238243
+ style: {
238244
+ ...styles$7.composer,
238245
+ ...activeSelectMode === void 0 ? {} : {
238246
+ visibility: "hidden",
238247
+ pointerEvents: "none"
238248
+ }
238249
+ },
238250
+ onClick: (event) => {
238251
+ focusArkmeComposerFromClick(textareaRef.current, event);
238252
+ },
238253
+ onDragOver: (event) => {
238254
+ if (!composerFileAddingDisabled && Array.from(event.dataTransfer.types).includes("Files")) {
238255
+ event.preventDefault();
238256
+ event.dataTransfer.dropEffect = "copy";
238257
+ }
238258
+ },
238259
+ onDrop: (event) => {
238260
+ if (!composerFileAddingDisabled && event.dataTransfer.files.length > 0) {
238261
+ event.preventDefault();
238262
+ selectFiles(event.dataTransfer.files);
238263
+ }
238264
+ },
238265
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238266
+ style: styles$7.composerStack,
238267
+ children: [
238268
+ activeRecordReeditComposer !== void 0 && activeRecordReeditComposer.error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238269
+ role: "alert",
238270
+ style: styles$7.error,
238271
+ children: activeRecordReeditComposer.error
238272
+ }),
238273
+ activeRecordReeditComposer !== void 0 && (activeRecordReeditComposer.conflict !== void 0 || activeRecordReeditComposer.snapshot?.draft !== void 0 && activeRecordReeditComposer.snapshot.draft.baseVersion !== void 0 && activeRecordReeditComposer.snapshot.draft.baseVersion !== activeRecordReeditComposer.snapshot.version) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238274
+ "data-arkme-feedback": "neutral",
238275
+ type: "button",
238276
+ style: styles$7.retry,
238277
+ disabled: composerFilesDisabled,
238278
+ "aria-label": activeRecordReeditComposer.conflict === "draft" ? "重新载入草稿" : "放弃草稿并重新载入",
238279
+ onClick: () => setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) ? {
238280
+ ...current,
238281
+ recoveryConfirmation: true
238282
+ } : current),
238283
+ children: activeRecordReeditComposer.conflict === "draft" ? "重新载入草稿" : "放弃草稿并重新载入"
238284
+ }),
238285
+ activeRecordReeditComposer?.recoveryConfirmation && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeConfirmDialog, {
238286
+ titleId: "arkme-reedit-recovery-title",
238287
+ title: activeRecordReeditComposer.conflict === "draft" ? "重新载入最新草稿?" : "放弃草稿并重新载入?",
238288
+ description: activeRecordReeditComposer.conflict === "draft" ? "当前输入区将替换为其他入口保存的最新草稿。不会删除草稿或修改已保存的快记。" : "本机这份重新编辑草稿中的正文和附件改动将被放弃,重新载入已保存的快记。此操作不会删除线上附件。",
238289
+ busy: activeRecordReeditComposer.busy,
238290
+ error: activeRecordReeditComposer.error,
238291
+ confirmTone: activeRecordReeditComposer.conflict === "draft" ? "primary" : "danger",
238292
+ confirmLabel: activeRecordReeditComposer.conflict === "draft" ? "重新载入" : "放弃并重新载入",
238293
+ busyLabel: tr$1("正在重新载入…"),
238294
+ onClose: () => setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) && !current.busy ? {
238295
+ ...current,
238296
+ recoveryConfirmation: false
238297
+ } : current),
238298
+ onConfirm: () => {
238299
+ recoverRecordReedit();
238300
+ }
238301
+ }),
238302
+ composerInfoRow,
238303
+ activeComposerTargetItem !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238304
+ style: styles$7.composerExtensionTarget,
238305
+ ...activeRecordReeditComposer === void 0 ? { "data-arkme-composer-extension-target": "true" } : { "data-arkme-composer-reedit-target": "true" },
238306
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238307
+ style: styles$7.composerExtensionTargetBody,
237973
238308
  children: [
237974
- pendingArticle && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237975
- "data-arkme-pending-article": "true",
237976
- style: {
237977
- display: "flex",
237978
- gap: 12,
237979
- alignItems: "center",
237980
- margin: "8px 12px",
237981
- padding: "10px 12px",
237982
- border: `1px solid ${arkmeTheme.border}`,
237983
- borderRadius: 10,
237984
- background: arkmeTheme.layer1,
237985
- color: arkmeTheme.text
237986
- },
237987
- children: [
237988
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {}),
237989
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238309
+ activeRecordReeditComposer !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238310
+ style: styles$7.composerReeditLabel,
238311
+ children: tr$1("重新编辑:")
238312
+ }),
238313
+ (activeComposerTargetItem.textContent.trim() || activeComposerTargetItem.title.trim()) !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238314
+ style: styles$7.composerExtensionTargetText,
238315
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeRichText, {
238316
+ text: activeComposerTargetItem.textContent.trim() || activeComposerTargetItem.title.trim(),
238317
+ presentation: "preview"
238318
+ })
238319
+ }),
238320
+ (activeComposerTargetItem.contentBlocks?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238321
+ style: styles$7.composerExtensionTargetFiles,
238322
+ children: activeComposerTargetItem.contentBlocks?.slice(0, 3).map((block, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238323
+ style: styles$7.composerExtensionTargetFile,
238324
+ title: block.fileName || "附件",
238325
+ children: block.kind === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
238326
+ style: styles$7.composerExtensionTargetImage,
238327
+ src: createArkmeSdk().mediaUrl(block.mediaRef),
238328
+ alt: block.fileName || "图片附件"
238329
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238330
+ hidden: true,
238331
+ children: block.fileName || "附件"
238332
+ })] }) : block.fileName || "附件"
238333
+ }, `${block.mediaRef}:${String(index)}`))
238334
+ })
238335
+ ]
238336
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238337
+ "data-arkme-feedback": "neutral",
238338
+ type: "button",
238339
+ style: styles$7.composerExtensionTargetCancel,
238340
+ "aria-label": activeRecordReeditComposer === void 0 ? "取消延展" : "关闭重新编辑",
238341
+ disabled: activeRecordReeditComposer?.busy === true || preparingReeditFiles,
238342
+ onClick: () => {
238343
+ if (activeRecordReeditComposer === void 0) {
238344
+ setComposerExtensionTarget(void 0);
238345
+ textareaRef.current?.focus();
238346
+ } else closeRecordReedit();
238347
+ },
238348
+ children: "×"
238349
+ })]
238350
+ }),
238351
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238352
+ ref: composerRef,
238353
+ className: "arkme-conversation-composer-inner",
238354
+ "data-arkme-primary-composer": "true",
238355
+ "data-arkme-composer-focused": composerInputFocused ? "true" : "false",
238356
+ "data-arkme-composer-resize-highlighted": composerResize.highlighted ? "true" : void 0,
238357
+ style: {
238358
+ ...styles$7.composerInner,
238359
+ ...composerInputFocused ? styles$7.composerInnerFocused : {},
238360
+ ...arkmeConversationComposerBorder(composerInputFocused || composerHasTarget ? colors.border : "transparent", composerHasTarget, composerResize.highlighted)
238361
+ },
238362
+ children: [
238363
+ composerResize.handle,
238364
+ addMenuOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeActionMenu, {
238365
+ label: tr$1("添加内容"),
238366
+ side: "top",
238367
+ getAnchorRect: () => addMenuTriggerRef.current?.getBoundingClientRect() ?? null,
238368
+ onClose: () => setAddMenuOpen(false),
238369
+ actions: [{
238370
+ id: "files",
238371
+ label: "添加附件",
238372
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, {}),
238373
+ onSelect: () => {
238374
+ setAddMenuOpen(false);
238375
+ fileInputRef.current?.click();
238376
+ }
238377
+ }, activeRecordReeditComposer === void 0 && {
238378
+ id: "article",
238379
+ label: sourceIsChat ? "添加长文" : "写长文",
238380
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {}),
238381
+ disabled: pendingArticle?.sending === true,
238382
+ onSelect: () => {
238383
+ if (pendingArticle?.sending) return;
238384
+ if (sourceIsChat) setArticlePickerScope(captureComposerAsyncScope());
238385
+ else createLongArticle();
238386
+ setAddMenuOpen(false);
238387
+ }
238388
+ }]
238389
+ }),
238390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
238391
+ ref: fileInputRef,
238392
+ type: "file",
238393
+ multiple: true,
238394
+ hidden: true,
238395
+ onChange: (event) => {
238396
+ selectFiles(event.currentTarget.files);
238397
+ }
238398
+ }),
238399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238400
+ className: "arkme-conversation-input-card",
238401
+ children: [
238402
+ pendingArticle && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238403
+ "data-arkme-pending-article": "true",
238404
+ style: {
238405
+ display: "flex",
238406
+ gap: 12,
238407
+ alignItems: "center",
238408
+ margin: "8px 12px",
238409
+ padding: "10px 12px",
238410
+ border: `1px solid ${arkmeTheme.border}`,
238411
+ borderRadius: 10,
238412
+ background: arkmeTheme.layer1,
238413
+ color: arkmeTheme.text
238414
+ },
238415
+ children: [
238416
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {}),
238417
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238418
+ style: {
238419
+ minWidth: 0,
238420
+ flex: 1
238421
+ },
238422
+ children: [
238423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238424
+ style: {
238425
+ whiteSpace: "nowrap",
238426
+ overflow: "hidden",
238427
+ textOverflow: "ellipsis",
238428
+ fontWeight: 600
238429
+ },
238430
+ children: pendingArticle.article.kind === "existing" ? pendingArticle.article.detail.title : pendingArticle.article.draft.title
238431
+ }),
238432
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238433
+ style: {
238434
+ color: arkmeTheme.secondary,
238435
+ fontSize: 12,
238436
+ marginTop: 4
238437
+ },
238438
+ children: pendingArticle.sending ? "长文发送中…" : "长文将单独发送,原文字和附件保留"
238439
+ }),
238440
+ pendingArticle.error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238441
+ role: "alert",
238442
+ style: {
238443
+ color: arkmeTheme.danger,
238444
+ fontSize: 12
238445
+ },
238446
+ children: [
238447
+ pendingArticle.error,
238448
+ " ",
238449
+ tr$1("· 点击发送重试")
238450
+ ]
238451
+ })
238452
+ ]
238453
+ }),
238454
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238455
+ type: "button",
238456
+ "aria-label": tr$1("移除待发送长文"),
238457
+ disabled: pendingArticle.sending,
238458
+ style: {
238459
+ color: arkmeTheme.secondary,
238460
+ background: "transparent",
238461
+ border: 0,
238462
+ cursor: "pointer",
238463
+ fontSize: 20
238464
+ },
238465
+ onClick: () => {
238466
+ if (articleDraftKey) composerArticleStore.remove(articleDraftKey);
238467
+ },
238468
+ children: "×"
238469
+ })
238470
+ ]
238471
+ }),
238472
+ visibleComposerAttachments.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeAttachmentStrip, {
238473
+ attachments: visibleComposerAttachments,
238474
+ disabled: composerFilesDisabled,
238475
+ onMove: (from, to) => {
238476
+ if (composerFilesDisabled) return;
238477
+ if (activeRecordReeditComposer === void 0) arkmeComposerDraftStore.moveAttachment(composerDraftKey, from, to);
238478
+ else setRecordReeditComposer((current) => {
238479
+ if (!sameArkmeRecordReeditSession(current, activeRecordReeditComposer)) return current;
238480
+ const next = [...current.attachments];
238481
+ const attachment = next[from];
238482
+ if (attachment === void 0 || to < 0 || to >= next.length) return current;
238483
+ next.splice(from, 1);
238484
+ next.splice(to, 0, attachment);
238485
+ return {
238486
+ ...current,
238487
+ attachments: next,
238488
+ error: ""
238489
+ };
238490
+ });
238491
+ },
238492
+ canPreview: (attachment) => activeRecordReeditComposer === void 0 ? attachment.localFile !== void 0 : activeRecordReeditComposer.attachments.some((view) => arkmeAttachmentId(view) === arkmeAttachmentId(attachment) && arkmeRecordReeditAttachmentBlock(view) !== void 0),
238493
+ onPreview: (attachment) => {
238494
+ if (activeRecordReeditComposer === void 0) {
238495
+ if (attachment.localFile !== void 0) {
238496
+ const block = localFileBlock(attachment.localFile);
238497
+ if (attachmentPreviewBridge()?.version === 1) try {
238498
+ openSessionAttachmentPreview(attachments.flatMap((value) => value.localFile === void 0 ? [] : [localFileBlock(value.localFile)]), block, "composer");
238499
+ } catch {
238500
+ setError("无法创建预览窗口,请再次点击附件重试");
238501
+ }
238502
+ else setDraftPreview(block);
238503
+ }
238504
+ } else {
238505
+ const view = activeRecordReeditComposer.attachments.find((view) => arkmeAttachmentId(view) === arkmeAttachmentId(attachment));
238506
+ if (view !== void 0) {
238507
+ const block = arkmeRecordReeditAttachmentBlock(view);
238508
+ if (block !== void 0 && attachmentPreviewBridge()?.version === 1) try {
238509
+ openSessionAttachmentPreview(activeRecordReeditComposer.attachments.flatMap((value) => {
238510
+ const item = arkmeRecordReeditAttachmentBlock(value);
238511
+ return item === void 0 ? [] : [item];
238512
+ }), block, "composer-reedit");
238513
+ } catch {
238514
+ setError("无法创建预览窗口,请再次点击附件重试");
238515
+ }
238516
+ else setDraftPreview(block);
238517
+ }
238518
+ }
238519
+ },
238520
+ onRemove: (attachment) => {
238521
+ if (composerFilesDisabled) return;
238522
+ if (activeRecordReeditComposer !== void 0) {
238523
+ setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) ? {
238524
+ ...current,
238525
+ attachments: current.attachments.filter((view) => arkmeAttachmentId(view) !== arkmeAttachmentId(attachment)),
238526
+ error: ""
238527
+ } : current);
238528
+ setDraftPreview(void 0);
238529
+ return;
238530
+ }
238531
+ arkmeComposerDraftStore.removeAttachment(composerDraftKey, arkmeAttachmentId(attachment));
238532
+ if (attachment.localFile !== void 0) callArkme("files.local.remove", { fileRef: attachment.localFile.fileRef }).catch((caught) => setError(errorMessage$1(caught)));
238533
+ }
238534
+ }),
238535
+ activeRecordReeditComposer?.attachments.some((attachment) => attachment.unavailable) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238536
+ role: "status",
238537
+ style: styles$7.error,
238538
+ children: tr$1("部分附件不可用,请移除后重新添加")
238539
+ }),
238540
+ activeConversation && draftPreview !== void 0 && typeof document !== "undefined" && (0, react_dom$1.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMediaPreview, {
238541
+ selected: draftPreview,
238542
+ blocks: activeRecordReeditComposer === void 0 ? attachments.flatMap((attachment) => attachment.localFile === void 0 ? [] : [localFileBlock(attachment.localFile)]) : activeRecordReeditComposer.attachments.flatMap((attachment) => {
238543
+ const block = arkmeRecordReeditAttachmentBlock(attachment);
238544
+ return block === void 0 ? [] : [block];
238545
+ }),
238546
+ onSelect: setDraftPreview,
238547
+ onClose: () => setDraftPreview(void 0),
238548
+ openLocalFile: false
238549
+ }), document.body),
238550
+ activeRecordReeditComposer === void 0 && hashTagTrigger !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238551
+ ref: hashTagSuggestionListRef,
238552
+ style: styles$7.mentionSuggestions,
238553
+ role: "listbox",
238554
+ "aria-label": tr$1("选择标签"),
238555
+ children: [hashTagCandidates.length === 0 && !hashTagError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238556
+ style: styles$7.mentionSuggestionsEmpty,
238557
+ children: hashTagLoading ? "正在加载标签…" : "暂无匹配标签,可继续输入创建新标签"
238558
+ }) : hashTagCandidates.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238559
+ "data-arkme-feedback": "neutral",
238560
+ type: "button",
238561
+ role: "option",
238562
+ "aria-selected": index === hashTagCandidateIndex,
237990
238563
  style: {
237991
- minWidth: 0,
237992
- flex: 1
238564
+ ...styles$7.mentionSuggestionRow,
238565
+ ...index === hashTagCandidateIndex ? styles$7.mentionSuggestionRowActive : {}
238566
+ },
238567
+ onMouseEnter: () => {
238568
+ setHashTagCandidateIndex(index);
237993
238569
  },
237994
- children: [
237995
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
237996
- style: {
237997
- whiteSpace: "nowrap",
237998
- overflow: "hidden",
237999
- textOverflow: "ellipsis",
238000
- fontWeight: 600
238001
- },
238002
- children: pendingArticle.article.kind === "existing" ? pendingArticle.article.detail.title : pendingArticle.article.draft.title
238003
- }),
238004
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238005
- style: {
238006
- color: arkmeTheme.secondary,
238007
- fontSize: 12,
238008
- marginTop: 4
238009
- },
238010
- children: pendingArticle.sending ? "长文发送中…" : "长文将单独发送,原文字和附件保留"
238011
- }),
238012
- pendingArticle.error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238013
- role: "alert",
238014
- style: {
238015
- color: arkmeTheme.danger,
238016
- fontSize: 12
238017
- },
238570
+ onMouseDown: (event) => {
238571
+ event.preventDefault();
238572
+ insertHashTagCandidate(item);
238573
+ },
238574
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238575
+ style: {
238576
+ ...styles$7.mentionSuggestionBotAvatar,
238577
+ flex: "none",
238578
+ fontWeight: 600
238579
+ },
238580
+ "aria-hidden": true,
238581
+ children: "#"
238582
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
238583
+ style: styles$7.mentionSuggestionText,
238584
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238585
+ style: styles$7.mentionSuggestionName,
238586
+ children: item.tagText
238587
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
238588
+ style: styles$7.mentionSuggestionSecondary,
238018
238589
  children: [
238019
- pendingArticle.error,
238590
+ tr$1("使用"),
238591
+ " ",
238592
+ item.recordCount,
238020
238593
  " ",
238021
- tr$1("· 点击发送重试")
238594
+ tr$1("次")
238022
238595
  ]
238023
- })
238024
- ]
238025
- }),
238026
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238027
- type: "button",
238028
- "aria-label": tr$1("移除待发送长文"),
238029
- disabled: pendingArticle.sending,
238030
- style: {
238031
- color: arkmeTheme.secondary,
238032
- background: "transparent",
238033
- border: 0,
238034
- cursor: "pointer",
238035
- fontSize: 20
238596
+ })]
238597
+ })]
238598
+ }, `${item.normalizedTag}:${item.tagText}`)), hashTagError && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238599
+ role: "status",
238600
+ style: styles$7.mentionSuggestionsEmpty,
238601
+ children: [tr$1("标签加载失败,"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238602
+ type: "button",
238603
+ onMouseDown: (event) => event.preventDefault(),
238604
+ onClick: () => hashTagRetryRef.current?.(),
238605
+ children: tr$1("重试")
238606
+ })]
238607
+ })]
238608
+ }),
238609
+ mentionTrigger !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238610
+ style: styles$7.mentionSuggestions,
238611
+ role: "listbox",
238612
+ "aria-label": tr$1("选择要 @ 的对象"),
238613
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMentionSuggestionThemeStyles, {}), mentionCandidates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238614
+ style: styles$7.mentionSuggestionsEmpty,
238615
+ children: tr$1("暂无可 @ 的对象")
238616
+ }) : mentionCandidates.map((member, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMentionSuggestionRow, {
238617
+ candidate: member,
238618
+ active: index === mentionCandidateIndex,
238619
+ styles: {
238620
+ row: styles$7.mentionSuggestionRow,
238621
+ rowActive: styles$7.mentionSuggestionRowActive,
238622
+ avatar: styles$7.mentionSuggestionAvatar,
238623
+ botAvatar: styles$7.mentionSuggestionBotAvatar,
238624
+ text: styles$7.mentionSuggestionText,
238625
+ name: styles$7.mentionSuggestionName,
238626
+ secondary: styles$7.mentionSuggestionSecondary
238036
238627
  },
238037
- onClick: () => {
238038
- if (articleDraftKey) composerArticleStore.remove(articleDraftKey);
238628
+ onActive: () => {
238629
+ setMentionCandidateIndex(index);
238039
238630
  },
238040
- children: "×"
238041
- })
238042
- ]
238043
- }),
238044
- visibleComposerAttachments.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeAttachmentStrip, {
238045
- attachments: visibleComposerAttachments,
238046
- disabled: composerFilesDisabled,
238047
- onMove: (from, to) => {
238048
- if (composerFilesDisabled) return;
238049
- if (activeRecordReeditComposer === void 0) arkmeComposerDraftStore.moveAttachment(composerDraftKey, from, to);
238050
- else setRecordReeditComposer((current) => {
238051
- if (!sameArkmeRecordReeditSession(current, activeRecordReeditComposer)) return current;
238052
- const next = [...current.attachments];
238053
- const attachment = next[from];
238054
- if (attachment === void 0 || to < 0 || to >= next.length) return current;
238055
- next.splice(from, 1);
238056
- next.splice(to, 0, attachment);
238057
- return {
238058
- ...current,
238059
- attachments: next,
238060
- error: ""
238061
- };
238062
- });
238063
- },
238064
- canPreview: (attachment) => activeRecordReeditComposer === void 0 ? attachment.localFile !== void 0 : activeRecordReeditComposer.attachments.some((view) => arkmeAttachmentId(view) === arkmeAttachmentId(attachment) && arkmeRecordReeditAttachmentBlock(view) !== void 0),
238065
- onPreview: (attachment) => {
238066
- if (activeRecordReeditComposer === void 0) {
238067
- if (attachment.localFile !== void 0) {
238068
- const block = localFileBlock(attachment.localFile);
238069
- if (attachmentPreviewBridge()?.version === 1) try {
238070
- openSessionAttachmentPreview(attachments.flatMap((value) => value.localFile === void 0 ? [] : [localFileBlock(value.localFile)]), block, "composer");
238071
- } catch {
238072
- setError("无法创建预览窗口,请再次点击附件重试");
238073
- }
238074
- else setDraftPreview(block);
238075
- }
238076
- } else {
238077
- const view = activeRecordReeditComposer.attachments.find((view) => arkmeAttachmentId(view) === arkmeAttachmentId(attachment));
238078
- if (view !== void 0) {
238079
- const block = arkmeRecordReeditAttachmentBlock(view);
238080
- if (block !== void 0 && attachmentPreviewBridge()?.version === 1) try {
238081
- openSessionAttachmentPreview(activeRecordReeditComposer.attachments.flatMap((value) => {
238082
- const item = arkmeRecordReeditAttachmentBlock(value);
238083
- return item === void 0 ? [] : [item];
238084
- }), block, "composer-reedit");
238085
- } catch {
238086
- setError("无法创建预览窗口,请再次点击附件重试");
238087
- }
238088
- else setDraftPreview(block);
238631
+ onSelect: () => {
238632
+ insertMentionCandidate(member);
238089
238633
  }
238090
- }
238091
- },
238092
- onRemove: (attachment) => {
238093
- if (composerFilesDisabled) return;
238094
- if (activeRecordReeditComposer !== void 0) {
238095
- setRecordReeditComposer((current) => sameArkmeRecordReeditSession(current, activeRecordReeditComposer) ? {
238096
- ...current,
238097
- attachments: current.attachments.filter((view) => arkmeAttachmentId(view) !== arkmeAttachmentId(attachment)),
238098
- error: ""
238099
- } : current);
238100
- setDraftPreview(void 0);
238101
- return;
238102
- }
238103
- arkmeComposerDraftStore.removeAttachment(composerDraftKey, arkmeAttachmentId(attachment));
238104
- if (attachment.localFile !== void 0) callArkme("files.local.remove", { fileRef: attachment.localFile.fileRef }).catch((caught) => setError(errorMessage$1(caught)));
238105
- }
238106
- }),
238107
- activeRecordReeditComposer?.attachments.some((attachment) => attachment.unavailable) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238108
- role: "status",
238109
- style: styles$7.error,
238110
- children: tr$1("部分附件不可用,请移除后重新添加")
238111
- }),
238112
- activeConversation && draftPreview !== void 0 && typeof document !== "undefined" && (0, react_dom$1.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMediaPreview, {
238113
- selected: draftPreview,
238114
- blocks: activeRecordReeditComposer === void 0 ? attachments.flatMap((attachment) => attachment.localFile === void 0 ? [] : [localFileBlock(attachment.localFile)]) : activeRecordReeditComposer.attachments.flatMap((attachment) => {
238115
- const block = arkmeRecordReeditAttachmentBlock(attachment);
238116
- return block === void 0 ? [] : [block];
238634
+ }, arkmeMentionCandidateKey(member)))]
238117
238635
  }),
238118
- onSelect: setDraftPreview,
238119
- onClose: () => setDraftPreview(void 0),
238120
- openLocalFile: false
238121
- }), document.body),
238122
- activeRecordReeditComposer === void 0 && hashTagTrigger !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238123
- ref: hashTagSuggestionListRef,
238124
- style: styles$7.mentionSuggestions,
238125
- role: "listbox",
238126
- "aria-label": tr$1("选择标签"),
238127
- children: [hashTagCandidates.length === 0 && !hashTagError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238128
- style: styles$7.mentionSuggestionsEmpty,
238129
- children: hashTagLoading ? "正在加载标签…" : "暂无匹配标签,可继续输入创建新标签"
238130
- }) : hashTagCandidates.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238131
- "data-arkme-feedback": "neutral",
238132
- type: "button",
238133
- role: "option",
238134
- "aria-selected": index === hashTagCandidateIndex,
238636
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeRichComposerInput, {
238637
+ textFormat: activeRecordReeditComposer?.snapshot?.textFormat ?? activeRecordReeditComposer?.item.textFormat ?? "plain",
238638
+ markdownEnabled: activeRecordReeditComposer === void 0 && markdownQuickNotesEnabled,
238639
+ className: "arkme-conversation-textarea",
238640
+ ref: textareaRef,
238135
238641
  style: {
238136
- ...styles$7.mentionSuggestionRow,
238137
- ...index === hashTagCandidateIndex ? styles$7.mentionSuggestionRowActive : {}
238642
+ ...styles$7.textarea,
238643
+ ...composerResize.editorStyle
238138
238644
  },
238139
- onMouseEnter: () => {
238140
- setHashTagCandidateIndex(index);
238645
+ value: visibleComposerText,
238646
+ mentions: activeRecordReeditComposer === void 0 ? composerDraft.mentions : activeRecordReeditComposer.mentions ?? [],
238647
+ emojis: activeRecordReeditComposer === void 0 ? composerDraft.emojis : [],
238648
+ maxLength: activeRecordReeditComposer?.snapshot?.maxTextLength ?? 2e4,
238649
+ placeholder: effectiveComposerPlaceholder,
238650
+ ariaLabel: activeRecordReeditComposer === void 0 ? effectiveComposerPlaceholder : "重新编辑快记",
238651
+ disabled: composerFilesDisabled,
238652
+ selectionRequest: activeConversation && !composerFilesDisabled && editedComposerSelection?.scope === composerAsyncScopeRef.current && authenticatedAccountKey === editedComposerSelection.scope.accountKey && activeRecordReeditComposer?.generation === editedComposerSelection.reeditGeneration ? editedComposerSelection.request : void 0,
238653
+ markdown: activeRecordReeditComposer === void 0 && !directAdmission.blocked ? composerDraft.markdown : void 0,
238654
+ onMarkdownChange: (markdown, text, mentions, emojis) => {
238655
+ if (activeRecordReeditComposer === void 0 && !directAdmission.blocked) arkmeComposerDraftStore.setMarkdown(composerDraftKey, markdown, text, mentions, emojis);
238141
238656
  },
238142
- onMouseDown: (event) => {
238143
- event.preventDefault();
238144
- insertHashTagCandidate(item);
238657
+ onTextChange: updateComposerText,
238658
+ onInputActivity: messagePreparing.input,
238659
+ onFocus: () => {
238660
+ messagePreparing.focus(true);
238661
+ setComposerInputFocused(true);
238145
238662
  },
238146
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238147
- style: {
238148
- ...styles$7.mentionSuggestionBotAvatar,
238149
- flex: "none",
238150
- fontWeight: 600
238151
- },
238152
- "aria-hidden": true,
238153
- children: "#"
238154
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
238155
- style: styles$7.mentionSuggestionText,
238156
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238157
- style: styles$7.mentionSuggestionName,
238158
- children: item.tagText
238159
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
238160
- style: styles$7.mentionSuggestionSecondary,
238161
- children: [
238162
- tr$1("使用"),
238163
- " ",
238164
- item.recordCount,
238165
- " ",
238166
- tr$1("次")
238167
- ]
238168
- })]
238169
- })]
238170
- }, `${item.normalizedTag}:${item.tagText}`)), hashTagError && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238171
- role: "status",
238172
- style: styles$7.mentionSuggestionsEmpty,
238173
- children: [tr$1("标签加载失败,"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
238174
- type: "button",
238175
- onMouseDown: (event) => event.preventDefault(),
238176
- onClick: () => hashTagRetryRef.current?.(),
238177
- children: tr$1("重试")
238178
- })]
238179
- })]
238180
- }),
238181
- mentionTrigger !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238182
- style: styles$7.mentionSuggestions,
238183
- role: "listbox",
238184
- "aria-label": tr$1("选择要 @ 的对象"),
238185
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMentionSuggestionThemeStyles, {}), mentionCandidates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238186
- style: styles$7.mentionSuggestionsEmpty,
238187
- children: tr$1("暂无可 @ 的对象")
238188
- }) : mentionCandidates.map((member, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMentionSuggestionRow, {
238189
- candidate: member,
238190
- active: index === mentionCandidateIndex,
238191
- styles: {
238192
- row: styles$7.mentionSuggestionRow,
238193
- rowActive: styles$7.mentionSuggestionRowActive,
238194
- avatar: styles$7.mentionSuggestionAvatar,
238195
- botAvatar: styles$7.mentionSuggestionBotAvatar,
238196
- text: styles$7.mentionSuggestionText,
238197
- name: styles$7.mentionSuggestionName,
238198
- secondary: styles$7.mentionSuggestionSecondary
238663
+ onBlur: () => {
238664
+ messagePreparing.focus(false);
238665
+ setComposerInputFocused(false);
238199
238666
  },
238200
- onActive: () => {
238201
- setMentionCandidateIndex(index);
238667
+ onSelectionChange: updateComposerRichTrigger,
238668
+ onPaste: (event) => {
238669
+ if (composerFileAddingDisabled) return;
238670
+ const files = arkmeClipboardFiles(event.clipboardData);
238671
+ if (files.length === 0) return;
238672
+ event.preventDefault();
238673
+ const restoreFocus = beginPasteFocus();
238674
+ setEditedComposerSelection(void 0);
238675
+ selectFiles(files, true).finally(restoreFocus);
238202
238676
  },
238203
- onSelect: () => {
238204
- insertMentionCandidate(member);
238205
- }
238206
- }, arkmeMentionCandidateKey(member)))]
238207
- }),
238208
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeRichComposerInput, {
238209
- textFormat: activeRecordReeditComposer?.snapshot?.textFormat ?? activeRecordReeditComposer?.item.textFormat ?? "plain",
238210
- markdownEnabled: activeRecordReeditComposer === void 0 && markdownQuickNotesEnabled,
238211
- className: "arkme-conversation-textarea",
238212
- ref: textareaRef,
238213
- style: {
238214
- ...styles$7.textarea,
238215
- ...composerResize.editorStyle
238216
- },
238217
- value: visibleComposerText,
238218
- mentions: activeRecordReeditComposer === void 0 ? composerDraft.mentions : activeRecordReeditComposer.mentions ?? [],
238219
- emojis: activeRecordReeditComposer === void 0 ? composerDraft.emojis : [],
238220
- maxLength: activeRecordReeditComposer?.snapshot?.maxTextLength ?? 2e4,
238221
- placeholder: effectiveComposerPlaceholder,
238222
- ariaLabel: activeRecordReeditComposer === void 0 ? effectiveComposerPlaceholder : "重新编辑快记",
238223
- disabled: composerFilesDisabled,
238224
- selectionRequest: activeConversation && !composerFilesDisabled && editedComposerSelection?.scope === composerAsyncScopeRef.current && authenticatedAccountKey === editedComposerSelection.scope.accountKey && activeRecordReeditComposer?.generation === editedComposerSelection.reeditGeneration ? editedComposerSelection.request : void 0,
238225
- markdown: activeRecordReeditComposer === void 0 && !directAdmission.blocked ? composerDraft.markdown : void 0,
238226
- onMarkdownChange: (markdown, text, mentions, emojis) => {
238227
- if (activeRecordReeditComposer === void 0 && !directAdmission.blocked) arkmeComposerDraftStore.setMarkdown(composerDraftKey, markdown, text, mentions, emojis);
238228
- },
238229
- onTextChange: updateComposerText,
238230
- onInputActivity: messagePreparing.input,
238231
- onFocus: () => {
238232
- messagePreparing.focus(true);
238233
- setComposerInputFocused(true);
238234
- },
238235
- onBlur: () => {
238236
- messagePreparing.focus(false);
238237
- setComposerInputFocused(false);
238238
- },
238239
- onSelectionChange: updateComposerRichTrigger,
238240
- onPaste: (event) => {
238241
- if (composerFileAddingDisabled) return;
238242
- const files = arkmeClipboardFiles(event.clipboardData);
238243
- if (files.length === 0) return;
238244
- event.preventDefault();
238245
- const restoreFocus = beginPasteFocus();
238246
- setEditedComposerSelection(void 0);
238247
- selectFiles(files, true).finally(restoreFocus);
238248
- },
238249
- onKeyDown: (event) => {
238250
- if (event.nativeEvent.isComposing) return;
238251
- if (activeRecordReeditComposer === void 0 && hashTagTrigger !== void 0) {
238252
- if (event.key === "Escape") {
238253
- event.preventDefault();
238254
- dismissedHashTagStartRef.current = hashTagTrigger.startIndex;
238255
- setHashTagTrigger(void 0);
238256
- return;
238257
- }
238258
- if (event.key === "ArrowDown" && hashTagCandidates.length > 0) {
238259
- event.preventDefault();
238260
- setHashTagCandidateIndex((index) => (index + 1) % hashTagCandidates.length);
238261
- return;
238262
- }
238263
- if (event.key === "ArrowUp" && hashTagCandidates.length > 0) {
238264
- event.preventDefault();
238265
- setHashTagCandidateIndex((index) => (index + hashTagCandidates.length - 1) % hashTagCandidates.length);
238266
- return;
238267
- }
238268
- if ((event.key === "Enter" || event.key === "Tab") && hashTagCandidates.length > 0) {
238269
- event.preventDefault();
238270
- const selectedCandidate = hashTagCandidates[Math.min(hashTagCandidateIndex, hashTagCandidates.length - 1)];
238271
- if (selectedCandidate !== void 0) insertHashTagCandidate(selectedCandidate);
238272
- return;
238273
- }
238274
- }
238275
- if (mentionTrigger !== void 0) {
238276
- if (event.key === "Escape") {
238277
- event.preventDefault();
238278
- setMentionTrigger(void 0);
238279
- return;
238677
+ onKeyDown: (event) => {
238678
+ if (event.nativeEvent.isComposing) return;
238679
+ if (activeRecordReeditComposer === void 0 && hashTagTrigger !== void 0) {
238680
+ if (event.key === "Escape") {
238681
+ event.preventDefault();
238682
+ dismissedHashTagStartRef.current = hashTagTrigger.startIndex;
238683
+ setHashTagTrigger(void 0);
238684
+ return;
238685
+ }
238686
+ if (event.key === "ArrowDown" && hashTagCandidates.length > 0) {
238687
+ event.preventDefault();
238688
+ setHashTagCandidateIndex((index) => (index + 1) % hashTagCandidates.length);
238689
+ return;
238690
+ }
238691
+ if (event.key === "ArrowUp" && hashTagCandidates.length > 0) {
238692
+ event.preventDefault();
238693
+ setHashTagCandidateIndex((index) => (index + hashTagCandidates.length - 1) % hashTagCandidates.length);
238694
+ return;
238695
+ }
238696
+ if ((event.key === "Enter" || event.key === "Tab") && hashTagCandidates.length > 0) {
238697
+ event.preventDefault();
238698
+ const selectedCandidate = hashTagCandidates[Math.min(hashTagCandidateIndex, hashTagCandidates.length - 1)];
238699
+ if (selectedCandidate !== void 0) insertHashTagCandidate(selectedCandidate);
238700
+ return;
238701
+ }
238280
238702
  }
238281
- if (event.key === "ArrowDown" && mentionCandidates.length > 0) {
238282
- event.preventDefault();
238283
- setMentionCandidateIndex((index) => (index + 1) % mentionCandidates.length);
238284
- return;
238703
+ if (mentionTrigger !== void 0) {
238704
+ if (event.key === "Escape") {
238705
+ event.preventDefault();
238706
+ setMentionTrigger(void 0);
238707
+ return;
238708
+ }
238709
+ if (event.key === "ArrowDown" && mentionCandidates.length > 0) {
238710
+ event.preventDefault();
238711
+ setMentionCandidateIndex((index) => (index + 1) % mentionCandidates.length);
238712
+ return;
238713
+ }
238714
+ if (event.key === "ArrowUp" && mentionCandidates.length > 0) {
238715
+ event.preventDefault();
238716
+ setMentionCandidateIndex((index) => (index + mentionCandidates.length - 1) % mentionCandidates.length);
238717
+ return;
238718
+ }
238719
+ if ((event.key === "Enter" || event.key === "Tab") && mentionCandidates.length > 0) {
238720
+ event.preventDefault();
238721
+ const selectedCandidate = mentionCandidates[Math.min(mentionCandidateIndex, mentionCandidates.length - 1)];
238722
+ if (selectedCandidate !== void 0) insertMentionCandidate(selectedCandidate);
238723
+ return;
238724
+ }
238285
238725
  }
238286
- if (event.key === "ArrowUp" && mentionCandidates.length > 0) {
238287
- event.preventDefault();
238288
- setMentionCandidateIndex((index) => (index + mentionCandidates.length - 1) % mentionCandidates.length);
238289
- return;
238726
+ if (activeRecordReeditComposer !== void 0 && !event.nativeEvent.isComposing && (event.key === "Backspace" || event.key === "Delete")) {
238727
+ const deletion = arkmeComposerAtomicDeletion(visibleComposerText, activeRecordReeditComposer.mentions ?? [], textareaRef.current?.selectionStart ?? visibleComposerText.length, textareaRef.current?.selectionEnd ?? visibleComposerText.length, event.key === "Backspace" ? "backward" : "forward");
238728
+ if (deletion) {
238729
+ event.preventDefault();
238730
+ updateComposerText(deletion.text);
238731
+ focusEditedComposer(deletion.caretIndex);
238732
+ return;
238733
+ }
238290
238734
  }
238291
- if ((event.key === "Enter" || event.key === "Tab") && mentionCandidates.length > 0) {
238292
- event.preventDefault();
238293
- const selectedCandidate = mentionCandidates[Math.min(mentionCandidateIndex, mentionCandidates.length - 1)];
238294
- if (selectedCandidate !== void 0) insertMentionCandidate(selectedCandidate);
238295
- return;
238735
+ if (activeRecordReeditComposer === void 0 && !event.nativeEvent.isComposing && (event.key === "Backspace" || event.key === "Delete")) {
238736
+ const caret = arkmeComposerDraftStore.deleteMentionAtSelection(composerDraftKey, textareaRef.current?.selectionStart ?? draft.length, textareaRef.current?.selectionEnd ?? draft.length, event.key === "Backspace" ? "backward" : "forward");
238737
+ if (caret !== void 0) {
238738
+ event.preventDefault();
238739
+ focusEditedComposer(caret);
238740
+ return;
238741
+ }
238296
238742
  }
238297
- }
238298
- if (activeRecordReeditComposer !== void 0 && !event.nativeEvent.isComposing && (event.key === "Backspace" || event.key === "Delete")) {
238299
- const deletion = arkmeComposerAtomicDeletion(visibleComposerText, activeRecordReeditComposer.mentions ?? [], textareaRef.current?.selectionStart ?? visibleComposerText.length, textareaRef.current?.selectionEnd ?? visibleComposerText.length, event.key === "Backspace" ? "backward" : "forward");
238300
- if (deletion) {
238743
+ if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
238301
238744
  event.preventDefault();
238302
- updateComposerText(deletion.text);
238303
- focusEditedComposer(deletion.caretIndex);
238304
- return;
238745
+ if (canSend) send();
238305
238746
  }
238306
238747
  }
238307
- if (activeRecordReeditComposer === void 0 && !event.nativeEvent.isComposing && (event.key === "Backspace" || event.key === "Delete")) {
238308
- const caret = arkmeComposerDraftStore.deleteMentionAtSelection(composerDraftKey, textareaRef.current?.selectionStart ?? draft.length, textareaRef.current?.selectionEnd ?? draft.length, event.key === "Backspace" ? "backward" : "forward");
238309
- if (caret !== void 0) {
238310
- event.preventDefault();
238311
- focusEditedComposer(caret);
238312
- return;
238748
+ }, activeRecordReeditComposer === void 0 ? composerDraftKey : `record-reedit:${activeRecordReeditComposer.generation}`)
238749
+ ]
238750
+ }),
238751
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238752
+ "data-arkme-composer-footer": "tools",
238753
+ style: styles$7.tools,
238754
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238755
+ style: styles$7.toolGroup,
238756
+ children: [
238757
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerToolButton, {
238758
+ ref: addMenuTriggerRef,
238759
+ onPointerDown: (event) => event.stopPropagation(),
238760
+ "aria-label": tr$1("添加内容"),
238761
+ "aria-haspopup": "menu",
238762
+ "aria-expanded": addMenuOpen,
238763
+ disabled: composerFileAddingDisabled,
238764
+ onClick: () => {
238765
+ setAddMenuOpen((value) => !value);
238766
+ },
238767
+ children: (activeRecordReeditComposer === void 0 ? preparingFiles : preparingReeditFiles) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeFilePreparingIndicator, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerPlusIcon, {})
238768
+ }),
238769
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeEmojiPicker, {
238770
+ accountKey: authenticatedAccountKey,
238771
+ disabled: activeSelectMode !== void 0 || preparingFiles || directAdmission.blocked || activeRecordReeditComposer !== void 0,
238772
+ scopeKey: composerDraftKey,
238773
+ ...source?.kind === "private_chat" || source?.kind === "group_chat" ? { sourceRef: source.sourceRef } : {},
238774
+ getCaretGeometry: () => textareaRef.current?.getCaretGeometry(),
238775
+ getEditorGeometry: () => textareaRef.current?.getEditorGeometry(),
238776
+ onSelect: insertEmoji,
238777
+ onUploadSticker: async (file) => {
238778
+ if (composerDraftKey === void 0) throw new Error("请先选择聊天");
238779
+ return await uploadFavoriteSticker(file);
238780
+ },
238781
+ onStickerSent: async () => {
238782
+ if (!sameComposerAsyncScope(renderedComposerAsyncScope)) return;
238783
+ await loadTimeline(void 0, false, 40, "return-to-latest");
238784
+ },
238785
+ onError: (message) => {
238786
+ setError(message);
238313
238787
  }
238314
- }
238315
- if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
238316
- event.preventDefault();
238317
- if (canSend) send();
238318
- }
238319
- }
238320
- }, activeRecordReeditComposer === void 0 ? composerDraftKey : `record-reedit:${activeRecordReeditComposer.generation}`)
238321
- ]
238322
- }),
238323
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238324
- "data-arkme-composer-footer": "tools",
238325
- style: styles$7.tools,
238326
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238327
- style: styles$7.toolGroup,
238328
- children: [
238329
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerToolButton, {
238330
- ref: addMenuTriggerRef,
238331
- onPointerDown: (event) => event.stopPropagation(),
238332
- "aria-label": tr$1("添加内容"),
238333
- "aria-haspopup": "menu",
238334
- "aria-expanded": addMenuOpen,
238335
- disabled: composerFileAddingDisabled,
238336
- onClick: () => {
238337
- setAddMenuOpen((value) => !value);
238338
- },
238339
- children: (activeRecordReeditComposer === void 0 ? preparingFiles : preparingReeditFiles) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeFilePreparingIndicator, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerPlusIcon, {})
238340
- }),
238341
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeEmojiPicker, {
238788
+ }, `emoji-picker:${authenticatedAccountKey}:${conversationOverlayKey}`),
238789
+ authenticatedUserId !== void 0 && activeRecordReeditComposer === void 0 && arkmeSourceSupportsRecordInputCapture(source?.kind) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerScreenshotButton, {
238790
+ userId: authenticatedUserId,
238791
+ scope: composerAsyncScopeRef.current,
238792
+ active: activeConversation,
238793
+ disabled: composerFileAddingDisabled || activeSelectMode !== void 0 || !activeConversation,
238794
+ isCurrent: () => sameComposerAsyncScope(renderedComposerAsyncScope) && recordReeditComposerRef.current === void 0,
238795
+ onBegin: (options) => {
238796
+ syncComposerUserInput(true);
238797
+ textareaRef.current?.focus({ preventScroll: true });
238798
+ return beginPasteFocus({
238799
+ nativeDialog: true,
238800
+ ...options
238801
+ });
238802
+ },
238803
+ onFile: (file) => selectFiles([file], true),
238804
+ onError: (message) => setError(message)
238805
+ })
238806
+ ]
238807
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238808
+ style: styles$7.composerSendArea,
238809
+ children: [authenticatedUserId !== void 0 && authenticatedAccountKey !== void 0 && source !== void 0 && isArkmeSelfWorkspaceSource(source) && activeRecordReeditComposer === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelfRolePicker, {
238342
238810
  accountKey: authenticatedAccountKey,
238343
- disabled: activeSelectMode !== void 0 || preparingFiles || directAdmission.blocked || activeRecordReeditComposer !== void 0,
238344
- scopeKey: composerDraftKey,
238345
- ...source?.kind === "private_chat" || source?.kind === "group_chat" ? { sourceRef: source.sourceRef } : {},
238346
- getCaretGeometry: () => textareaRef.current?.getCaretGeometry(),
238347
- getEditorGeometry: () => textareaRef.current?.getEditorGeometry(),
238348
- onSelect: insertEmoji,
238349
- onUploadSticker: async (file) => {
238350
- if (composerDraftKey === void 0) throw new Error("请先选择聊天");
238351
- return await uploadFavoriteSticker(file);
238352
- },
238353
- onStickerSent: async () => {
238354
- if (!sameComposerAsyncScope(renderedComposerAsyncScope)) return;
238355
- await loadTimeline(void 0, false, 40, "return-to-latest");
238356
- },
238357
- onError: (message) => {
238358
- setError(message);
238359
- }
238360
- }, `emoji-picker:${authenticatedAccountKey}:${conversationOverlayKey}`),
238361
- authenticatedUserId !== void 0 && activeRecordReeditComposer === void 0 && arkmeSourceSupportsRecordInputCapture(source?.kind) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerScreenshotButton, {
238362
238811
  userId: authenticatedUserId,
238363
- scope: composerAsyncScopeRef.current,
238364
- active: activeConversation,
238365
- disabled: composerFileAddingDisabled || activeSelectMode !== void 0 || !activeConversation,
238366
- isCurrent: () => sameComposerAsyncScope(renderedComposerAsyncScope) && recordReeditComposerRef.current === void 0,
238367
- onBegin: (options) => {
238368
- syncComposerUserInput(true);
238369
- textareaRef.current?.focus({ preventScroll: true });
238370
- return beginPasteFocus({
238371
- nativeDialog: true,
238372
- ...options
238373
- });
238374
- },
238375
- onFile: (file) => selectFiles([file], true),
238376
- onError: (message) => setError(message)
238377
- })
238378
- ]
238379
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238380
- style: styles$7.composerSendArea,
238381
- children: [authenticatedUserId !== void 0 && authenticatedAccountKey !== void 0 && source !== void 0 && isArkmeSelfWorkspaceSource(source) && activeRecordReeditComposer === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelfRolePicker, {
238382
- accountKey: authenticatedAccountKey,
238383
- userId: authenticatedUserId,
238384
- selectedRole: selectedSelfRole,
238385
- onSelect: setSelectedSelfRole,
238386
- selfAvatarRef: selfProfile?.avatarRef,
238387
- disabled: composerFilesDisabled || activeSelectMode !== void 0
238388
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerSendButton, {
238389
- disabled: !canSend,
238390
- ariaLabel: activeRecordReeditComposer === void 0 ? pendingArticle ? "发送长文" : tr$1("发送消息") : "保存重新编辑",
238391
- shortcutHint: tr$1("Enter发送 / Shift+Enter换行"),
238392
- onClick: () => {
238393
- send();
238394
- }
238812
+ selectedRole: selectedSelfRole,
238813
+ onSelect: setSelectedSelfRole,
238814
+ selfAvatarRef: selfProfile?.avatarRef,
238815
+ disabled: composerFilesDisabled || activeSelectMode !== void 0
238816
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeComposerSendButton, {
238817
+ disabled: !canSend,
238818
+ ariaLabel: activeRecordReeditComposer === void 0 ? pendingArticle ? "发送长文" : tr$1("发送消息") : "保存重新编辑",
238819
+ shortcutHint: tr$1("Enter发送 / Shift+Enter换行"),
238820
+ onClick: () => {
238821
+ send();
238822
+ }
238823
+ })]
238395
238824
  })]
238396
- })]
238397
- }),
238398
- activeRecordReeditComposer === void 0 && arkmeSourceSupportsRecordInputCapture(source?.kind) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeBackgroundSoundWaveform, {
238399
- owner: recordInputCaptureOwner,
238400
- draftKey: composerDraftKey
238401
- })
238402
- ]
238403
- })
238404
- ]
238405
- })
238406
- }),
238407
- activeSelectMode !== void 0 && selectedMessageCount > 0 && !selectedMessagesSupportSnapshotBatch && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238408
- role: "status",
238409
- style: {
238410
- padding: "6px 16px",
238411
- color: arkmeTheme.secondary,
238412
- fontSize: 12
238413
- },
238414
- children: selectedMessageCount > 100 ? `已选择 ${selectedMessageCount} 条消息,批量操作最多支持 100 条,请减少选择后操作` : "选中的消息包含暂不支持复制链接或转发的内容,可取消这些消息后操作"
238415
- }),
238416
- activeSelectMode !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238417
- style: {
238418
- ...styles$7.selectBar,
238419
- flexWrap: "wrap"
238420
- },
238421
- role: "toolbar",
238422
- "aria-label": tr$1("已选择 {v0} 条消息", { v0: selectedMessageCount }),
238423
- children: [
238424
- askDsh.status && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238425
- role: "status",
238426
- "aria-live": "polite",
238427
- style: {
238428
- flexBasis: "100%",
238429
- textAlign: "center",
238430
- color: arkmeTheme.secondary,
238431
- fontSize: 12,
238432
- overflowWrap: "anywhere"
238433
- },
238434
- children: askDsh.status
238435
- }),
238436
- source !== void 0 && isArkmeSelfWorkspaceSource(source) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238437
- "data-arkme-feedback": "neutral",
238438
- type: "button",
238439
- "aria-label": tr$1("指定主题"),
238440
- style: styles$7.selectBarButton,
238441
- disabled: !canAssignRecordTopics(selectedMessageItems) || selectedMessageItems.length !== selectedMessageCount,
238442
- onClick: (event) => {
238443
- if (selectedMessageItems.length !== selectedMessageCount) return;
238444
- openRecordTopicAssignment(selectedMessageItems, event.currentTarget);
238445
- },
238446
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238447
- style: styles$7.selectBarIconTile,
238448
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, {
238449
- kind: "assign",
238450
- size: 20
238825
+ }),
238826
+ activeRecordReeditComposer === void 0 && arkmeSourceSupportsRecordInputCapture(source?.kind) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeBackgroundSoundWaveform, {
238827
+ owner: recordInputCaptureOwner,
238828
+ draftKey: composerDraftKey
238829
+ })
238830
+ ]
238451
238831
  })
238452
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238453
- style: styles$7.selectBarLabel,
238454
- children: tr$1("指定主题")
238455
- })]
238456
- }),
238457
- (() => {
238458
- const copyTextEnabled = arkmeCanCopySelectedMessageText(selectedMessageItems.length, messageActionBusy !== void 0);
238459
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238832
+ ]
238833
+ })
238834
+ }),
238835
+ activeSelectMode !== void 0 && selectedMessageCount > 0 && !selectedMessagesSupportSnapshotBatch && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238836
+ role: "status",
238837
+ style: {
238838
+ padding: "6px 16px",
238839
+ color: arkmeTheme.secondary,
238840
+ fontSize: 12
238841
+ },
238842
+ children: selectedMessageCount > 100 ? `已选择 ${selectedMessageCount} 条消息,批量操作最多支持 100 条,请减少选择后操作` : "选中的消息包含暂不支持复制链接或转发的内容,可取消这些消息后操作"
238843
+ }),
238844
+ activeSelectMode !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238845
+ style: {
238846
+ ...styles$7.selectBar,
238847
+ flexWrap: "wrap"
238848
+ },
238849
+ role: "toolbar",
238850
+ "aria-label": tr$1("已选择 {v0} 条消息", { v0: selectedMessageCount }),
238851
+ children: [
238852
+ askDsh.status && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
238853
+ role: "status",
238854
+ "aria-live": "polite",
238855
+ style: {
238856
+ flexBasis: "100%",
238857
+ textAlign: "center",
238858
+ color: arkmeTheme.secondary,
238859
+ fontSize: 12,
238860
+ overflowWrap: "anywhere"
238861
+ },
238862
+ children: askDsh.status
238863
+ }),
238864
+ source !== void 0 && isArkmeSelfWorkspaceSource(source) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238865
+ "data-arkme-feedback": "neutral",
238866
+ type: "button",
238867
+ "aria-label": tr$1("指定主题"),
238868
+ style: styles$7.selectBarButton,
238869
+ disabled: !canAssignRecordTopics(selectedMessageItems) || selectedMessageItems.length !== selectedMessageCount,
238870
+ onClick: (event) => {
238871
+ if (selectedMessageItems.length !== selectedMessageCount) return;
238872
+ openRecordTopicAssignment(selectedMessageItems, event.currentTarget);
238873
+ },
238874
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238875
+ style: styles$7.selectBarIconTile,
238876
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, {
238877
+ kind: "assign",
238878
+ size: 20
238879
+ })
238880
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238881
+ style: styles$7.selectBarLabel,
238882
+ children: tr$1("指定主题")
238883
+ })]
238884
+ }),
238885
+ (() => {
238886
+ const copyTextEnabled = arkmeCanCopySelectedMessageText(selectedMessageItems.length, messageActionBusy !== void 0);
238887
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238888
+ "data-arkme-feedback": "neutral",
238889
+ type: "button",
238890
+ style: {
238891
+ ...styles$7.selectBarButton,
238892
+ ...!copyTextEnabled ? styles$7.selectBarButtonDisabled : {}
238893
+ },
238894
+ disabled: !copyTextEnabled,
238895
+ onClick: () => {
238896
+ copySelectedMessageText();
238897
+ },
238898
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238899
+ style: styles$7.selectBarIconTile,
238900
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "copy" })
238901
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238902
+ style: styles$7.selectBarLabel,
238903
+ children: ARKME_MESSAGE_SELECT_ACTION_LABELS[0]
238904
+ })]
238905
+ });
238906
+ })(),
238907
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238460
238908
  "data-arkme-feedback": "neutral",
238461
238909
  type: "button",
238462
238910
  style: {
238463
238911
  ...styles$7.selectBarButton,
238464
- ...!copyTextEnabled ? styles$7.selectBarButtonDisabled : {}
238912
+ ...!selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238465
238913
  },
238466
- disabled: !copyTextEnabled,
238914
+ disabled: !selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0,
238467
238915
  onClick: () => {
238468
- copySelectedMessageText();
238916
+ copyMessageLink(selectedMessageItems);
238469
238917
  },
238470
238918
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238471
238919
  style: styles$7.selectBarIconTile,
238472
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "copy" })
238920
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "link" })
238473
238921
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238474
238922
  style: styles$7.selectBarLabel,
238475
- children: ARKME_MESSAGE_SELECT_ACTION_LABELS[0]
238923
+ children: ARKME_MESSAGE_SELECT_ACTION_LABELS[1]
238476
238924
  })]
238477
- });
238478
- })(),
238479
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238480
- "data-arkme-feedback": "neutral",
238481
- type: "button",
238482
- style: {
238483
- ...styles$7.selectBarButton,
238484
- ...!selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238485
- },
238486
- disabled: !selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0,
238487
- onClick: () => {
238488
- copyMessageLink(selectedMessageItems);
238489
- },
238490
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238491
- style: styles$7.selectBarIconTile,
238492
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "link" })
238493
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238494
- style: styles$7.selectBarLabel,
238495
- children: ARKME_MESSAGE_SELECT_ACTION_LABELS[1]
238496
- })]
238497
- }),
238498
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238499
- "data-arkme-feedback": "neutral",
238500
- type: "button",
238501
- style: {
238502
- ...styles$7.selectBarButton,
238503
- ...!selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238504
- },
238505
- disabled: !selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0,
238506
- onClick: () => {
238507
- openForwardTargetPicker();
238508
- },
238509
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238510
- style: styles$7.selectBarIconTile,
238511
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "forward" })
238512
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238513
- style: styles$7.selectBarLabel,
238514
- children: messageActionBusy === "forward" ? "转发中" : ARKME_MESSAGE_SELECT_ACTION_LABELS[2]
238515
- })]
238516
- }),
238517
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238518
- "data-arkme-feedback": "neutral",
238519
- type: "button",
238520
- "aria-label": "问 DSH",
238521
- title: selectedMessagesCanAskDsh ? "将所选快记及原件添加到 DSH 新对话,等待手动发送" : "请选择 1 至 100 条可读取的快记",
238522
- style: {
238523
- ...styles$7.selectBarButton,
238524
- ...!selectedMessagesCanAskDsh || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238525
- },
238526
- disabled: !selectedMessagesCanAskDsh || messageActionBusy !== void 0,
238527
- onClick: () => {
238528
- if (source) askDsh.run(source.sourceRef, askDshNotesWithLocalNames(selectedMessageItems, source, conversationMemberByRef, selfProfile));
238529
- },
238530
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238531
- style: styles$7.selectBarIconTile,
238532
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AskDshIcon, { size: 22 })
238533
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238534
- style: styles$7.selectBarLabel,
238535
- children: askDsh.busy ? "准备中" : "问 DSH"
238536
- })]
238537
- }),
238538
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238539
- "data-arkme-feedback": "danger",
238540
- type: "button",
238541
- "aria-label": tr$1("删除"),
238542
- title: selectedMessagesCanDelete ? tr$1("删除") : "包含他人或暂不可删除的快记",
238543
- style: {
238544
- ...styles$7.selectBarButton,
238545
- ...!selectedMessagesCanDelete || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238546
- },
238547
- disabled: !selectedMessagesCanDelete || messageActionBusy !== void 0,
238548
- onClick: () => {
238549
- if (source && selectedMessagesCanDelete && messageActionBusy === void 0) setRecordDeletion({
238550
- scopeKey: topicAssignmentScopeKey,
238551
- sourceRef: source.sourceRef,
238552
- items: [...selectedMessageItems]
238553
- });
238554
- },
238555
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238556
- style: styles$7.selectBarIconTile,
238557
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$9, { size: 22 })
238558
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238559
- style: styles$7.selectBarLabel,
238560
- children: tr$1("删除")
238561
- })]
238562
- }),
238563
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238564
- "data-arkme-feedback": "neutral",
238565
- type: "button",
238566
- style: {
238567
- ...styles$7.selectBarButton,
238568
- ...messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238569
- },
238570
- disabled: messageActionBusy !== void 0,
238571
- "aria-label": ARKME_MESSAGE_SELECT_ACTION_LABELS[3],
238572
- onClick: exitMessageSelectMode,
238573
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238574
- style: styles$7.selectBarIconTile,
238575
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, {
238576
- kind: "close",
238577
- size: 18
238578
- })
238579
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238580
- style: styles$7.selectBarLabel,
238581
- children: ARKME_MESSAGE_SELECT_ACTION_LABELS[3]
238582
- })]
238583
- })
238584
- ]
238585
- })
238586
- ]
238587
- })
238588
- ]
238925
+ }),
238926
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238927
+ "data-arkme-feedback": "neutral",
238928
+ type: "button",
238929
+ style: {
238930
+ ...styles$7.selectBarButton,
238931
+ ...!selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238932
+ },
238933
+ disabled: !selectedMessagesSupportSnapshotBatch || messageActionBusy !== void 0,
238934
+ onClick: () => {
238935
+ openForwardTargetPicker();
238936
+ },
238937
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238938
+ style: styles$7.selectBarIconTile,
238939
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, { kind: "forward" })
238940
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238941
+ style: styles$7.selectBarLabel,
238942
+ children: messageActionBusy === "forward" ? "转发中" : ARKME_MESSAGE_SELECT_ACTION_LABELS[2]
238943
+ })]
238944
+ }),
238945
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238946
+ "data-arkme-feedback": "neutral",
238947
+ type: "button",
238948
+ "aria-label": "问 DSH",
238949
+ title: selectedMessagesCanAskDsh ? "将所选快记及原件添加到 DSH 新对话,等待手动发送" : "请选择 1 至 100 条可读取的快记",
238950
+ style: {
238951
+ ...styles$7.selectBarButton,
238952
+ ...!selectedMessagesCanAskDsh || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238953
+ },
238954
+ disabled: !selectedMessagesCanAskDsh || messageActionBusy !== void 0,
238955
+ onClick: () => {
238956
+ if (source) askDsh.run(source.sourceRef, askDshNotesWithLocalNames(selectedMessageItems, source, conversationMemberByRef, selfProfile));
238957
+ },
238958
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238959
+ style: styles$7.selectBarIconTile,
238960
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AskDshIcon, { size: 22 })
238961
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238962
+ style: styles$7.selectBarLabel,
238963
+ children: askDsh.busy ? "准备中" : "问 DSH"
238964
+ })]
238965
+ }),
238966
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238967
+ "data-arkme-feedback": "danger",
238968
+ type: "button",
238969
+ "aria-label": tr$1("删除"),
238970
+ title: selectedMessagesCanDelete ? tr$1("删除") : "包含他人或暂不可删除的快记",
238971
+ style: {
238972
+ ...styles$7.selectBarButton,
238973
+ ...!selectedMessagesCanDelete || messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238974
+ },
238975
+ disabled: !selectedMessagesCanDelete || messageActionBusy !== void 0,
238976
+ onClick: () => {
238977
+ if (source && selectedMessagesCanDelete && messageActionBusy === void 0) setRecordDeletion({
238978
+ scopeKey: topicAssignmentScopeKey,
238979
+ sourceRef: source.sourceRef,
238980
+ items: [...selectedMessageItems]
238981
+ });
238982
+ },
238983
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238984
+ style: styles$7.selectBarIconTile,
238985
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$9, { size: 22 })
238986
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
238987
+ style: styles$7.selectBarLabel,
238988
+ children: tr$1("删除")
238989
+ })]
238990
+ }),
238991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
238992
+ "data-arkme-feedback": "neutral",
238993
+ type: "button",
238994
+ style: {
238995
+ ...styles$7.selectBarButton,
238996
+ ...messageActionBusy !== void 0 ? styles$7.selectBarButtonDisabled : {}
238997
+ },
238998
+ disabled: messageActionBusy !== void 0,
238999
+ "aria-label": ARKME_MESSAGE_SELECT_ACTION_LABELS[3],
239000
+ onClick: exitMessageSelectMode,
239001
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
239002
+ style: styles$7.selectBarIconTile,
239003
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeSelectActionIcon, {
239004
+ kind: "close",
239005
+ size: 18
239006
+ })
239007
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
239008
+ style: styles$7.selectBarLabel,
239009
+ children: ARKME_MESSAGE_SELECT_ACTION_LABELS[3]
239010
+ })]
239011
+ })
239012
+ ]
239013
+ })
239014
+ ]
239015
+ })
239016
+ ]
239017
+ })
238589
239018
  }),
238590
239019
  forwardDialog,
238591
239020
  activeConversation && messageMenu !== void 0 && messageMenuItem !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeActionMenu, {
@@ -238890,7 +239319,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
238890
239319
  canExtend: !archiveReadOnly,
238891
239320
  sourceKind: source?.kind,
238892
239321
  ...detailTopicPath === void 0 ? {} : { selfTopicPath: detailTopicPath },
238893
- ...detailTopicPresentation === void 0 ? {} : { selfTopicSource: detailTopicPresentation.topic },
239322
+ ...detailTopicPresentation !== void 0 ? { selfTopicSource: detailTopicPresentation.topic } : source?.kind === "topic" ? { selfTopicSource: source } : {},
238894
239323
  onOpenSelfTopic: (topic) => {
238895
239324
  setDrawer(void 0);
238896
239325
  activateSelfSource(topic);
@@ -247953,7 +248382,7 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
247953
248382
  font-weight: 500;
247954
248383
  }
247955
248384
 
247956
- .arkme-token-detail-toolbar select {
248385
+ .arkme-token-detail-toolbar select, .arkme-points-toolbar select {
247957
248386
  color: inherit;
247958
248387
  background: var(--dsw-alias-bg-layer-2, #f3f4f6);
247959
248388
  border: 1px solid var(--dsw-alias-border-l2, #e1e3e6);
@@ -247963,7 +248392,7 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
247963
248392
  padding: 5px 7px;
247964
248393
  }
247965
248394
 
247966
- .arkme-token-detail-toolbar select:focus-visible {
248395
+ .arkme-token-detail-toolbar select:focus-visible, .arkme-points-toolbar select:focus-visible {
247967
248396
  outline: 2px solid var(--dsw-alias-state-business-primary, #3964fe);
247968
248397
  outline-offset: 2px;
247969
248398
  }
@@ -248052,10 +248481,15 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
248052
248481
  display: block;
248053
248482
  }
248054
248483
 
248055
- .arkme-usage-balance-amount strong {
248056
- color: var(--dsw-alias-label-primary, #17191c);
248057
- font-size: 20px;
248058
- font-weight: 600;
248484
+ .arkme-usage-points-balance {
248485
+ flex-wrap: wrap;
248486
+ align-items: baseline;
248487
+ gap: 4px 12px;
248488
+ display: flex;
248489
+ }
248490
+
248491
+ .arkme-usage-points-sources {
248492
+ color: var(--dsw-alias-label-secondary, #68707c);
248059
248493
  }
248060
248494
 
248061
248495
  .arkme-usage-track {
@@ -248243,6 +248677,104 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
248243
248677
  height: 5px;
248244
248678
  margin-top: 9px;
248245
248679
  }
248680
+
248681
+ .arkme-usage-summary-row[data-usage-kind="ai-points"] {
248682
+ grid-template-columns: minmax(0, 1fr) auto;
248683
+ }
248684
+
248685
+ .arkme-account-usage .arkme-points-disclosure {
248686
+ align-items: center;
248687
+ gap: 6px;
248688
+ margin-top: 8px;
248689
+ display: flex;
248690
+ }
248691
+
248692
+ .arkme-usage-breakdown[data-usage-detail="points"] {
248693
+ margin-top: 8px;
248694
+ }
248695
+
248696
+ .arkme-points-toolbar {
248697
+ flex-wrap: wrap;
248698
+ justify-content: space-between;
248699
+ align-items: center;
248700
+ gap: 8px 12px;
248701
+ display: flex;
248702
+ }
248703
+
248704
+ .arkme-points-toolbar > span {
248705
+ color: var(--dsw-alias-label-secondary, #68707c);
248706
+ }
248707
+
248708
+ .arkme-usage-breakdown[data-usage-detail="points"] summary {
248709
+ cursor: pointer;
248710
+ overflow-wrap: anywhere;
248711
+ font-variant-numeric: tabular-nums;
248712
+ justify-content: space-between;
248713
+ align-items: center;
248714
+ gap: 12px;
248715
+ padding: 12px 0;
248716
+ list-style: none;
248717
+ display: flex;
248718
+ }
248719
+
248720
+ .arkme-usage-breakdown[data-usage-detail="points"] summary::-webkit-details-marker {
248721
+ display: none;
248722
+ }
248723
+
248724
+ .arkme-usage-breakdown[data-usage-detail="points"] summary > span:first-child {
248725
+ min-width: 0;
248726
+ }
248727
+
248728
+ .arkme-usage-breakdown[data-usage-detail="points"] summary strong {
248729
+ font-weight: 500;
248730
+ }
248731
+
248732
+ .arkme-usage-breakdown[data-usage-detail="points"] summary small {
248733
+ color: var(--dsw-alias-label-secondary, #68707c);
248734
+ margin-top: 4px;
248735
+ display: block;
248736
+ }
248737
+
248738
+ .arkme-points-record-amount {
248739
+ white-space: nowrap;
248740
+ flex: none;
248741
+ }
248742
+
248743
+ .arkme-points-chevron {
248744
+ color: var(--dsw-alias-label-secondary, #68707c);
248745
+ margin-left: 4px;
248746
+ display: inline-block;
248747
+ }
248748
+
248749
+ .arkme-usage-breakdown[data-usage-detail="points"] details[open] > summary .arkme-points-chevron {
248750
+ transform: rotate(90deg);
248751
+ }
248752
+
248753
+ .arkme-usage-breakdown[data-usage-detail="points"] details {
248754
+ border-bottom: 1px solid var(--dsw-alias-border-l2, #e1e3e6);
248755
+ }
248756
+
248757
+ .arkme-points-call {
248758
+ border-left: 2px solid var(--dsw-alias-border-l2, #e1e3e6);
248759
+ overflow-wrap: anywhere;
248760
+ margin-bottom: 12px;
248761
+ padding-left: 12px;
248762
+ }
248763
+
248764
+ .arkme-points-call small {
248765
+ color: var(--dsw-alias-label-secondary, #68707c);
248766
+ margin-top: 4px;
248767
+ display: block;
248768
+ }
248769
+
248770
+ .arkme-points-funding {
248771
+ color: var(--dsw-alias-label-secondary, #68707c);
248772
+ }
248773
+
248774
+ .arkme-usage-breakdown[data-usage-detail="points"] summary:focus-visible {
248775
+ outline: 2px solid var(--dsw-alias-state-business-primary, #3964fe);
248776
+ outline-offset: 2px;
248777
+ }
248246
248778
  \n.arkme-profile-edit-row {
248247
248779
  border: 0;
248248
248780
  border-bottom: 1px solid var(--dsw-alias-border-l1, #ececef);
@@ -249132,62 +249664,6 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
249132
249664
  ]
249133
249665
  });
249134
249666
  }
249135
- function HistoryMonth({ scope, month }) {
249136
- const [year, number] = month.split("-").map(Number);
249137
- const start = new Date(year, number - 1, 1).getTime(), end = new Date(year, number, 1).getTime();
249138
- const data = useReactionHistory(scope, Number.isFinite(start) ? start : void 0, Number.isFinite(end) ? end : void 0);
249139
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
249140
- data.busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
249141
- role: "status",
249142
- children: "加载中…"
249143
- }),
249144
- data.error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
249145
- role: "alert",
249146
- children: [
249147
- data.error,
249148
- " ",
249149
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
249150
- type: "button",
249151
- onClick: () => void data.load(),
249152
- children: "重试"
249153
- })
249154
- ]
249155
- }),
249156
- !data.busy && !data.error && !data.events.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "这个月没有表态记录" }),
249157
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: data.events.map((event, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
249158
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", { children: new Date(event.at).toLocaleString() }),
249159
- " · ",
249160
- event.added ? "表态" : "取消表态",
249161
- " ",
249162
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactionLabel, { label: event.label }),
249163
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [event.source, event.text ? " · " + event.text : ""] })
249164
- ] }, index)) }),
249165
- data.hasMore && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
249166
- type: "button",
249167
- disabled: data.busy,
249168
- onClick: () => void data.load(true),
249169
- children: "加载更多"
249170
- })
249171
- ] });
249172
- }
249173
- function ArkmeReactionHistoryRecords({ scope }) {
249174
- const now = /* @__PURE__ */ new Date();
249175
- const [month, setMonth] = (0, react$1.useState)(`${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`);
249176
- const [open, setOpen] = (0, react$1.useState)(false);
249177
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
249178
- className: "arkme-data-panel",
249179
- onToggle: (event) => setOpen(event.currentTarget.open),
249180
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "表态操作记录" }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: ["月份 ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
249181
- "aria-label": "表态记录月份",
249182
- type: "month",
249183
- value: month,
249184
- onChange: (event) => setMonth(event.target.value)
249185
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HistoryMonth, {
249186
- scope,
249187
- month
249188
- }, scope + month)] })]
249189
- });
249190
- }
249191
249667
  //#endregion
249192
249668
  //#region node_modules/@phosphor-icons/react/dist/defs/Copy.es.js
249193
249669
  const e$8 = /* @__PURE__ */ new Map([
@@ -251234,8 +251710,7 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
251234
251710
  children: [
251235
251711
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeAccountUsageDetails, {
251236
251712
  accountScope: scope,
251237
- onViewMembership: () => setMemberOpen(true),
251238
- onRefreshMembership: membership.refresh
251713
+ onViewMembership: () => setMemberOpen(true)
251239
251714
  }),
251240
251715
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251241
251716
  ref: membershipTrigger,
@@ -251366,194 +251841,190 @@ body[data-ds-dark-theme] .arkme-day-arrangement-status[data-arrangement-status="
251366
251841
  className: "arkme-data-settings",
251367
251842
  "data-arkme-settings-page": "data",
251368
251843
  "aria-label": tr$1("数据管理"),
251369
- children: [
251370
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [page !== "home" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251371
- type: "button",
251372
- className: "arkme-data-back",
251373
- disabled: recovering,
251374
- onClick: () => setPage("home"),
251375
- children: tr$1("‹ 数据管理")
251376
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: {
251377
- home: "数据管理",
251378
- archived: "已归档主题",
251379
- deleted: "最近删除",
251380
- import: "导入数据",
251381
- export: "导出数据"
251382
- }[page] })] }),
251383
- page === "home" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251384
- className: "arkme-data-hint",
251385
- children: tr$1("管理、迁入和保留属于你的记录。")
251386
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251387
- className: "arkme-data-entries",
251388
- children: [
251389
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251390
- type: "button",
251391
- onClick: () => setPage("archived"),
251392
- children: [
251393
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$15, {
251394
- size: 20,
251395
- "aria-hidden": true
251396
- }),
251397
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("已归档主题") }),
251398
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251399
- size: 15,
251400
- "aria-hidden": true
251401
- })
251402
- ]
251403
- }),
251404
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251405
- type: "button",
251406
- onClick: () => setPage("deleted"),
251407
- children: [
251408
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$9, {
251409
- size: 20,
251410
- "aria-hidden": true
251411
- }),
251412
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("最近删除") }),
251413
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251414
- size: 15,
251415
- "aria-hidden": true
251416
- })
251417
- ]
251418
- }),
251419
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251420
- type: "button",
251421
- onClick: () => setPage("import"),
251422
- children: [
251423
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n, {
251424
- size: 20,
251425
- "aria-hidden": true
251426
- }),
251427
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("导入数据") }),
251428
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251429
- size: 15,
251430
- "aria-hidden": true
251431
- })
251432
- ]
251433
- }),
251434
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251435
- type: "button",
251436
- onClick: () => setPage("export"),
251437
- children: [
251438
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(l$6, {
251439
- size: 20,
251440
- "aria-hidden": true
251441
- }),
251442
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("导出数据") }),
251443
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251444
- size: 15,
251445
- "aria-hidden": true
251446
- })
251447
- ]
251448
- })
251449
- ]
251450
- })] }) : page === "archived" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeArchiveManagementPanel, { close }) : page === "import" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251451
- className: "arkme-data-panel",
251452
- children: [
251453
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("在网页中导入") }),
251454
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("与 Flutter 桌面端使用同一个导入页面。请在网页中登录同一账号,再选择要导入的文件。") }),
251455
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
251456
- className: "arkme-data-primary",
251457
- href: "https://jiwo.cc/import",
251458
- target: "_blank",
251459
- rel: "noopener noreferrer",
251460
- children: tr$1("打开导入网页 ↗")
251461
- }),
251462
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("不会自动上传文件,也不会通过链接传递你的登录凭证。") })
251463
- ]
251464
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
251465
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251844
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [page !== "home" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251845
+ type: "button",
251846
+ className: "arkme-data-back",
251847
+ disabled: recovering,
251848
+ onClick: () => setPage("home"),
251849
+ children: tr$1("‹ 数据管理")
251850
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: {
251851
+ home: "数据管理",
251852
+ archived: "已归档主题",
251853
+ deleted: "最近删除",
251854
+ import: "导入数据",
251855
+ export: "导出数据"
251856
+ }[page] })] }), page === "home" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251857
+ className: "arkme-data-hint",
251858
+ children: tr$1("管理、迁入和保留属于你的记录。")
251859
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251860
+ className: "arkme-data-entries",
251861
+ children: [
251862
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251466
251863
  type: "button",
251467
- className: "arkme-settings-link",
251468
- disabled: loading || recovering,
251469
- onClick: () => setRevision((value) => value + 1),
251470
- children: loading ? tr$1("读取中…") : tr$1("刷新")
251864
+ onClick: () => setPage("archived"),
251865
+ children: [
251866
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$15, {
251867
+ size: 20,
251868
+ "aria-hidden": true
251869
+ }),
251870
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("已归档主题") }),
251871
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251872
+ size: 15,
251873
+ "aria-hidden": true
251874
+ })
251875
+ ]
251471
251876
  }),
251472
- error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251473
- role: "alert",
251474
- className: "arkme-data-error",
251475
- children: tr$1(error)
251877
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251878
+ type: "button",
251879
+ onClick: () => setPage("deleted"),
251880
+ children: [
251881
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$9, {
251882
+ size: 20,
251883
+ "aria-hidden": true
251884
+ }),
251885
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("最近删除") }),
251886
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251887
+ size: 15,
251888
+ "aria-hidden": true
251889
+ })
251890
+ ]
251476
251891
  }),
251477
- notice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251478
- role: "status",
251479
- children: notice
251892
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251893
+ type: "button",
251894
+ onClick: () => setPage("import"),
251895
+ children: [
251896
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(n, {
251897
+ size: 20,
251898
+ "aria-hidden": true
251899
+ }),
251900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("导入数据") }),
251901
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251902
+ size: 15,
251903
+ "aria-hidden": true
251904
+ })
251905
+ ]
251480
251906
  }),
251481
- page === "deleted" && deleted && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
251482
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
251483
- className: "arkme-data-hint",
251484
- children: [
251485
- deleted.items.length ? `本次显示 ${deleted.items.length} 条${deleted.mayHaveMore ? ",更多记录请在手机端查看" : ""}。` : deleted.unverifiedCount ? tr$1("部分记录状态无法确认,已隐藏,请刷新或在手机端查看。") : deleted.mayHaveMore ? tr$1("本次读取范围内暂无可恢复记录,更多记录请在手机端查看。") : tr$1("暂无最近删除的记录。"),
251486
- deleted.items.length > 0 && !!deleted.unverifiedCount && tr$1("部分记录状态无法确认,已隐藏,请刷新或在手机端查看。"),
251487
- tr$1("浏览不会自动清除数据。")
251488
- ]
251489
- }),
251490
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
251491
- className: "arkme-data-deleted-list",
251492
- children: deleted.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", { children: [item.title || item.text.slice(0, 80) || "无文字记录", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: new Date(item.sendAtMillis).toLocaleString(arkmeIntlLocale()) })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: item.text || "此记录无文字内容,附件请在恢复后查看。" })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251493
- type: "button",
251494
- disabled: recovering || item.version <= 0,
251495
- onClick: () => {
251496
- setConfirm(item);
251497
- setError("");
251498
- },
251499
- children: tr$1("恢复")
251500
- })] }, item.recordUid))
251501
- }),
251502
- confirm && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251503
- className: "arkme-data-panel",
251504
- role: "group",
251505
- "aria-label": tr$1("确认恢复记录"),
251506
- children: [
251507
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
251508
- tr$1("恢复“"),
251509
- confirm.title || confirm.text.slice(0, 40) || "无文字记录",
251510
- "”?"
251511
- ] }),
251512
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251513
- type: "button",
251514
- disabled: recovering,
251515
- onClick: () => {
251516
- recover();
251517
- },
251518
- children: recovering ? "正在恢复…" : "确认恢复"
251519
- }),
251520
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251521
- type: "button",
251522
- disabled: recovering,
251523
- onClick: () => setConfirm(void 0),
251524
- children: tr$1("取消")
251525
- })
251526
- ]
251527
- })
251528
- ] }),
251529
- page === "export" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251907
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
251908
+ type: "button",
251909
+ onClick: () => setPage("export"),
251910
+ children: [
251911
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(l$6, {
251912
+ size: 20,
251913
+ "aria-hidden": true
251914
+ }),
251915
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr$1("导出数据") }),
251916
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
251917
+ size: 15,
251918
+ "aria-hidden": true
251919
+ })
251920
+ ]
251921
+ })
251922
+ ]
251923
+ })] }) : page === "archived" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeArchiveManagementPanel, { close }) : page === "import" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251924
+ className: "arkme-data-panel",
251925
+ children: [
251926
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("在网页中导入") }),
251927
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("与 Flutter 桌面端使用同一个导入页面。请在网页中登录同一账号,再选择要导入的文件。") }),
251928
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
251929
+ className: "arkme-data-primary",
251930
+ href: "https://jiwo.cc/import",
251931
+ target: "_blank",
251932
+ rel: "noopener noreferrer",
251933
+ children: tr$1("打开导入网页 ↗")
251934
+ }),
251935
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("不会自动上传文件,也不会通过链接传递你的登录凭证。") })
251936
+ ]
251937
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
251938
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251939
+ type: "button",
251940
+ className: "arkme-settings-link",
251941
+ disabled: loading || recovering,
251942
+ onClick: () => setRevision((value) => value + 1),
251943
+ children: loading ? tr$1("读取中…") : tr$1("刷新")
251944
+ }),
251945
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251946
+ role: "alert",
251947
+ className: "arkme-data-error",
251948
+ children: tr$1(error)
251949
+ }),
251950
+ notice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
251951
+ role: "status",
251952
+ children: notice
251953
+ }),
251954
+ page === "deleted" && deleted && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
251955
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
251956
+ className: "arkme-data-hint",
251957
+ children: [
251958
+ deleted.items.length ? `本次显示 ${deleted.items.length} 条${deleted.mayHaveMore ? ",更多记录请在手机端查看" : ""}。` : deleted.unverifiedCount ? tr$1("部分记录状态无法确认,已隐藏,请刷新或在手机端查看。") : deleted.mayHaveMore ? tr$1("本次读取范围内暂无可恢复记录,更多记录请在手机端查看。") : tr$1("暂无最近删除的记录。"),
251959
+ deleted.items.length > 0 && !!deleted.unverifiedCount && tr$1("部分记录状态无法确认,已隐藏,请刷新或在手机端查看。"),
251960
+ tr$1("浏览不会自动清除数据。")
251961
+ ]
251962
+ }),
251963
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
251964
+ className: "arkme-data-deleted-list",
251965
+ children: deleted.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", { children: [item.title || item.text.slice(0, 80) || "无文字记录", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: new Date(item.sendAtMillis).toLocaleString(arkmeIntlLocale()) })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: item.text || "此记录无文字内容,附件请在恢复后查看。" })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251966
+ type: "button",
251967
+ disabled: recovering || item.version <= 0,
251968
+ onClick: () => {
251969
+ setConfirm(item);
251970
+ setError("");
251971
+ },
251972
+ children: tr$1("恢复")
251973
+ })] }, item.recordUid))
251974
+ }),
251975
+ confirm && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251530
251976
  className: "arkme-data-panel",
251977
+ role: "group",
251978
+ "aria-label": tr$1("确认恢复记录"),
251531
251979
  children: [
251532
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("完整备份") }),
251533
- preflight && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
251534
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
251535
- preflight.recordCount,
251536
- " ",
251537
- tr$1("条快记 ·"),
251538
- " ",
251539
- preflight.voiceCount,
251540
- " ",
251541
- tr$1("个语音 ·"),
251542
- " ",
251543
- preflight.imageCount,
251544
- " ",
251545
- tr$1("张图片")
251546
- ] }),
251547
- (preflight.message || !preflight.canExport) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: preflight.message || "当前暂不满足导出条件,请在手机端查看。" }),
251548
- preflight.latestAtMillis > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [tr$1("最近导出:"), new Date(preflight.latestAtMillis).toLocaleString(arkmeIntlLocale())] })
251980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
251981
+ tr$1("恢复“"),
251982
+ confirm.title || confirm.text.slice(0, 40) || "无文字记录",
251983
+ "”?"
251549
251984
  ] }),
251550
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("当前插件尚未接入完整文件打包下载。请先在即我手机端或 Flutter 桌面端的「数据管理 → 导出」完成备份。") }),
251551
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("这里只查询导出条件,不会创建导出任务或消耗导出次数。") })
251985
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251986
+ type: "button",
251987
+ disabled: recovering,
251988
+ onClick: () => {
251989
+ recover();
251990
+ },
251991
+ children: recovering ? "正在恢复…" : "确认恢复"
251992
+ }),
251993
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
251994
+ type: "button",
251995
+ disabled: recovering,
251996
+ onClick: () => setConfirm(void 0),
251997
+ children: tr$1("取消")
251998
+ })
251552
251999
  ]
251553
252000
  })
251554
252001
  ] }),
251555
- page === "home" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeReactionHistoryRecords, { scope })
251556
- ]
252002
+ page === "export" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
252003
+ className: "arkme-data-panel",
252004
+ children: [
252005
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: tr$1("完整备份") }),
252006
+ preflight && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
252007
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
252008
+ preflight.recordCount,
252009
+ " ",
252010
+ tr$1("条快记 ·"),
252011
+ " ",
252012
+ preflight.voiceCount,
252013
+ " ",
252014
+ tr$1("个语音 ·"),
252015
+ " ",
252016
+ preflight.imageCount,
252017
+ " ",
252018
+ tr$1("张图片")
252019
+ ] }),
252020
+ (preflight.message || !preflight.canExport) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: preflight.message || "当前暂不满足导出条件,请在手机端查看。" }),
252021
+ preflight.latestAtMillis > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [tr$1("最近导出:"), new Date(preflight.latestAtMillis).toLocaleString(arkmeIntlLocale())] })
252022
+ ] }),
252023
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr$1("当前插件尚未接入完整文件打包下载。请先在即我手机端或 Flutter 桌面端的「数据管理 → 导出」完成备份。") }),
252024
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: tr$1("这里只查询导出条件,不会创建导出任务或消耗导出次数。") })
252025
+ ]
252026
+ })
252027
+ ] })]
251557
252028
  });
251558
252029
  }
251559
252030
  //#endregion