@senguoyun/dsh-arkme 0.1.83 → 0.1.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/recognized-speaker-directory-backend-handoff-2026-09-28.md +157 -0
- package/docs/recognized-speaker-entry-and-visits.md +47 -0
- package/docs/recognized-speaker-presence-delivery.md +51 -0
- package/docs/recognized-speaker-sorting.md +30 -0
- package/lib/client.js +1194 -253
- package/lib/client.js.map +1 -1
- package/lib/harness-model-client.js +51 -7
- package/lib/harness-native-selection-client.js +35 -0
- package/lib/harness-sidebar-client.js +20 -0
- package/lib/index.js +154 -77
- package/lib/persistent-extension.js +1 -1
- package/lib/{persistent-runtime-B6vPAaiG.js → persistent-runtime-CuKplHIv.js} +101 -262
- package/lib/sdk.js +20 -0
- package/lib/types/arkme-service.d.ts +1 -1
- package/lib/types/arkme-service.d.ts.map +1 -1
- package/lib/types/client/ArkmeAccountUsage.d.ts.map +1 -1
- package/lib/types/client/ArkmeModelPricing.d.ts +9 -0
- package/lib/types/client/ArkmeModelPricing.d.ts.map +1 -0
- package/lib/types/client/ArkmeModelSelect.d.ts.map +1 -1
- package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
- package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts +6 -2
- package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts.map +1 -1
- package/lib/types/client/ArkmeRecordingSurface.d.ts.map +1 -1
- package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
- package/lib/types/client/ArkoModelMenu.d.ts.map +1 -1
- package/lib/types/client/locales/en.d.ts.map +1 -1
- package/lib/types/client/reaction-preview-store.d.ts +1 -0
- package/lib/types/client/reaction-preview-store.d.ts.map +1 -1
- package/lib/types/client/recognized-speaker-directory.d.ts +36 -0
- package/lib/types/client/recognized-speaker-directory.d.ts.map +1 -0
- package/lib/types/client/recognized-speaker-order.d.ts +28 -0
- package/lib/types/client/recognized-speaker-order.d.ts.map +1 -0
- package/lib/types/client/recognized-speaker-tracker.d.ts +33 -0
- package/lib/types/client/recognized-speaker-tracker.d.ts.map +1 -0
- package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts +12 -0
- package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts.map +1 -0
- package/lib/types/client/recordings/SpeakerSelfGuide.d.ts +8 -0
- package/lib/types/client/recordings/SpeakerSelfGuide.d.ts.map +1 -0
- package/lib/types/client/recordings/recording-speaker-options-store.d.ts.map +1 -1
- package/lib/types/sdk/index.d.ts +10 -0
- package/lib/types/sdk/index.d.ts.map +1 -1
- package/lib/types/services/chat-service.d.ts.map +1 -1
- package/lib/types/services/recording-service.d.ts +2 -5
- package/lib/types/services/recording-service.d.ts.map +1 -1
- package/lib/types/services/unmarked-speaker-service.d.ts.map +1 -1
- package/lib/types/tools/business/recordings/index.d.ts +1 -1
- package/lib/types/tools/business/recordings/index.d.ts.map +1 -1
- package/lib/types/tools/business/recordings/speaker-presence.d.ts +2 -0
- package/lib/types/tools/business/recordings/speaker-presence.d.ts.map +1 -0
- package/lib/types/tools/ports/recordings.d.ts +4 -0
- package/lib/types/tools/ports/recordings.d.ts.map +1 -1
- package/lib/types/types.d.ts +18 -7
- package/lib/types/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/lib/types/recording-speaker-presence.d.ts +0 -28
- package/lib/types/recording-speaker-presence.d.ts.map +0 -1
package/lib/client.js
CHANGED
|
@@ -249,6 +249,26 @@ window.__ModuleLoader__.load({
|
|
|
249
249
|
this.route = route;
|
|
250
250
|
this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
251
251
|
}
|
|
252
|
+
/** Account-scoped marked speaker candidates; refs can be used only with this provider/account. */
|
|
253
|
+
async recordingSpeakerCandidates(signal) {
|
|
254
|
+
await this.requireSpeakerPresence(signal);
|
|
255
|
+
return await this.call("recordings.speaker.options", {}, signal);
|
|
256
|
+
}
|
|
257
|
+
async recordingSpeakerPresence(signal) {
|
|
258
|
+
await this.requireSpeakerPresence(signal);
|
|
259
|
+
return await this.call("recordings.speaker.presence", {}, signal);
|
|
260
|
+
}
|
|
261
|
+
async recordingSpeakerMembers(speakerRef, options = {}) {
|
|
262
|
+
if (speakerRef.trim() === "") throw new TypeError("speakerRef is required");
|
|
263
|
+
await this.requireSpeakerPresence(options.signal);
|
|
264
|
+
return await this.call("recordings.speaker.members", {
|
|
265
|
+
speakerRef,
|
|
266
|
+
...options.expectedVersion === void 0 ? {} : { expectedVersion: options.expectedVersion }
|
|
267
|
+
}, options.signal);
|
|
268
|
+
}
|
|
269
|
+
async requireSpeakerPresence(signal) {
|
|
270
|
+
if ((await this.capabilities(signal)).features.speakerPresence !== true) throw new Error("当前 Provider 不支持全历史说话人统计");
|
|
271
|
+
}
|
|
252
272
|
async capabilities(signal) {
|
|
253
273
|
const capabilities = await this.call("provider.capabilities", void 0, signal);
|
|
254
274
|
if (capabilities.contractVersion !== 1) throw new Error(`Unsupported Arkme provider contract version ${String(capabilities.contractVersion)}`);
|
|
@@ -33147,6 +33167,12 @@ window.__ModuleLoader__.load({
|
|
|
33147
33167
|
/** Application copy only. User-authored text is never looked up in this table. */
|
|
33148
33168
|
const arkmeEnglish = Object.fromEntries(`
|
|
33149
33169
|
个人世界|Personal world
|
|
33170
|
+
说话人排序|Sort speakers
|
|
33171
|
+
经常出现|Most frequent
|
|
33172
|
+
最近出现|Most recent
|
|
33173
|
+
正在补齐说话人列表,排序仍在更新…|Loading the remaining speakers. Order is still updating…
|
|
33174
|
+
列表尚未完整,当前仅对已加载的说话人排序和搜索。|The list is incomplete. Sorting and search cover loaded speakers only.
|
|
33175
|
+
显示更多说话人|Show more speakers
|
|
33150
33176
|
语音通话邀请|Voice call invitation
|
|
33151
33177
|
视频通话邀请|Video call invitation
|
|
33152
33178
|
公开快记|Public note
|
|
@@ -33726,6 +33752,7 @@ AI智能体|AI agent
|
|
|
33726
33752
|
群聊名称|Group name
|
|
33727
33753
|
最新|Latest
|
|
33728
33754
|
部分历史附件暂不可用|Some earlier attachments are unavailable
|
|
33755
|
+
附件暂不可用|Attachment unavailable
|
|
33729
33756
|
正在加载编辑记录…|Loading edit history…
|
|
33730
33757
|
暂无编辑记录|No edit history
|
|
33731
33758
|
重新加载历史附件|Reload earlier attachments
|
|
@@ -34769,6 +34796,14 @@ Bot 已移出群聊|Bot removed from the group
|
|
|
34769
34796
|
{v0}人|{v0} people
|
|
34770
34797
|
正在读取群 Bot…|Loading group Bots…
|
|
34771
34798
|
Bot 列表加载失败,点击重试|Could not load Bots. Click to retry
|
|
34799
|
+
新识别 {v0} 个|{v0} newly identified
|
|
34800
|
+
识别我的声音|Identify my voice
|
|
34801
|
+
你的声纹正在处理中|Your voiceprint is being processed
|
|
34802
|
+
已录入声纹,暂未在录音中匹配到你|Voiceprint enrolled. No match found in your recordings yet.
|
|
34803
|
+
还没有标记你的声音|Your voice has not been labeled yet
|
|
34804
|
+
打开你的录音,点击说话人名称并选择自己;请先试听确认。|Open your recording, listen to confirm, then click the speaker name and select yourself.
|
|
34805
|
+
从录音中标记我|Label myself in a recording
|
|
34806
|
+
管理声纹|Manage voiceprint
|
|
34772
34807
|
`.trim().split("\n").map((line) => {
|
|
34773
34808
|
const index = line.indexOf("|");
|
|
34774
34809
|
return [line.slice(0, index), line.slice(index + 1)];
|
|
@@ -47700,7 +47735,7 @@ function(test) {
|
|
|
47700
47735
|
* Test type.
|
|
47701
47736
|
*/
|
|
47702
47737
|
/** @type {Readonly<ActionTuple>} */
|
|
47703
|
-
const empty$
|
|
47738
|
+
const empty$5 = [];
|
|
47704
47739
|
/**
|
|
47705
47740
|
* Visit nodes, with ancestral information.
|
|
47706
47741
|
*
|
|
@@ -47772,7 +47807,7 @@ function(test) {
|
|
|
47772
47807
|
return visit;
|
|
47773
47808
|
function visit() {
|
|
47774
47809
|
/** @type {Readonly<ActionTuple>} */
|
|
47775
|
-
let result = empty$
|
|
47810
|
+
let result = empty$5;
|
|
47776
47811
|
/** @type {Readonly<ActionTuple>} */
|
|
47777
47812
|
let subresult;
|
|
47778
47813
|
/** @type {number} */
|
|
@@ -47811,7 +47846,7 @@ function(test) {
|
|
|
47811
47846
|
function toResult(value) {
|
|
47812
47847
|
if (Array.isArray(value)) return value;
|
|
47813
47848
|
if (typeof value === "number") return [true, value];
|
|
47814
|
-
return value === null || value === void 0 ? empty$
|
|
47849
|
+
return value === null || value === void 0 ? empty$5 : [value];
|
|
47815
47850
|
}
|
|
47816
47851
|
//#endregion
|
|
47817
47852
|
//#region node_modules/mdast-util-find-and-replace/lib/index.js
|
|
@@ -55726,9 +55761,12 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
55726
55761
|
}
|
|
55727
55762
|
this.inactive.delete(target.id);
|
|
55728
55763
|
this.knownTargets.set(target.id, target);
|
|
55729
|
-
|
|
55764
|
+
if (existing) {
|
|
55765
|
+
existing.target = target;
|
|
55766
|
+
existing.count++;
|
|
55767
|
+
} else this.targets.set(target.id, {
|
|
55730
55768
|
target,
|
|
55731
|
-
count:
|
|
55769
|
+
count: 1
|
|
55732
55770
|
});
|
|
55733
55771
|
if (this.refreshing) this.refreshAgain = true;
|
|
55734
55772
|
this.schedule(40);
|
|
@@ -55740,18 +55778,23 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
55740
55778
|
else {
|
|
55741
55779
|
this.targets.delete(target.id);
|
|
55742
55780
|
this.failures.delete(target.id);
|
|
55743
|
-
|
|
55744
|
-
else this.knownTargets.delete(target.id);
|
|
55745
|
-
while (this.inactive.size > 400) {
|
|
55746
|
-
const oldest = this.inactive.values().next().value;
|
|
55747
|
-
this.inactive.delete(oldest);
|
|
55748
|
-
this.states.delete(oldest);
|
|
55749
|
-
this.knownTargets.delete(oldest);
|
|
55750
|
-
}
|
|
55781
|
+
this.retainInactive(target.id);
|
|
55751
55782
|
}
|
|
55752
55783
|
if (!this.targets.size) this.stop();
|
|
55753
55784
|
};
|
|
55754
55785
|
}
|
|
55786
|
+
retainInactive(id) {
|
|
55787
|
+
if (this.targets.has(id)) return;
|
|
55788
|
+
if (this.states.has(id) || this.failures.has(id)) this.inactive.add(id);
|
|
55789
|
+
else this.knownTargets.delete(id);
|
|
55790
|
+
while (this.inactive.size > 400) {
|
|
55791
|
+
const oldest = this.inactive.values().next().value;
|
|
55792
|
+
this.inactive.delete(oldest);
|
|
55793
|
+
this.states.delete(oldest);
|
|
55794
|
+
this.knownTargets.delete(oldest);
|
|
55795
|
+
this.failures.delete(oldest);
|
|
55796
|
+
}
|
|
55797
|
+
}
|
|
55755
55798
|
async prepare(scope, targets, signal, force = false) {
|
|
55756
55799
|
if (scope !== this.scope || signal.aborted) return;
|
|
55757
55800
|
const missing = targets.filter((target) => force || !this.states.has(target.id)).slice(0, 200);
|
|
@@ -55907,7 +55950,19 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
55907
55950
|
if (recovered.outcome === "revision_conflict") throw new Error("上次表态已在其他设备更新,请重新选择");
|
|
55908
55951
|
await this.refresh();
|
|
55909
55952
|
}
|
|
55910
|
-
if (!this.states.has(target.id))
|
|
55953
|
+
if (!this.states.has(target.id)) {
|
|
55954
|
+
const page = await this.transport({
|
|
55955
|
+
action: "query",
|
|
55956
|
+
accountKey: scope,
|
|
55957
|
+
targets: [target]
|
|
55958
|
+
}, signal);
|
|
55959
|
+
if (signal.aborted) return false;
|
|
55960
|
+
const loaded = page.items.find((item) => item.target_id === target.id);
|
|
55961
|
+
if (!loaded) throw new Error("消息已不可访问");
|
|
55962
|
+
const previous = this.states.get(target.id);
|
|
55963
|
+
if (!previous || previous.mine.revision <= loaded.mine.revision) this.states.set(target.id, loaded);
|
|
55964
|
+
this.knownTargets.set(target.id, target);
|
|
55965
|
+
}
|
|
55911
55966
|
const state = this.states.get(target.id);
|
|
55912
55967
|
if (signal.aborted || !state) throw new Error("请先成功加载消息表态");
|
|
55913
55968
|
const selected = state.mine.selections.find((item) => expressionIdentity(item.expression) === expressionIdentity(chosen));
|
|
@@ -55940,6 +55995,7 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
55940
55995
|
return false;
|
|
55941
55996
|
} finally {
|
|
55942
55997
|
if (!signal.aborted) {
|
|
55998
|
+
this.retainInactive(target.id);
|
|
55943
55999
|
this.writing = false;
|
|
55944
56000
|
this.publish();
|
|
55945
56001
|
}
|
|
@@ -56813,6 +56869,474 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
56813
56869
|
}
|
|
56814
56870
|
};
|
|
56815
56871
|
//#endregion
|
|
56872
|
+
//#region src/client/recognized-speaker-tracker.ts
|
|
56873
|
+
const empty$4 = { checkedAt: 0 };
|
|
56874
|
+
const storageKey$4 = (account) => `dsh-arkme:speaker-visits:v1:${account}`;
|
|
56875
|
+
const storage$1 = () => {
|
|
56876
|
+
try {
|
|
56877
|
+
return window.localStorage;
|
|
56878
|
+
} catch {
|
|
56879
|
+
return;
|
|
56880
|
+
}
|
|
56881
|
+
};
|
|
56882
|
+
function markedSpeakerKeys(options) {
|
|
56883
|
+
return [...new Set(options.filter((option) => option.kind === "speaker").map((option) => `m:${option.personKey || option.optionKey}`))];
|
|
56884
|
+
}
|
|
56885
|
+
/** Only complete identity snapshots can establish a baseline or produce a precise delta.
|
|
56886
|
+
* A removed identity may be a merge/recluster; without lineage we suppress ambiguous
|
|
56887
|
+
* additions for that transition rather than presenting a false "new person".
|
|
56888
|
+
*/
|
|
56889
|
+
var RecognizedSpeakerTracker = class {
|
|
56890
|
+
getStorage;
|
|
56891
|
+
records = /* @__PURE__ */ new Map();
|
|
56892
|
+
snapshots = /* @__PURE__ */ new Map();
|
|
56893
|
+
listeners = /* @__PURE__ */ new Set();
|
|
56894
|
+
constructor(getStorage = storage$1) {
|
|
56895
|
+
this.getStorage = getStorage;
|
|
56896
|
+
}
|
|
56897
|
+
subscribe = (listener) => {
|
|
56898
|
+
this.listeners.add(listener);
|
|
56899
|
+
return () => {
|
|
56900
|
+
this.listeners.delete(listener);
|
|
56901
|
+
};
|
|
56902
|
+
};
|
|
56903
|
+
get = (account) => account === void 0 ? empty$4 : this.snapshots.get(account) ?? empty$4;
|
|
56904
|
+
emit(account, snapshot) {
|
|
56905
|
+
this.snapshots.set(account, snapshot);
|
|
56906
|
+
for (const listener of this.listeners) listener();
|
|
56907
|
+
}
|
|
56908
|
+
read(account) {
|
|
56909
|
+
if (this.records.has(account)) return this.records.get(account);
|
|
56910
|
+
try {
|
|
56911
|
+
const value = JSON.parse(this.getStorage()?.getItem(storageKey$4(account)) ?? "null");
|
|
56912
|
+
if (value !== null && [
|
|
56913
|
+
"known",
|
|
56914
|
+
"current",
|
|
56915
|
+
"pending"
|
|
56916
|
+
].every((key) => {
|
|
56917
|
+
const list = value[key];
|
|
56918
|
+
return Array.isArray(list) && list.length <= 2e4 && list.every((item) => typeof item === "string" && item.length <= 256);
|
|
56919
|
+
})) {
|
|
56920
|
+
this.records.set(account, value);
|
|
56921
|
+
return value;
|
|
56922
|
+
}
|
|
56923
|
+
} catch {}
|
|
56924
|
+
}
|
|
56925
|
+
save(account, value) {
|
|
56926
|
+
this.records.set(account, value);
|
|
56927
|
+
try {
|
|
56928
|
+
this.getStorage()?.setItem(storageKey$4(account), JSON.stringify(value));
|
|
56929
|
+
} catch {}
|
|
56930
|
+
}
|
|
56931
|
+
setTotal(account, total) {
|
|
56932
|
+
if (!Number.isSafeInteger(total) || total < 0) return;
|
|
56933
|
+
const previous = this.get(account);
|
|
56934
|
+
this.emit(account, previous.total === total ? {
|
|
56935
|
+
...previous,
|
|
56936
|
+
total
|
|
56937
|
+
} : {
|
|
56938
|
+
total,
|
|
56939
|
+
checkedAt: 0
|
|
56940
|
+
});
|
|
56941
|
+
}
|
|
56942
|
+
uncertain(account) {
|
|
56943
|
+
const previous = this.get(account);
|
|
56944
|
+
this.emit(account, {
|
|
56945
|
+
...previous.total === void 0 ? {} : { total: previous.total },
|
|
56946
|
+
checkedAt: 0
|
|
56947
|
+
});
|
|
56948
|
+
}
|
|
56949
|
+
acknowledge(account) {
|
|
56950
|
+
const previous = this.read(account);
|
|
56951
|
+
if (previous === void 0) return;
|
|
56952
|
+
this.save(account, {
|
|
56953
|
+
...previous,
|
|
56954
|
+
pending: []
|
|
56955
|
+
});
|
|
56956
|
+
this.emit(account, {
|
|
56957
|
+
...this.get(account),
|
|
56958
|
+
newCount: 0
|
|
56959
|
+
});
|
|
56960
|
+
}
|
|
56961
|
+
observe(account, options, candidates, viewed = false) {
|
|
56962
|
+
const marked = markedSpeakerKeys(options);
|
|
56963
|
+
if (candidates.some((candidate) => !candidate.identityKey)) {
|
|
56964
|
+
this.uncertain(account);
|
|
56965
|
+
return;
|
|
56966
|
+
}
|
|
56967
|
+
const current = [.../* @__PURE__ */ new Set([...marked, ...candidates.map((candidate) => `u:${candidate.identityKey}`)])];
|
|
56968
|
+
const previous = this.read(account);
|
|
56969
|
+
const known = new Set(previous?.known ?? []);
|
|
56970
|
+
const currentSet = new Set(current);
|
|
56971
|
+
const removed = previous?.current.some((key) => !currentSet.has(key)) ?? false;
|
|
56972
|
+
const additions = previous === void 0 || removed ? [] : current.filter((key) => !known.has(key));
|
|
56973
|
+
const pending = viewed ? [] : [.../* @__PURE__ */ new Set([...(previous?.pending ?? []).filter((key) => currentSet.has(key)), ...additions])];
|
|
56974
|
+
current.forEach((key) => known.add(key));
|
|
56975
|
+
const record = known.size > 2e4 ? {
|
|
56976
|
+
known: current,
|
|
56977
|
+
current,
|
|
56978
|
+
pending: []
|
|
56979
|
+
} : {
|
|
56980
|
+
known: [...known],
|
|
56981
|
+
current,
|
|
56982
|
+
pending
|
|
56983
|
+
};
|
|
56984
|
+
this.save(account, record);
|
|
56985
|
+
this.emit(account, {
|
|
56986
|
+
total: current.length,
|
|
56987
|
+
newCount: record.pending.length,
|
|
56988
|
+
checkedAt: Date.now()
|
|
56989
|
+
});
|
|
56990
|
+
}
|
|
56991
|
+
clearSession() {
|
|
56992
|
+
this.snapshots.clear();
|
|
56993
|
+
this.records.clear();
|
|
56994
|
+
for (const listener of this.listeners) listener();
|
|
56995
|
+
}
|
|
56996
|
+
};
|
|
56997
|
+
const recognizedSpeakerTracker = new RecognizedSpeakerTracker();
|
|
56998
|
+
let activeAccount$1 = "";
|
|
56999
|
+
arkmeAuthStore.subscribe(() => {
|
|
57000
|
+
const auth = arkmeAuthStore.getSnapshot().auth;
|
|
57001
|
+
const next = auth?.status === "authenticated" ? `${auth.environment}:${auth.userId}` : "";
|
|
57002
|
+
if (next !== activeAccount$1) {
|
|
57003
|
+
activeAccount$1 = next;
|
|
57004
|
+
recognizedSpeakerTracker.clearSession();
|
|
57005
|
+
}
|
|
57006
|
+
});
|
|
57007
|
+
//#endregion
|
|
57008
|
+
//#region src/client/recognized-speaker-order.ts
|
|
57009
|
+
const preferenceKey$3 = (accountKey) => `dsh-arkme:recognized-speaker-order:v1:${accountKey}`;
|
|
57010
|
+
function browserStorage$1() {
|
|
57011
|
+
try {
|
|
57012
|
+
return typeof window === "undefined" ? void 0 : window.localStorage;
|
|
57013
|
+
} catch {
|
|
57014
|
+
return;
|
|
57015
|
+
}
|
|
57016
|
+
}
|
|
57017
|
+
function readRecognizedSpeakerOrder(accountKey, storage = browserStorage$1()) {
|
|
57018
|
+
try {
|
|
57019
|
+
return storage?.getItem(preferenceKey$3(accountKey)) === "recent" ? "recent" : "frequent";
|
|
57020
|
+
} catch {
|
|
57021
|
+
return "frequent";
|
|
57022
|
+
}
|
|
57023
|
+
}
|
|
57024
|
+
function writeRecognizedSpeakerOrder(accountKey, order, storage = browserStorage$1()) {
|
|
57025
|
+
try {
|
|
57026
|
+
storage?.setItem(preferenceKey$3(accountKey), order);
|
|
57027
|
+
} catch {}
|
|
57028
|
+
}
|
|
57029
|
+
function positiveNumber(value) {
|
|
57030
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? value : 0;
|
|
57031
|
+
}
|
|
57032
|
+
/** Missing statistics sort last. Ties remain stable across refreshes and filters. */
|
|
57033
|
+
function compareRecognizedSpeakers(left, right, order) {
|
|
57034
|
+
const leftDays = positiveNumber(left.dayCount), rightDays = positiveNumber(right.dayCount);
|
|
57035
|
+
const leftTime = positiveNumber(left.lastSeenAt), rightTime = positiveNumber(right.lastSeenAt);
|
|
57036
|
+
return (order === "frequent" ? rightDays - leftDays || rightTime - leftTime : rightTime - leftTime || rightDays - leftDays) || left.name.localeCompare(right.name, void 0, { numeric: true }) || left.key.localeCompare(right.key);
|
|
57037
|
+
}
|
|
57038
|
+
/** The upstream cursor has a fixed order. Read metadata pages before claiming global order.
|
|
57039
|
+
* Bound reads to the host's 2,000-candidate reference budget; never silently call a partial
|
|
57040
|
+
* traversal complete. No audio or per-speaker detail is loaded here.
|
|
57041
|
+
*/
|
|
57042
|
+
async function loadSpeakerCandidateSnapshot(loadPage, signal, onProgress) {
|
|
57043
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
57044
|
+
const rows = /* @__PURE__ */ new Map();
|
|
57045
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
57046
|
+
let cursor = "";
|
|
57047
|
+
let snapshot = {
|
|
57048
|
+
items: [],
|
|
57049
|
+
complete: false,
|
|
57050
|
+
projectionState: void 0
|
|
57051
|
+
};
|
|
57052
|
+
for (let pageIndex = 0; pageIndex < 40; pageIndex += 1) {
|
|
57053
|
+
signal.throwIfAborted();
|
|
57054
|
+
const page = await loadPage(cursor, signal);
|
|
57055
|
+
signal.throwIfAborted();
|
|
57056
|
+
if (page.section !== "unmarked-speakers") throw new Error("未标记说话人列表响应无效");
|
|
57057
|
+
if (page.cursorStale) {
|
|
57058
|
+
snapshot = {
|
|
57059
|
+
items: [],
|
|
57060
|
+
complete: false,
|
|
57061
|
+
projectionState: "stale"
|
|
57062
|
+
};
|
|
57063
|
+
onProgress(snapshot);
|
|
57064
|
+
if (attempt === 0) break;
|
|
57065
|
+
return snapshot;
|
|
57066
|
+
}
|
|
57067
|
+
for (const item of page.items) if (item.kind === "unmarked-speaker" && rows.size < 2e3) rows.set(item.candidateRef, item);
|
|
57068
|
+
snapshot = {
|
|
57069
|
+
items: [...rows.values()],
|
|
57070
|
+
complete: !page.hasMore && page.coverage !== "partial" && (page.projectionState === void 0 || page.projectionState === "fresh"),
|
|
57071
|
+
projectionState: page.projectionState
|
|
57072
|
+
};
|
|
57073
|
+
onProgress(snapshot);
|
|
57074
|
+
if (!page.hasMore || rows.size >= 2e3 || page.projectionState !== void 0 && page.projectionState !== "fresh") return snapshot;
|
|
57075
|
+
const next = page.nextCursor ?? "";
|
|
57076
|
+
if (next === "" || cursors.has(next)) return snapshot;
|
|
57077
|
+
cursors.add(next);
|
|
57078
|
+
cursor = next;
|
|
57079
|
+
if (pageIndex === 39) return snapshot;
|
|
57080
|
+
}
|
|
57081
|
+
}
|
|
57082
|
+
return {
|
|
57083
|
+
items: [],
|
|
57084
|
+
complete: false,
|
|
57085
|
+
projectionState: "stale"
|
|
57086
|
+
};
|
|
57087
|
+
}
|
|
57088
|
+
//#endregion
|
|
57089
|
+
//#region src/client/recognized-speaker-directory.ts
|
|
57090
|
+
const readSpeakerOptions = (signal) => callArkme("recordings.speaker.options", {}, signal);
|
|
57091
|
+
const readSpeakerPresence = (signal) => callArkme("recordings.speaker.presence", {}, signal);
|
|
57092
|
+
const readSpeakerPage = (cursor, signal) => callArkme("directory.list", {
|
|
57093
|
+
section: "unmarked-speakers",
|
|
57094
|
+
limit: 50,
|
|
57095
|
+
...cursor === "" ? {} : { cursor }
|
|
57096
|
+
}, signal);
|
|
57097
|
+
var SpeakerReadDeferred = class extends Error {
|
|
57098
|
+
retryAt;
|
|
57099
|
+
constructor(retryAt, cause) {
|
|
57100
|
+
super(cause instanceof Error ? cause.message : "说话人列表暂时无法加载", { cause });
|
|
57101
|
+
this.retryAt = retryAt;
|
|
57102
|
+
}
|
|
57103
|
+
};
|
|
57104
|
+
function speakerRetryDelay(error) {
|
|
57105
|
+
return error instanceof SpeakerReadDeferred ? Math.max(1e3, error.retryAt - Date.now()) : void 0;
|
|
57106
|
+
}
|
|
57107
|
+
/** Per-account shared read. A short release grace lets entry -> list hand off the same
|
|
57108
|
+
* request; leaving both cancels it. A late/aborted response can never update the cache.
|
|
57109
|
+
*/
|
|
57110
|
+
var SharedRead = class {
|
|
57111
|
+
ttl;
|
|
57112
|
+
load;
|
|
57113
|
+
now;
|
|
57114
|
+
value;
|
|
57115
|
+
freshUntil = 0;
|
|
57116
|
+
retryAt = 0;
|
|
57117
|
+
failures = 0;
|
|
57118
|
+
error;
|
|
57119
|
+
pending;
|
|
57120
|
+
listeners = /* @__PURE__ */ new Set();
|
|
57121
|
+
releaseTimer;
|
|
57122
|
+
constructor(ttl, load, now) {
|
|
57123
|
+
this.ttl = ttl;
|
|
57124
|
+
this.load = load;
|
|
57125
|
+
this.now = now;
|
|
57126
|
+
}
|
|
57127
|
+
read(signal, progress = () => {}) {
|
|
57128
|
+
signal.throwIfAborted();
|
|
57129
|
+
if (this.value !== void 0) progress(this.value);
|
|
57130
|
+
if (this.now() < this.retryAt) return Promise.reject(new SpeakerReadDeferred(this.retryAt, this.error));
|
|
57131
|
+
if (this.value !== void 0 && this.now() < this.freshUntil) return Promise.resolve(this.value);
|
|
57132
|
+
clearTimeout(this.releaseTimer);
|
|
57133
|
+
if (this.pending?.controller.signal.aborted) this.pending = void 0;
|
|
57134
|
+
if (this.pending === void 0) {
|
|
57135
|
+
const controller = new AbortController();
|
|
57136
|
+
const emit = (value) => {
|
|
57137
|
+
controller.signal.throwIfAborted();
|
|
57138
|
+
this.value = value;
|
|
57139
|
+
for (const listener of this.listeners) listener(value);
|
|
57140
|
+
};
|
|
57141
|
+
const promise = Promise.resolve().then(async () => {
|
|
57142
|
+
controller.signal.throwIfAborted();
|
|
57143
|
+
const value = await this.load(controller.signal, emit);
|
|
57144
|
+
controller.signal.throwIfAborted();
|
|
57145
|
+
emit(value);
|
|
57146
|
+
this.freshUntil = this.now() + this.ttl;
|
|
57147
|
+
this.failures = 0;
|
|
57148
|
+
this.retryAt = 0;
|
|
57149
|
+
this.error = void 0;
|
|
57150
|
+
return value;
|
|
57151
|
+
}).catch((error) => {
|
|
57152
|
+
if (controller.signal.aborted) throw error;
|
|
57153
|
+
this.failures += 1;
|
|
57154
|
+
const limited = /(?:\b429\b|rate.?limit|too many requests)/i.test(error instanceof Error ? error.message : String(error));
|
|
57155
|
+
this.retryAt = this.now() + Math.min(5 * 6e4, (limited ? 6e4 : 15e3) * 2 ** Math.min(4, this.failures - 1));
|
|
57156
|
+
this.error = error;
|
|
57157
|
+
throw new SpeakerReadDeferred(this.retryAt, error);
|
|
57158
|
+
}).finally(() => {
|
|
57159
|
+
if (this.pending?.controller === controller) this.pending = void 0;
|
|
57160
|
+
});
|
|
57161
|
+
this.pending = {
|
|
57162
|
+
controller,
|
|
57163
|
+
promise
|
|
57164
|
+
};
|
|
57165
|
+
}
|
|
57166
|
+
const pending = this.pending;
|
|
57167
|
+
return new Promise((resolve, reject) => {
|
|
57168
|
+
const listener = (value) => {
|
|
57169
|
+
if (!signal.aborted) progress(value);
|
|
57170
|
+
};
|
|
57171
|
+
this.listeners.add(listener);
|
|
57172
|
+
const cleanup = () => {
|
|
57173
|
+
signal.removeEventListener("abort", abort);
|
|
57174
|
+
this.listeners.delete(listener);
|
|
57175
|
+
if (this.listeners.size === 0 && this.pending === pending) this.releaseTimer = setTimeout(() => {
|
|
57176
|
+
if (this.listeners.size === 0 && this.pending === pending) pending.controller.abort();
|
|
57177
|
+
}, 250);
|
|
57178
|
+
};
|
|
57179
|
+
const abort = () => {
|
|
57180
|
+
cleanup();
|
|
57181
|
+
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
57182
|
+
};
|
|
57183
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
57184
|
+
pending.promise.then((value) => {
|
|
57185
|
+
cleanup();
|
|
57186
|
+
if (!signal.aborted) resolve(value);
|
|
57187
|
+
}, (error) => {
|
|
57188
|
+
cleanup();
|
|
57189
|
+
if (!signal.aborted) reject(error);
|
|
57190
|
+
});
|
|
57191
|
+
});
|
|
57192
|
+
}
|
|
57193
|
+
invalidate() {
|
|
57194
|
+
clearTimeout(this.releaseTimer);
|
|
57195
|
+
this.pending?.controller.abort();
|
|
57196
|
+
this.pending = void 0;
|
|
57197
|
+
this.freshUntil = 0;
|
|
57198
|
+
}
|
|
57199
|
+
dispose() {
|
|
57200
|
+
this.invalidate();
|
|
57201
|
+
this.listeners.clear();
|
|
57202
|
+
this.value = void 0;
|
|
57203
|
+
}
|
|
57204
|
+
};
|
|
57205
|
+
function pause(milliseconds, signal) {
|
|
57206
|
+
if (milliseconds <= 0) return Promise.resolve();
|
|
57207
|
+
return new Promise((resolve, reject) => {
|
|
57208
|
+
const abort = () => {
|
|
57209
|
+
clearTimeout(timer);
|
|
57210
|
+
reject(signal.reason);
|
|
57211
|
+
};
|
|
57212
|
+
const timer = setTimeout(() => {
|
|
57213
|
+
signal.removeEventListener("abort", abort);
|
|
57214
|
+
resolve();
|
|
57215
|
+
}, milliseconds);
|
|
57216
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
57217
|
+
if (signal.aborted) abort();
|
|
57218
|
+
});
|
|
57219
|
+
}
|
|
57220
|
+
var RecognizedSpeakerDirectory = class {
|
|
57221
|
+
loaders;
|
|
57222
|
+
pageGapMs;
|
|
57223
|
+
now;
|
|
57224
|
+
accounts = /* @__PURE__ */ new Map();
|
|
57225
|
+
constructor(loaders = {
|
|
57226
|
+
marked: readSpeakerOptions,
|
|
57227
|
+
page: readSpeakerPage,
|
|
57228
|
+
presence: readSpeakerPresence
|
|
57229
|
+
}, pageGapMs = 750, now = Date.now) {
|
|
57230
|
+
this.loaders = loaders;
|
|
57231
|
+
this.pageGapMs = pageGapMs;
|
|
57232
|
+
this.now = now;
|
|
57233
|
+
}
|
|
57234
|
+
account(account) {
|
|
57235
|
+
const found = this.accounts.get(account);
|
|
57236
|
+
if (found !== void 0) return found;
|
|
57237
|
+
const pages = /* @__PURE__ */ new Map();
|
|
57238
|
+
let startedAt = 0, lastRequestAt = 0, completed = false;
|
|
57239
|
+
let state;
|
|
57240
|
+
state = {
|
|
57241
|
+
pages,
|
|
57242
|
+
marked: new SharedRead(6e4, (signal) => this.loaders.marked(signal), this.now),
|
|
57243
|
+
presence: new SharedRead(6e4, (signal) => this.loaders.presence(signal), this.now),
|
|
57244
|
+
candidates: new SharedRead(5 * 6e4, async (signal, emit) => {
|
|
57245
|
+
if (completed || this.now() - startedAt >= 5 * 6e4) pages.clear();
|
|
57246
|
+
if (pages.size === 0) startedAt = this.now();
|
|
57247
|
+
completed = false;
|
|
57248
|
+
let total;
|
|
57249
|
+
const result = await loadSpeakerCandidateSnapshot(async (cursor) => {
|
|
57250
|
+
const cached = pages.get(cursor);
|
|
57251
|
+
if (cached !== void 0) return cached;
|
|
57252
|
+
await pause(Math.max(0, lastRequestAt + this.pageGapMs - this.now()), signal);
|
|
57253
|
+
signal.throwIfAborted();
|
|
57254
|
+
lastRequestAt = this.now();
|
|
57255
|
+
const page = await this.loaders.page(cursor, signal);
|
|
57256
|
+
signal.throwIfAborted();
|
|
57257
|
+
if (page.cursorStale) {
|
|
57258
|
+
pages.clear();
|
|
57259
|
+
startedAt = this.now();
|
|
57260
|
+
} else if (page.projectionState === void 0 || page.projectionState === "fresh") pages.set(cursor, page);
|
|
57261
|
+
return page;
|
|
57262
|
+
}, signal, (snapshot) => {
|
|
57263
|
+
const first = pages.get("");
|
|
57264
|
+
total = first?.coverage !== "partial" ? first?.total : void 0;
|
|
57265
|
+
if (!state.candidates.value?.complete || snapshot.complete) emit({
|
|
57266
|
+
...snapshot,
|
|
57267
|
+
total
|
|
57268
|
+
});
|
|
57269
|
+
});
|
|
57270
|
+
completed = result.complete;
|
|
57271
|
+
if (!result.complete) {
|
|
57272
|
+
if (!state.candidates.value?.complete) emit({
|
|
57273
|
+
...result,
|
|
57274
|
+
total
|
|
57275
|
+
});
|
|
57276
|
+
throw new Error("说话人列表尚未完整,请稍后重试");
|
|
57277
|
+
}
|
|
57278
|
+
return {
|
|
57279
|
+
...result,
|
|
57280
|
+
total
|
|
57281
|
+
};
|
|
57282
|
+
}, this.now)
|
|
57283
|
+
};
|
|
57284
|
+
this.accounts.set(account, state);
|
|
57285
|
+
return state;
|
|
57286
|
+
}
|
|
57287
|
+
peekMarked(account) {
|
|
57288
|
+
return this.accounts.get(account)?.marked.value;
|
|
57289
|
+
}
|
|
57290
|
+
peekPresence(account) {
|
|
57291
|
+
return this.accounts.get(account)?.presence.value;
|
|
57292
|
+
}
|
|
57293
|
+
peekCandidates(account) {
|
|
57294
|
+
return this.accounts.get(account)?.candidates.value;
|
|
57295
|
+
}
|
|
57296
|
+
readMarked(account, signal) {
|
|
57297
|
+
return this.account(account).marked.read(signal);
|
|
57298
|
+
}
|
|
57299
|
+
readPresence(account, signal) {
|
|
57300
|
+
return this.account(account).presence.read(signal);
|
|
57301
|
+
}
|
|
57302
|
+
refreshPresence(account, signal) {
|
|
57303
|
+
this.account(account).presence.invalidate();
|
|
57304
|
+
return this.readPresence(account, signal);
|
|
57305
|
+
}
|
|
57306
|
+
readCandidates(account, signal, progress) {
|
|
57307
|
+
return this.account(account).candidates.read(signal, progress);
|
|
57308
|
+
}
|
|
57309
|
+
invalidate(account) {
|
|
57310
|
+
const state = this.accounts.get(account);
|
|
57311
|
+
if (state === void 0) return;
|
|
57312
|
+
state.pages.clear();
|
|
57313
|
+
state.marked.invalidate();
|
|
57314
|
+
state.presence.invalidate();
|
|
57315
|
+
state.candidates.invalidate();
|
|
57316
|
+
}
|
|
57317
|
+
clear() {
|
|
57318
|
+
for (const state of this.accounts.values()) {
|
|
57319
|
+
state.marked.dispose();
|
|
57320
|
+
state.presence.dispose();
|
|
57321
|
+
state.candidates.dispose();
|
|
57322
|
+
}
|
|
57323
|
+
this.accounts.clear();
|
|
57324
|
+
}
|
|
57325
|
+
};
|
|
57326
|
+
const recognizedSpeakerDirectory = new RecognizedSpeakerDirectory();
|
|
57327
|
+
const accountKey = () => {
|
|
57328
|
+
const auth = arkmeAuthStore.getSnapshot().auth;
|
|
57329
|
+
return auth?.status === "authenticated" ? `${auth.environment}:${auth.userId}` : "";
|
|
57330
|
+
};
|
|
57331
|
+
let activeAccount = accountKey();
|
|
57332
|
+
arkmeAuthStore.subscribe(() => {
|
|
57333
|
+
const next = accountKey();
|
|
57334
|
+
if (next !== activeAccount) {
|
|
57335
|
+
activeAccount = next;
|
|
57336
|
+
recognizedSpeakerDirectory.clear();
|
|
57337
|
+
}
|
|
57338
|
+
});
|
|
57339
|
+
//#endregion
|
|
56816
57340
|
//#region src/client/recordings/recording-speaker-options-store.ts
|
|
56817
57341
|
function recordingSpeakerAccount(auth) {
|
|
56818
57342
|
return auth?.status === "authenticated" && auth.userId !== void 0 ? `${auth.environment}:${auth.userId}` : void 0;
|
|
@@ -56868,6 +57392,10 @@ body[data-ds-dark-theme] .arkme-bot-identity {
|
|
|
56868
57392
|
throw error;
|
|
56869
57393
|
} finally {
|
|
56870
57394
|
if (context.current()) {
|
|
57395
|
+
if (binding.account !== void 0) {
|
|
57396
|
+
recognizedSpeakerTracker.uncertain(binding.account);
|
|
57397
|
+
recognizedSpeakerDirectory.invalidate(binding.account);
|
|
57398
|
+
}
|
|
56871
57399
|
recordingSpeakerOptions.reset();
|
|
56872
57400
|
recordingSpeakerOptions.invalidate();
|
|
56873
57401
|
recordingSpeakerItemContexts.reset((candidateKey) => candidateKey === key || !recordingSpeakerItemContexts.get(candidateKey).mutating);
|
|
@@ -123941,7 +124469,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
123941
124469
|
function detailExtensionSenderName(item) {
|
|
123942
124470
|
return item.senderDisplayName.trim() || (item.sourceKind === "agent_message" ? "Agent" : "未知用户");
|
|
123943
124471
|
}
|
|
123944
|
-
function detailExtensionAuthor(item, personalSource, profile) {
|
|
124472
|
+
function detailExtensionAuthor(item, personalSource, profile, sourceKind, conversationMembers = []) {
|
|
123945
124473
|
const role = personalSource && item.sourceKind === "record_extension" ? item.selfRole : void 0;
|
|
123946
124474
|
if (role !== void 0) return {
|
|
123947
124475
|
name: role.name,
|
|
@@ -123949,16 +124477,21 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
123949
124477
|
role
|
|
123950
124478
|
};
|
|
123951
124479
|
const ownRecord = personalSource && item.sourceKind === "record_extension" && profile !== void 0 && (item.recordOwnerUserId === void 0 || item.recordOwnerUserId === profile.userId);
|
|
124480
|
+
const currentNameFallback = ownRecord && item.senderNameSnapshot !== true && item.senderDisplayName.trim() === "我";
|
|
124481
|
+
const privateOwn = sourceKind === "private_chat" && item.senderIsMe === true && profile !== void 0;
|
|
124482
|
+
const member = item.senderMemberRef === void 0 ? void 0 : conversationMembers.find((candidate) => candidate.memberRef === item.senderMemberRef);
|
|
124483
|
+
const memberName = member?.displayName.trim();
|
|
123952
124484
|
return {
|
|
123953
|
-
name:
|
|
123954
|
-
avatar: arkmePersonalAvatarRef({
|
|
124485
|
+
name: privateOwn || currentNameFallback ? profile?.nickname.trim() || profile?.displayName.trim() || detailExtensionSenderName(item) : memberName && memberName !== "群成员" ? memberName : detailExtensionSenderName(item),
|
|
124486
|
+
avatar: privateOwn ? profile?.avatarRef.trim() || member?.avatarRef?.trim() || item.senderAvatarUrl || "" : member?.avatarRef?.trim() || arkmePersonalAvatarRef({
|
|
123955
124487
|
isMe: ownRecord,
|
|
123956
124488
|
...item.senderAvatarUrl === void 0 ? {} : { avatarRef: item.senderAvatarUrl }
|
|
123957
|
-
}, profile)
|
|
124489
|
+
}, profile) || ""
|
|
123958
124490
|
};
|
|
123959
124491
|
}
|
|
123960
124492
|
function detailExtensionTimelineItem$1(item, author) {
|
|
123961
124493
|
const avatar = author.avatar;
|
|
124494
|
+
const mediaOnlyUnavailable = item.mediaUnavailable === true && item.mediaItems.length > 0 && item.title.trim() === "" && item.textContent.trim() === "" && (item.contentBlocks?.length ?? 0) === 0;
|
|
123962
124495
|
return {
|
|
123963
124496
|
itemUid: item.recordUid,
|
|
123964
124497
|
senderName: author.name,
|
|
@@ -123972,7 +124505,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
123972
124505
|
templateKind: item.templateKind,
|
|
123973
124506
|
displayKind: item.displayKind,
|
|
123974
124507
|
...item.contentBlocks === void 0 ? {} : { contentBlocks: item.contentBlocks },
|
|
123975
|
-
...
|
|
124508
|
+
...mediaOnlyUnavailable ? { mediaUnavailable: true } : {},
|
|
123976
124509
|
...author.role === void 0 ? {} : { selfRole: author.role },
|
|
123977
124510
|
...avatar !== "" && !/^(https?:|data:|blob:)/iu.test(avatar) ? { avatarRef: avatar } : {}
|
|
123978
124511
|
};
|
|
@@ -124076,7 +124609,7 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124076
124609
|
})]
|
|
124077
124610
|
});
|
|
124078
124611
|
}
|
|
124079
|
-
function DetailExtensionContext({ state, optimistic, selectedRecordUid, sourceRef, sourceIdentityKey, shareWebsite, onMessageCopyLinkOpen, onMentionClick, isMentionClickable, onRetry, onSelect, personalSource, currentSelfProfile }) {
|
|
124612
|
+
function DetailExtensionContext({ state, optimistic, selectedRecordUid, sourceRef, sourceIdentityKey, shareWebsite, onMessageCopyLinkOpen, onMentionClick, isMentionClickable, onRetry, onSelect, personalSource, currentSelfProfile, sourceKind, conversationMembers }) {
|
|
124080
124613
|
const context = state.kind === "success" ? state.context : void 0;
|
|
124081
124614
|
const byUid = /* @__PURE__ */ new Map();
|
|
124082
124615
|
for (const item of optimistic) byUid.set(item.recordUid, item);
|
|
@@ -124119,8 +124652,9 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124119
124652
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
124120
124653
|
style: styles$56.extensionContextList,
|
|
124121
124654
|
children: orderedDetailExtensions(extensions, context?.parentRecordUid ?? "").map(({ item: extension, nested }) => {
|
|
124122
|
-
const author = detailExtensionAuthor(extension, personalSource, currentSelfProfile);
|
|
124655
|
+
const author = detailExtensionAuthor(extension, personalSource, currentSelfProfile, sourceKind, conversationMembers);
|
|
124123
124656
|
const timelineItem = detailExtensionTimelineItem$1(extension, author);
|
|
124657
|
+
const missingMedia = extension.mediaUnavailable === true && extension.mediaItems.length > 0 && (extension.title.trim() !== "" || extension.textContent.trim() !== "" || (extension.contentBlocks?.length ?? 0) > 0);
|
|
124124
124658
|
const selected = extension.recordUid === selectedRecordUid;
|
|
124125
124659
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
124126
124660
|
style: {
|
|
@@ -124146,26 +124680,44 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124146
124680
|
size: nested ? 28 : 32
|
|
124147
124681
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
124148
124682
|
style: styles$56.extensionContextBody,
|
|
124149
|
-
children: [
|
|
124150
|
-
|
|
124151
|
-
|
|
124152
|
-
|
|
124153
|
-
|
|
124154
|
-
|
|
124155
|
-
|
|
124156
|
-
|
|
124157
|
-
|
|
124158
|
-
|
|
124159
|
-
|
|
124160
|
-
|
|
124161
|
-
|
|
124162
|
-
|
|
124163
|
-
|
|
124164
|
-
|
|
124165
|
-
|
|
124166
|
-
|
|
124167
|
-
|
|
124168
|
-
|
|
124683
|
+
children: [
|
|
124684
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
124685
|
+
style: styles$56.extensionContextHead,
|
|
124686
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
124687
|
+
style: styles$56.extensionContextName,
|
|
124688
|
+
children: author.name
|
|
124689
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
124690
|
+
style: styles$56.extensionContextTime,
|
|
124691
|
+
children: [dateLabel$1(extension.sendAtMillis), timeLabel$5(extension.sendAtMillis)].filter(Boolean).join(" ")
|
|
124692
|
+
})]
|
|
124693
|
+
}),
|
|
124694
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeMessageContent, {
|
|
124695
|
+
presentation: "detail",
|
|
124696
|
+
item: timelineItem,
|
|
124697
|
+
highlightMentions: true,
|
|
124698
|
+
...sourceRef === void 0 ? {} : { sourceRef },
|
|
124699
|
+
...sourceIdentityKey === void 0 ? {} : { sourceIdentityKey },
|
|
124700
|
+
...shareWebsite === void 0 ? {} : { shareWebsite },
|
|
124701
|
+
...onMessageCopyLinkOpen === void 0 ? {} : { onMessageCopyLinkOpen },
|
|
124702
|
+
...onMentionClick === void 0 ? {} : { onMentionClick },
|
|
124703
|
+
...isMentionClickable === void 0 ? {} : { isMentionClickable }
|
|
124704
|
+
}),
|
|
124705
|
+
missingMedia && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
124706
|
+
"data-arkme-missing-extension-media": true,
|
|
124707
|
+
style: {
|
|
124708
|
+
display: "inline-flex",
|
|
124709
|
+
alignItems: "center",
|
|
124710
|
+
gap: 4,
|
|
124711
|
+
marginTop: 5,
|
|
124712
|
+
color: arkmeTheme.tertiary,
|
|
124713
|
+
fontSize: 12
|
|
124714
|
+
},
|
|
124715
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(o$22, {
|
|
124716
|
+
size: 13,
|
|
124717
|
+
"aria-hidden": true
|
|
124718
|
+
}), tr$1("附件暂不可用")]
|
|
124719
|
+
})
|
|
124720
|
+
]
|
|
124169
124721
|
})]
|
|
124170
124722
|
}, extension.recordUid);
|
|
124171
124723
|
})
|
|
@@ -124212,10 +124764,18 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124212
124764
|
const controller = new AbortController();
|
|
124213
124765
|
listAbortRef.current = controller;
|
|
124214
124766
|
setRelatedState((current) => current.kind === "success" ? current : { kind: "loading" });
|
|
124215
|
-
callArkme("source.related-quick-notes.from-message", {
|
|
124767
|
+
const readRelated = () => callArkme("source.related-quick-notes.from-message", {
|
|
124216
124768
|
sourceRef: normalizedSourceRef,
|
|
124217
124769
|
messageActionRef
|
|
124218
|
-
}, controller.signal)
|
|
124770
|
+
}, controller.signal);
|
|
124771
|
+
readRelated().then(async (first) => {
|
|
124772
|
+
if (first.items.length > 0 || controller.signal.aborted) return first;
|
|
124773
|
+
try {
|
|
124774
|
+
return await readRelated();
|
|
124775
|
+
} catch {
|
|
124776
|
+
return first;
|
|
124777
|
+
}
|
|
124778
|
+
}).then((list) => {
|
|
124219
124779
|
if (controller.signal.aborted || listAbortRef.current !== controller) return;
|
|
124220
124780
|
setRelatedState(list.items.length === 0 ? { kind: "empty" } : {
|
|
124221
124781
|
kind: "success",
|
|
@@ -124362,9 +124922,10 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124362
124922
|
const textContent = showOriginal && item.aiPolish?.originalText !== void 0 ? item.aiPolish.originalText : item.aiPolish?.state === "polished" && item.aiPolish.polishedText !== void 0 ? item.aiPolish.polishedText : item.textContent;
|
|
124363
124923
|
const canToggle = item.aiPolish?.state === "polished" && item.aiPolish.originalText !== void 0 && item.aiPolish.polishedText !== void 0;
|
|
124364
124924
|
const personalSource = sourceKind === "send_to_self" || sourceKind === "topic" || sourceKind === "default_category";
|
|
124925
|
+
const privateOwnCurrentName = sourceKind === "private_chat" && item.isMe && item.senderKind !== "bot" && currentSelfProfile !== void 0;
|
|
124365
124926
|
const currentNameFallback = personalSource && item.isMe && item.avatarSnapshot === true && item.senderNameSnapshot !== true && currentSelfProfile !== void 0;
|
|
124366
124927
|
const selfRole = sourceKind === void 0 ? void 0 : arkmeSelfRoleForPresentation(item, sourceKind);
|
|
124367
|
-
const authorName = selfRole?.name ?? (currentNameFallback ? currentSelfProfile?.nickname.trim() || currentSelfProfile?.displayName.trim() || item.senderName : arkmeTimelineDetailSenderText(item, conversationMembers));
|
|
124928
|
+
const authorName = selfRole?.name ?? (privateOwnCurrentName || currentNameFallback ? currentSelfProfile?.nickname.trim() || currentSelfProfile?.displayName.trim() || item.senderName : arkmeTimelineDetailSenderText(item, conversationMembers));
|
|
124368
124929
|
const authorAvatarRef = personalSource ? arkmePersonalAvatarRef(item, currentSelfProfile) : item.avatarRef;
|
|
124369
124930
|
const roleAvatarFallback = selfRole === void 0 ? void 0 : arkmeSelfRoleAvatarFallback(selfRole);
|
|
124370
124931
|
const topicTitle = selfTopicPath?.trim() || item.selfTopic?.title?.trim() || tr$1("未指定主题");
|
|
@@ -124579,6 +125140,8 @@ body[data-ds-dark-theme] .arkme-mention-all-avatar [data-arkme-theme-image="dark
|
|
|
124579
125140
|
state: extensionState,
|
|
124580
125141
|
optimistic: optimisticExtensions,
|
|
124581
125142
|
personalSource,
|
|
125143
|
+
sourceKind,
|
|
125144
|
+
conversationMembers,
|
|
124582
125145
|
...currentSelfProfile === void 0 ? {} : { currentSelfProfile },
|
|
124583
125146
|
...selectedExtensionRecordUid === void 0 ? {} : { selectedRecordUid: selectedExtensionRecordUid },
|
|
124584
125147
|
...sourceRef === void 0 ? {} : { sourceRef },
|
|
@@ -154041,7 +154604,7 @@ body:has([data-arkme-self-topic-menu]) > [role="menu"] { z-index: 10030; }
|
|
|
154041
154604
|
};
|
|
154042
154605
|
//#endregion
|
|
154043
154606
|
//#region node_modules/@rc-component/util/es/hooks/useMemo.js
|
|
154044
|
-
function useMemo$
|
|
154607
|
+
function useMemo$37(getValue, condition, shouldUpdate) {
|
|
154045
154608
|
const cacheRef = react.useRef({});
|
|
154046
154609
|
if (!("value" in cacheRef.current) || shouldUpdate(cacheRef.current.condition, condition)) {
|
|
154047
154610
|
cacheRef.current.value = getValue();
|
|
@@ -154154,7 +154717,7 @@ body:has([data-arkme-self-topic-menu]) > [role="menu"] { z-index: 10030; }
|
|
|
154154
154717
|
};
|
|
154155
154718
|
};
|
|
154156
154719
|
const useComposeRef = (...refs) => {
|
|
154157
|
-
return useMemo$
|
|
154720
|
+
return useMemo$37(() => composeRef(...refs), refs, (prev, next) => prev.length !== next.length || prev.every((ref, i) => ref !== next[i]));
|
|
154158
154721
|
};
|
|
154159
154722
|
const supportRef = (nodeOrComponent) => {
|
|
154160
154723
|
if (!nodeOrComponent) return false;
|
|
@@ -171867,8 +172430,19 @@ html body {
|
|
|
171867
172430
|
o$11.displayName = "CheckIcon";
|
|
171868
172431
|
const n$6 = o$11;
|
|
171869
172432
|
//#endregion
|
|
172433
|
+
//#region src/client/ArkmeModelPricing.tsx
|
|
172434
|
+
/** One disclosure per menu keeps pricing available without repeating it in every row. */
|
|
172435
|
+
function ArkmeModelPricing({ models }) {
|
|
172436
|
+
const pricedModels = models.filter((model) => model.description);
|
|
172437
|
+
if (pricedModels.length === 0) return null;
|
|
172438
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
172439
|
+
className: "arkme-model-price",
|
|
172440
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: tr$1("按用量扣积分 · 计费说明") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", { children: pricedModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: model.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: model.description })] }, model.id)) })]
|
|
172441
|
+
});
|
|
172442
|
+
}
|
|
172443
|
+
//#endregion
|
|
171870
172444
|
//#region src/client/arkme-model-select.css?inline
|
|
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:
|
|
172445
|
+
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 border-top: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n margin-top: 4px;\n padding: 10px;\n font-size: 12px;\n}\n\n.arkme-model-price summary {\n cursor: pointer;\n}\n\n.arkme-model-price summary:focus-visible {\n outline-offset: 2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-price dl {\n overflow-wrap: anywhere;\n margin: 0;\n line-height: 1.6;\n}\n\n.arkme-model-price dl > div {\n margin-top: 10px;\n}\n\n.arkme-model-price dt {\n color: var(--dsw-alias-label-primary, #20232c);\n}\n\n.arkme-model-price dd {\n margin: 2px 0 0;\n}\n";
|
|
171872
172446
|
//#endregion
|
|
171873
172447
|
//#region src/client/ArkoModelMenu.tsx
|
|
171874
172448
|
function ArkoModelMenu({ anchor, catalog, busy, error, onSelect, onClose }) {
|
|
@@ -171938,7 +172512,7 @@ html body {
|
|
|
171938
172512
|
"Home",
|
|
171939
172513
|
"End"
|
|
171940
172514
|
].includes(event.key)) return;
|
|
171941
|
-
const items = Array.from(menu.current?.querySelectorAll("button:not(:disabled)") ?? []);
|
|
172515
|
+
const items = Array.from(menu.current?.querySelectorAll("button:not(:disabled), summary") ?? []);
|
|
171942
172516
|
if (!items.length) return;
|
|
171943
172517
|
event.preventDefault();
|
|
171944
172518
|
event.stopPropagation();
|
|
@@ -171957,7 +172531,7 @@ html body {
|
|
|
171957
172531
|
children: [
|
|
171958
172532
|
catalog.options.map((option) => {
|
|
171959
172533
|
const selected = option.routeKey === catalog.effectiveRouteKey;
|
|
171960
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
172534
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
171961
172535
|
type: "button",
|
|
171962
172536
|
className: "arkme-model-option",
|
|
171963
172537
|
role: "menuitemradio",
|
|
@@ -171977,11 +172551,13 @@ html body {
|
|
|
171977
172551
|
style: { flex: "none" },
|
|
171978
172552
|
"aria-hidden": true
|
|
171979
172553
|
})]
|
|
171980
|
-
}), option.
|
|
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);
|
|
172554
|
+
}) }, option.routeKey);
|
|
171984
172555
|
}),
|
|
172556
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeModelPricing, { models: catalog.options.map((option) => ({
|
|
172557
|
+
id: option.routeKey,
|
|
172558
|
+
name: option.displayName,
|
|
172559
|
+
description: option.costDescription
|
|
172560
|
+
})) }),
|
|
171985
172561
|
busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
171986
172562
|
className: "arkme-model-status",
|
|
171987
172563
|
role: "status",
|
|
@@ -177478,6 +178054,132 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
177478
178054
|
e$36.displayName = "FingerprintIcon";
|
|
177479
178055
|
const p$2 = e$36;
|
|
177480
178056
|
//#endregion
|
|
178057
|
+
//#region src/client/recordings/RecognizedSpeakerEntry.tsx
|
|
178058
|
+
function RecognizedSpeakerEntry({ accountKey, active, onOpen, style, readMarked = readSpeakerOptions, readPage = readSpeakerPage, directory: providedDirectory }) {
|
|
178059
|
+
useArkmeLocale();
|
|
178060
|
+
const directory = (0, react$1.useMemo)(() => providedDirectory ?? (readMarked === readSpeakerOptions && readPage === readSpeakerPage ? recognizedSpeakerDirectory : new RecognizedSpeakerDirectory({
|
|
178061
|
+
marked: readMarked,
|
|
178062
|
+
page: readPage,
|
|
178063
|
+
presence: readSpeakerPresence
|
|
178064
|
+
}, 0)), [
|
|
178065
|
+
providedDirectory,
|
|
178066
|
+
readMarked,
|
|
178067
|
+
readPage
|
|
178068
|
+
]);
|
|
178069
|
+
const snapshot = (0, react$1.useSyncExternalStore)(recognizedSpeakerTracker.subscribe, () => recognizedSpeakerTracker.get(accountKey), () => recognizedSpeakerTracker.get(accountKey));
|
|
178070
|
+
(0, react$1.useEffect)(() => {
|
|
178071
|
+
if (!active || accountKey === void 0) return;
|
|
178072
|
+
const controller = new AbortController();
|
|
178073
|
+
let busy = false;
|
|
178074
|
+
let retryTimer;
|
|
178075
|
+
const refresh = async () => {
|
|
178076
|
+
if (busy || controller.signal.aborted || typeof document !== "undefined" && document.visibilityState === "hidden") return;
|
|
178077
|
+
busy = true;
|
|
178078
|
+
try {
|
|
178079
|
+
let marked;
|
|
178080
|
+
const updateTotal = () => {
|
|
178081
|
+
const value = directory.peekCandidates(accountKey);
|
|
178082
|
+
if (marked !== void 0 && value?.total !== void 0 && !controller.signal.aborted) recognizedSpeakerTracker.setTotal(accountKey, markedSpeakerKeys(marked).length + value.total);
|
|
178083
|
+
};
|
|
178084
|
+
const [, result] = await Promise.all([directory.readMarked(accountKey, controller.signal).then((value) => {
|
|
178085
|
+
marked = value;
|
|
178086
|
+
updateTotal();
|
|
178087
|
+
}), directory.readCandidates(accountKey, controller.signal, updateTotal)]);
|
|
178088
|
+
if (controller.signal.aborted) return;
|
|
178089
|
+
if (result.complete && marked !== void 0) recognizedSpeakerTracker.observe(accountKey, marked, result.items);
|
|
178090
|
+
else recognizedSpeakerTracker.uncertain(accountKey);
|
|
178091
|
+
} catch (error) {
|
|
178092
|
+
if (!controller.signal.aborted) {
|
|
178093
|
+
recognizedSpeakerTracker.uncertain(accountKey);
|
|
178094
|
+
const delay = speakerRetryDelay(error);
|
|
178095
|
+
if (delay !== void 0) {
|
|
178096
|
+
clearTimeout(retryTimer);
|
|
178097
|
+
retryTimer = setTimeout(() => {
|
|
178098
|
+
refresh();
|
|
178099
|
+
}, delay);
|
|
178100
|
+
}
|
|
178101
|
+
}
|
|
178102
|
+
} finally {
|
|
178103
|
+
busy = false;
|
|
178104
|
+
}
|
|
178105
|
+
};
|
|
178106
|
+
refresh();
|
|
178107
|
+
const timer = setInterval(() => {
|
|
178108
|
+
refresh();
|
|
178109
|
+
}, 6e4);
|
|
178110
|
+
const onVisible = () => {
|
|
178111
|
+
refresh();
|
|
178112
|
+
};
|
|
178113
|
+
if (typeof document !== "undefined") document.addEventListener("visibilitychange", onVisible);
|
|
178114
|
+
return () => {
|
|
178115
|
+
controller.abort();
|
|
178116
|
+
clearInterval(timer);
|
|
178117
|
+
clearTimeout(retryTimer);
|
|
178118
|
+
if (typeof document !== "undefined") document.removeEventListener("visibilitychange", onVisible);
|
|
178119
|
+
};
|
|
178120
|
+
}, [
|
|
178121
|
+
accountKey,
|
|
178122
|
+
active,
|
|
178123
|
+
directory
|
|
178124
|
+
]);
|
|
178125
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
178126
|
+
"data-arkme-feedback": "recording-action",
|
|
178127
|
+
type: "button",
|
|
178128
|
+
style: {
|
|
178129
|
+
...style,
|
|
178130
|
+
flexDirection: "column",
|
|
178131
|
+
minWidth: 0,
|
|
178132
|
+
fontSize: 13
|
|
178133
|
+
},
|
|
178134
|
+
onClick: onOpen,
|
|
178135
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
178136
|
+
style: {
|
|
178137
|
+
display: "flex",
|
|
178138
|
+
maxWidth: "100%",
|
|
178139
|
+
alignItems: "center",
|
|
178140
|
+
justifyContent: "center",
|
|
178141
|
+
gap: 4
|
|
178142
|
+
},
|
|
178143
|
+
children: [
|
|
178144
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$7, {
|
|
178145
|
+
size: 16,
|
|
178146
|
+
style: { flexShrink: 0 },
|
|
178147
|
+
"aria-hidden": true
|
|
178148
|
+
}),
|
|
178149
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
178150
|
+
title: tr$1("已识别说话人"),
|
|
178151
|
+
style: {
|
|
178152
|
+
minWidth: 0,
|
|
178153
|
+
overflow: "hidden",
|
|
178154
|
+
textOverflow: "ellipsis"
|
|
178155
|
+
},
|
|
178156
|
+
children: tr$1("已识别说话人")
|
|
178157
|
+
}),
|
|
178158
|
+
snapshot.total !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
178159
|
+
style: {
|
|
178160
|
+
flexShrink: 0,
|
|
178161
|
+
fontVariantNumeric: "tabular-nums"
|
|
178162
|
+
},
|
|
178163
|
+
children: snapshot.total
|
|
178164
|
+
}),
|
|
178165
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
|
|
178166
|
+
size: 12,
|
|
178167
|
+
style: { flexShrink: 0 },
|
|
178168
|
+
"aria-hidden": true
|
|
178169
|
+
})
|
|
178170
|
+
]
|
|
178171
|
+
}), (snapshot.newCount ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
178172
|
+
style: {
|
|
178173
|
+
fontSize: 11,
|
|
178174
|
+
lineHeight: "15px",
|
|
178175
|
+
fontWeight: 400
|
|
178176
|
+
},
|
|
178177
|
+
"aria-live": "polite",
|
|
178178
|
+
children: tr$1("新识别 {v0} 个", { v0: snapshot.newCount })
|
|
178179
|
+
})]
|
|
178180
|
+
});
|
|
178181
|
+
}
|
|
178182
|
+
//#endregion
|
|
177481
178183
|
//#region src/recording-time.ts
|
|
177482
178184
|
const RECORDING_MINIMUM_YEAR = 1970;
|
|
177483
178185
|
function recordingMinimumLocalDateMillis() {
|
|
@@ -185865,7 +186567,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
185865
186567
|
toolbar: {
|
|
185866
186568
|
marginTop: 12,
|
|
185867
186569
|
display: "grid",
|
|
185868
|
-
gridTemplateColumns: "repeat(
|
|
186570
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
185869
186571
|
alignItems: "stretch",
|
|
185870
186572
|
gap: 8
|
|
185871
186573
|
},
|
|
@@ -188095,25 +188797,14 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
188095
188797
|
"aria-hidden": true
|
|
188096
188798
|
}), tr$1("全天候录音")]
|
|
188097
188799
|
}),
|
|
188098
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
188099
|
-
"data-arkme-feedback": "recording-action",
|
|
188100
|
-
type: "button",
|
|
188800
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RecognizedSpeakerEntry, {
|
|
188101
188801
|
style: styles$21.mobileGuideButton,
|
|
188102
|
-
|
|
188802
|
+
accountKey: auth.auth?.status === "authenticated" ? `${auth.auth.environment}:${auth.auth.userId}` : void 0,
|
|
188803
|
+
active: active && ui.mode === "recordings",
|
|
188804
|
+
onOpen: () => {
|
|
188103
188805
|
tour.finish(false);
|
|
188104
188806
|
arkmeUi.showRecognizedSpeakers(selectedDate.getTime());
|
|
188105
|
-
}
|
|
188106
|
-
children: [
|
|
188107
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(n$7, {
|
|
188108
|
-
size: 16,
|
|
188109
|
-
"aria-hidden": true
|
|
188110
|
-
}),
|
|
188111
|
-
tr$1("已识别说话人"),
|
|
188112
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
|
|
188113
|
-
size: 12,
|
|
188114
|
-
"aria-hidden": true
|
|
188115
|
-
})
|
|
188116
|
-
]
|
|
188807
|
+
}
|
|
188117
188808
|
}),
|
|
188118
188809
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
188119
188810
|
"data-arkme-feedback": "recording-action",
|
|
@@ -189487,6 +190178,82 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189487
190178
|
});
|
|
189488
190179
|
}
|
|
189489
190180
|
//#endregion
|
|
190181
|
+
//#region src/client/recordings/SpeakerSelfGuide.tsx
|
|
190182
|
+
const loadVoiceprint = (signal) => callArkme("voiceprint.status", {}, signal);
|
|
190183
|
+
function SpeakerSelfGuide({ onOpenRecordings, readVoiceprint = loadVoiceprint }) {
|
|
190184
|
+
useArkmeLocale();
|
|
190185
|
+
const [state, setState] = (0, react$1.useState)({ loading: true });
|
|
190186
|
+
(0, react$1.useEffect)(() => {
|
|
190187
|
+
const controller = new AbortController();
|
|
190188
|
+
readVoiceprint(controller.signal).then((value) => {
|
|
190189
|
+
if (!controller.signal.aborted) setState({
|
|
190190
|
+
loading: false,
|
|
190191
|
+
value
|
|
190192
|
+
});
|
|
190193
|
+
}).catch(() => {
|
|
190194
|
+
if (!controller.signal.aborted) setState({ loading: false });
|
|
190195
|
+
});
|
|
190196
|
+
return () => {
|
|
190197
|
+
controller.abort();
|
|
190198
|
+
};
|
|
190199
|
+
}, [readVoiceprint]);
|
|
190200
|
+
if (state.loading) return null;
|
|
190201
|
+
const pending = state.value?.enrollmentPending === true;
|
|
190202
|
+
const hasVoiceprint = state.value?.hasVoiceprint === true;
|
|
190203
|
+
const title = pending ? "你的声纹正在处理中" : hasVoiceprint ? "已录入声纹,暂未在录音中匹配到你" : "还没有标记你的声音";
|
|
190204
|
+
const actionStyle = {
|
|
190205
|
+
border: 0,
|
|
190206
|
+
padding: 0,
|
|
190207
|
+
background: "transparent",
|
|
190208
|
+
color: arkmeTheme.accent,
|
|
190209
|
+
cursor: "pointer",
|
|
190210
|
+
font: "inherit",
|
|
190211
|
+
fontSize: 12
|
|
190212
|
+
};
|
|
190213
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
190214
|
+
"aria-label": tr$1("识别我的声音"),
|
|
190215
|
+
style: {
|
|
190216
|
+
padding: "12px 14px",
|
|
190217
|
+
marginBottom: 16,
|
|
190218
|
+
borderRadius: 10,
|
|
190219
|
+
background: arkmeTheme.layer1,
|
|
190220
|
+
fontSize: 13
|
|
190221
|
+
},
|
|
190222
|
+
children: [
|
|
190223
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: tr$1(title) }),
|
|
190224
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
190225
|
+
style: {
|
|
190226
|
+
marginTop: 5,
|
|
190227
|
+
color: arkmeTheme.secondary,
|
|
190228
|
+
fontSize: 12
|
|
190229
|
+
},
|
|
190230
|
+
children: tr$1("打开你的录音,点击说话人名称并选择自己;请先试听确认。")
|
|
190231
|
+
}),
|
|
190232
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190233
|
+
style: {
|
|
190234
|
+
display: "flex",
|
|
190235
|
+
gap: 18,
|
|
190236
|
+
flexWrap: "wrap",
|
|
190237
|
+
marginTop: 8
|
|
190238
|
+
},
|
|
190239
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
190240
|
+
type: "button",
|
|
190241
|
+
style: actionStyle,
|
|
190242
|
+
onClick: onOpenRecordings,
|
|
190243
|
+
children: tr$1("从录音中标记我")
|
|
190244
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
190245
|
+
type: "button",
|
|
190246
|
+
style: actionStyle,
|
|
190247
|
+
onClick: () => {
|
|
190248
|
+
arkmeUi.showVoiceprint();
|
|
190249
|
+
},
|
|
190250
|
+
children: tr$1(state.value !== void 0 && !hasVoiceprint && !pending ? "录入我的声纹" : "管理声纹")
|
|
190251
|
+
})]
|
|
190252
|
+
})
|
|
190253
|
+
]
|
|
190254
|
+
});
|
|
190255
|
+
}
|
|
190256
|
+
//#endregion
|
|
189490
190257
|
//#region src/client/ArkmeRecognizedSpeakersSurface.tsx
|
|
189491
190258
|
/** Group only by a stable owner identity, never by a shared name or speaker number. */
|
|
189492
190259
|
function identifiedSpeakerRows(options, candidates) {
|
|
@@ -189514,7 +190281,9 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189514
190281
|
name: tr$1("说话人 {v0}", { v0: candidate.speakerToken?.trim() || candidate.displayName }),
|
|
189515
190282
|
token: candidate.speakerToken?.trim() || "",
|
|
189516
190283
|
subtitle: candidate.subtitle,
|
|
189517
|
-
candidateRef: candidate.candidateRef
|
|
190284
|
+
candidateRef: candidate.candidateRef,
|
|
190285
|
+
dayCount: candidate.appearanceDays,
|
|
190286
|
+
lastSeenAt: candidate.latestAtMillis
|
|
189518
190287
|
});
|
|
189519
190288
|
}
|
|
189520
190289
|
return [...[...marked.values()].sort((left, right) => left.name.localeCompare(right.name)), ...unmarked.values()];
|
|
@@ -189600,6 +190369,19 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189600
190369
|
font: "inherit",
|
|
189601
190370
|
fontSize: 13
|
|
189602
190371
|
},
|
|
190372
|
+
sort: {
|
|
190373
|
+
flex: "none",
|
|
190374
|
+
height: 36,
|
|
190375
|
+
maxWidth: "100%",
|
|
190376
|
+
padding: "0 9px",
|
|
190377
|
+
border: `1px solid ${arkmeTheme.border}`,
|
|
190378
|
+
borderRadius: 9,
|
|
190379
|
+
background: arkmeTheme.base,
|
|
190380
|
+
color: arkmeTheme.text,
|
|
190381
|
+
font: "inherit",
|
|
190382
|
+
fontSize: 13,
|
|
190383
|
+
cursor: "pointer"
|
|
190384
|
+
},
|
|
189603
190385
|
list: {
|
|
189604
190386
|
minWidth: 0,
|
|
189605
190387
|
margin: 0,
|
|
@@ -189693,39 +190475,31 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189693
190475
|
borderBottom: `1px solid ${arkmeTheme.borderSoft}`
|
|
189694
190476
|
}
|
|
189695
190477
|
};
|
|
189696
|
-
const
|
|
189697
|
-
|
|
189698
|
-
|
|
189699
|
-
const defaultLoadUnmarked = async (cursor, signal) => await callArkme("directory.list", {
|
|
189700
|
-
section: "unmarked-speakers",
|
|
189701
|
-
limit: 50,
|
|
189702
|
-
...cursor === "" ? { refresh: true } : { cursor }
|
|
190478
|
+
const defaultLoadMarkedMembers = async (speakerRef, signal, expectedVersion) => await callArkme("recordings.speaker.members", {
|
|
190479
|
+
speakerRef,
|
|
190480
|
+
...expectedVersion === void 0 ? {} : { expectedVersion }
|
|
189703
190481
|
}, signal);
|
|
189704
190482
|
function failureMessage(error) {
|
|
189705
190483
|
return error instanceof Error && error.message.trim() !== "" ? error.message : tr$1("说话人列表暂时无法加载");
|
|
189706
190484
|
}
|
|
189707
190485
|
function markedPresenceLabel(stat, result, loading, error) {
|
|
190486
|
+
if (loading || result?.state === "building") return tr$1("出现统计整理中");
|
|
190487
|
+
if (error !== "" || result?.state === "failed" || result === void 0) return tr$1("出现统计暂不可用");
|
|
190488
|
+
if (result.state === "stale") return tr$1("出现统计更新中");
|
|
189708
190489
|
if (stat !== void 0) {
|
|
189709
190490
|
const date = new Date(stat.lastSeenAt);
|
|
189710
190491
|
if (!Number.isNaN(date.getTime())) {
|
|
189711
190492
|
const two = (value) => String(value).padStart(2, "0");
|
|
189712
190493
|
const recent = `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())} ${two(date.getHours())}:${two(date.getMinutes())}`;
|
|
189713
|
-
return
|
|
189714
|
-
v0: stat.dayCount,
|
|
189715
|
-
v1: recent
|
|
189716
|
-
}) : tr$1("出现 {v0} 天 · 最近 {v1}", {
|
|
190494
|
+
return tr$1("出现 {v0} 天 · 最近 {v1}", {
|
|
189717
190495
|
v0: stat.dayCount,
|
|
189718
190496
|
v1: recent
|
|
189719
190497
|
});
|
|
189720
190498
|
}
|
|
189721
190499
|
}
|
|
189722
|
-
if (loading || result?.state === "building") return tr$1("出现统计整理中");
|
|
189723
|
-
if (error !== "" || result?.state === "failed" || result === void 0) return tr$1("出现统计暂不可用");
|
|
189724
|
-
if (result.state === "stale") return tr$1("出现统计更新中");
|
|
189725
|
-
if (result.scope === "recent-seven-days") return tr$1("近 7 天未见已转写发声 · 全历史待接口");
|
|
189726
190500
|
return tr$1("暂无可统计的录音片段");
|
|
189727
190501
|
}
|
|
189728
|
-
function MarkedSpeakerDetail({ accountKey, speaker, loadMembers }) {
|
|
190502
|
+
function MarkedSpeakerDetail({ accountKey, speaker, loadMembers, version, onVersionChanged }) {
|
|
189729
190503
|
const [state, setState] = (0, react$1.useState)({
|
|
189730
190504
|
loading: true,
|
|
189731
190505
|
error: ""
|
|
@@ -189736,25 +190510,38 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189736
190510
|
loading: true,
|
|
189737
190511
|
error: ""
|
|
189738
190512
|
});
|
|
189739
|
-
|
|
189740
|
-
|
|
189741
|
-
|
|
189742
|
-
result,
|
|
189743
|
-
|
|
189744
|
-
|
|
189745
|
-
|
|
189746
|
-
|
|
189747
|
-
|
|
189748
|
-
|
|
189749
|
-
|
|
189750
|
-
|
|
190513
|
+
let timer;
|
|
190514
|
+
const load = async () => {
|
|
190515
|
+
try {
|
|
190516
|
+
const result = await loadMembers(speaker.speakerRef, controller.signal, version);
|
|
190517
|
+
if (controller.signal.aborted) return;
|
|
190518
|
+
setState({
|
|
190519
|
+
loading: false,
|
|
190520
|
+
result,
|
|
190521
|
+
error: ""
|
|
190522
|
+
});
|
|
190523
|
+
if (result.state === "stale" && result.version !== void 0 && result.version !== version) onVersionChanged();
|
|
190524
|
+
if (result.state !== "fresh") timer = setTimeout(() => {
|
|
190525
|
+
load();
|
|
190526
|
+
}, Math.max(5e3, result.retryAfterMs ?? 1e4));
|
|
190527
|
+
} catch (error) {
|
|
190528
|
+
if (!controller.signal.aborted) setState({
|
|
190529
|
+
loading: false,
|
|
190530
|
+
error: failureMessage(error)
|
|
190531
|
+
});
|
|
190532
|
+
}
|
|
190533
|
+
};
|
|
190534
|
+
load();
|
|
189751
190535
|
return () => {
|
|
190536
|
+
clearTimeout(timer);
|
|
189752
190537
|
controller.abort();
|
|
189753
190538
|
};
|
|
189754
190539
|
}, [
|
|
189755
190540
|
accountKey,
|
|
189756
190541
|
speaker.speakerRef,
|
|
189757
|
-
loadMembers
|
|
190542
|
+
loadMembers,
|
|
190543
|
+
version,
|
|
190544
|
+
onVersionChanged
|
|
189758
190545
|
]);
|
|
189759
190546
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
189760
190547
|
"aria-label": tr$1("已标记说话人详情"),
|
|
@@ -189780,23 +190567,27 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189780
190567
|
margin: "0 0 8px",
|
|
189781
190568
|
whiteSpace: "normal"
|
|
189782
190569
|
},
|
|
189783
|
-
children: tr$1("
|
|
190570
|
+
children: tr$1("展示全部历史已转写片段中可核实的关联。")
|
|
189784
190571
|
}),
|
|
189785
|
-
state.loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
190572
|
+
state.loading || state.result?.state === "building" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
189786
190573
|
role: "status",
|
|
189787
190574
|
style: styles$20.state,
|
|
189788
190575
|
children: tr$1("正在查找关联说话人…")
|
|
189789
|
-
}) : state.error !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
190576
|
+
}) : state.error !== "" || state.result?.state === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
189790
190577
|
role: "alert",
|
|
189791
190578
|
style: styles$20.error,
|
|
189792
|
-
children: state.error
|
|
190579
|
+
children: state.error || tr$1("出现统计暂不可用")
|
|
190580
|
+
}) : state.result?.state === "stale" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
190581
|
+
role: "status",
|
|
190582
|
+
style: styles$20.state,
|
|
190583
|
+
children: tr$1("出现统计更新中")
|
|
189793
190584
|
}) : state.result?.items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
189794
190585
|
role: "status",
|
|
189795
190586
|
style: styles$20.state,
|
|
189796
|
-
children: state.result.dayCount > 0 ? tr$1("
|
|
190587
|
+
children: state.result.dayCount > 0 ? tr$1("有发声,但未找到稳定的原始识别身份。") : tr$1("暂无可核实的关联说话人。")
|
|
189797
190588
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
189798
190589
|
style: styles$20.list,
|
|
189799
|
-
children: state.result?.items.map((member
|
|
190590
|
+
children: state.result?.items.map((member) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
189800
190591
|
style: styles$20.memberRow,
|
|
189801
190592
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UnmarkedSpeakerTokenAvatar, {
|
|
189802
190593
|
token: member.token,
|
|
@@ -189809,18 +190600,34 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189809
190600
|
children: tr$1("说话人 {v0}", { v0: member.token })
|
|
189810
190601
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
189811
190602
|
style: styles$20.meta,
|
|
189812
|
-
children: tr$1("
|
|
190603
|
+
children: tr$1("出现 {v0} 天", { v0: member.dayCount })
|
|
189813
190604
|
})]
|
|
189814
190605
|
})]
|
|
189815
|
-
},
|
|
190606
|
+
}, member.identityKey))
|
|
189816
190607
|
})
|
|
189817
190608
|
]
|
|
189818
190609
|
});
|
|
189819
190610
|
}
|
|
189820
|
-
function ArkmeRecognizedSpeakersSurface({ accountKey, onBack, loadMarked =
|
|
190611
|
+
function ArkmeRecognizedSpeakersSurface({ accountKey, onBack, loadMarked = readSpeakerOptions, loadPresence = readSpeakerPresence, loadMarkedMembers = defaultLoadMarkedMembers, loadUnmarked = readSpeakerPage, directory: providedDirectory }) {
|
|
189821
190612
|
useArkmeLocale();
|
|
190613
|
+
const directory = (0, react$1.useMemo)(() => providedDirectory ?? (loadMarked === readSpeakerOptions && loadUnmarked === readSpeakerPage && loadPresence === readSpeakerPresence ? recognizedSpeakerDirectory : new RecognizedSpeakerDirectory({
|
|
190614
|
+
marked: loadMarked,
|
|
190615
|
+
page: loadUnmarked,
|
|
190616
|
+
presence: loadPresence
|
|
190617
|
+
}, 0)), [
|
|
190618
|
+
providedDirectory,
|
|
190619
|
+
loadMarked,
|
|
190620
|
+
loadUnmarked,
|
|
190621
|
+
loadPresence
|
|
190622
|
+
]);
|
|
189822
190623
|
const [filter, setFilter] = (0, react$1.useState)("all");
|
|
189823
190624
|
const [query, setQuery] = (0, react$1.useState)("");
|
|
190625
|
+
const [orderPreference, setOrderPreference] = (0, react$1.useState)(() => ({
|
|
190626
|
+
accountKey,
|
|
190627
|
+
value: readRecognizedSpeakerOrder(accountKey)
|
|
190628
|
+
}));
|
|
190629
|
+
const order = orderPreference.accountKey === accountKey ? orderPreference.value : readRecognizedSpeakerOrder(accountKey);
|
|
190630
|
+
const [visibleCount, setVisibleCount] = (0, react$1.useState)(100);
|
|
189824
190631
|
const [refreshRevision, setRefreshRevision] = (0, react$1.useState)(0);
|
|
189825
190632
|
const [marked, setMarked] = (0, react$1.useState)({
|
|
189826
190633
|
loading: true,
|
|
@@ -189833,24 +190640,64 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189833
190640
|
});
|
|
189834
190641
|
const [unmarked, setUnmarked] = (0, react$1.useState)({
|
|
189835
190642
|
loading: true,
|
|
189836
|
-
|
|
190643
|
+
complete: false,
|
|
189837
190644
|
items: [],
|
|
189838
|
-
|
|
189839
|
-
hasMore: false,
|
|
190645
|
+
projectionState: void 0,
|
|
189840
190646
|
error: ""
|
|
189841
190647
|
});
|
|
189842
190648
|
const [selectedCandidate, setSelectedCandidate] = (0, react$1.useState)();
|
|
189843
190649
|
const [selectedMarked, setSelectedMarked] = (0, react$1.useState)();
|
|
189844
|
-
const
|
|
189845
|
-
const
|
|
190650
|
+
const lastAccountKey = (0, react$1.useRef)(accountKey);
|
|
190651
|
+
const readAccount = (0, react$1.useRef)();
|
|
189846
190652
|
const refresh = (0, react$1.useCallback)(() => {
|
|
189847
|
-
|
|
189848
|
-
moreBusy.current = false;
|
|
190653
|
+
directory.invalidate(accountKey);
|
|
189849
190654
|
setSelectedMarked(void 0);
|
|
189850
190655
|
setRefreshRevision((value) => value + 1);
|
|
189851
|
-
}, []);
|
|
190656
|
+
}, [directory, accountKey]);
|
|
190657
|
+
(0, react$1.useEffect)(() => {
|
|
190658
|
+
setVisibleCount(100);
|
|
190659
|
+
}, [
|
|
190660
|
+
accountKey,
|
|
190661
|
+
filter,
|
|
190662
|
+
query,
|
|
190663
|
+
order
|
|
190664
|
+
]);
|
|
189852
190665
|
(0, react$1.useEffect)(() => {
|
|
189853
190666
|
const controller = new AbortController();
|
|
190667
|
+
const retryTimers = [];
|
|
190668
|
+
const retry = (error, read) => {
|
|
190669
|
+
const delay = speakerRetryDelay(error);
|
|
190670
|
+
if (delay !== void 0) retryTimers.push(setTimeout(() => {
|
|
190671
|
+
if (!controller.signal.aborted) read();
|
|
190672
|
+
}, delay));
|
|
190673
|
+
};
|
|
190674
|
+
readAccount.current = void 0;
|
|
190675
|
+
if (lastAccountKey.current !== accountKey) {
|
|
190676
|
+
lastAccountKey.current = accountKey;
|
|
190677
|
+
setMarked({
|
|
190678
|
+
loading: true,
|
|
190679
|
+
items: [],
|
|
190680
|
+
error: ""
|
|
190681
|
+
});
|
|
190682
|
+
setPresence({
|
|
190683
|
+
loading: true,
|
|
190684
|
+
error: ""
|
|
190685
|
+
});
|
|
190686
|
+
setUnmarked({
|
|
190687
|
+
loading: true,
|
|
190688
|
+
complete: false,
|
|
190689
|
+
items: [],
|
|
190690
|
+
projectionState: void 0,
|
|
190691
|
+
error: ""
|
|
190692
|
+
});
|
|
190693
|
+
setOrderPreference({
|
|
190694
|
+
accountKey,
|
|
190695
|
+
value: readRecognizedSpeakerOrder(accountKey)
|
|
190696
|
+
});
|
|
190697
|
+
setQuery("");
|
|
190698
|
+
setSelectedMarked(void 0);
|
|
190699
|
+
setSelectedCandidate(void 0);
|
|
190700
|
+
}
|
|
189854
190701
|
setMarked((previous) => ({
|
|
189855
190702
|
...previous,
|
|
189856
190703
|
loading: true,
|
|
@@ -189864,73 +190711,103 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189864
190711
|
setUnmarked((previous) => ({
|
|
189865
190712
|
...previous,
|
|
189866
190713
|
loading: true,
|
|
189867
|
-
|
|
190714
|
+
complete: false,
|
|
189868
190715
|
error: ""
|
|
189869
190716
|
}));
|
|
189870
|
-
|
|
189871
|
-
|
|
189872
|
-
|
|
189873
|
-
|
|
189874
|
-
|
|
189875
|
-
});
|
|
189876
|
-
}).catch((error) => {
|
|
189877
|
-
if (!controller.signal.aborted) setMarked((previous) => ({
|
|
189878
|
-
...previous,
|
|
189879
|
-
loading: false,
|
|
189880
|
-
error: failureMessage(error)
|
|
189881
|
-
}));
|
|
190717
|
+
const cachedMarked = directory.peekMarked(accountKey);
|
|
190718
|
+
if (cachedMarked !== void 0) setMarked({
|
|
190719
|
+
loading: false,
|
|
190720
|
+
items: cachedMarked,
|
|
190721
|
+
error: ""
|
|
189882
190722
|
});
|
|
189883
|
-
|
|
189884
|
-
|
|
189885
|
-
|
|
189886
|
-
|
|
189887
|
-
|
|
190723
|
+
const readMarked = () => {
|
|
190724
|
+
directory.readMarked(accountKey, controller.signal).then((items) => {
|
|
190725
|
+
if (!controller.signal.aborted) setMarked({
|
|
190726
|
+
loading: false,
|
|
190727
|
+
items,
|
|
190728
|
+
error: ""
|
|
190729
|
+
});
|
|
190730
|
+
}).catch((error) => {
|
|
190731
|
+
if (!controller.signal.aborted) {
|
|
190732
|
+
setMarked((previous) => ({
|
|
190733
|
+
...previous,
|
|
190734
|
+
loading: false,
|
|
190735
|
+
error: failureMessage(error)
|
|
190736
|
+
}));
|
|
190737
|
+
retry(error, readMarked);
|
|
190738
|
+
}
|
|
189888
190739
|
});
|
|
189889
|
-
}
|
|
189890
|
-
|
|
189891
|
-
|
|
189892
|
-
|
|
189893
|
-
|
|
189894
|
-
|
|
190740
|
+
};
|
|
190741
|
+
readMarked();
|
|
190742
|
+
const cachedPresence = directory.peekPresence(accountKey);
|
|
190743
|
+
if (cachedPresence !== void 0) setPresence({
|
|
190744
|
+
loading: false,
|
|
190745
|
+
result: cachedPresence,
|
|
190746
|
+
error: ""
|
|
189895
190747
|
});
|
|
189896
|
-
|
|
189897
|
-
|
|
189898
|
-
|
|
189899
|
-
|
|
189900
|
-
|
|
189901
|
-
|
|
189902
|
-
|
|
189903
|
-
|
|
189904
|
-
|
|
189905
|
-
|
|
189906
|
-
|
|
190748
|
+
const readPresence = () => {
|
|
190749
|
+
directory.readPresence(accountKey, controller.signal).then((result) => {
|
|
190750
|
+
if (!controller.signal.aborted) setPresence({
|
|
190751
|
+
loading: false,
|
|
190752
|
+
result,
|
|
190753
|
+
error: ""
|
|
190754
|
+
});
|
|
190755
|
+
}).catch((error) => {
|
|
190756
|
+
if (!controller.signal.aborted) {
|
|
190757
|
+
setPresence((previous) => ({
|
|
190758
|
+
...previous,
|
|
190759
|
+
loading: false,
|
|
190760
|
+
error: failureMessage(error)
|
|
190761
|
+
}));
|
|
190762
|
+
retry(error, readPresence);
|
|
190763
|
+
}
|
|
189907
190764
|
});
|
|
189908
|
-
}
|
|
189909
|
-
|
|
189910
|
-
|
|
189911
|
-
|
|
189912
|
-
|
|
189913
|
-
|
|
189914
|
-
|
|
189915
|
-
|
|
190765
|
+
};
|
|
190766
|
+
readPresence();
|
|
190767
|
+
const readCandidates = () => {
|
|
190768
|
+
directory.readCandidates(accountKey, controller.signal, (snapshot) => {
|
|
190769
|
+
if (!controller.signal.aborted) {
|
|
190770
|
+
readAccount.current = accountKey;
|
|
190771
|
+
setUnmarked({
|
|
190772
|
+
...snapshot,
|
|
190773
|
+
loading: true,
|
|
190774
|
+
error: ""
|
|
190775
|
+
});
|
|
190776
|
+
}
|
|
190777
|
+
}).then((snapshot) => {
|
|
190778
|
+
if (!controller.signal.aborted) setUnmarked({
|
|
190779
|
+
...snapshot,
|
|
190780
|
+
loading: false,
|
|
190781
|
+
error: ""
|
|
190782
|
+
});
|
|
190783
|
+
}).catch((error) => {
|
|
190784
|
+
if (!controller.signal.aborted) {
|
|
190785
|
+
setUnmarked((previous) => ({
|
|
190786
|
+
...previous,
|
|
190787
|
+
loading: false,
|
|
190788
|
+
complete: false,
|
|
190789
|
+
error: failureMessage(error)
|
|
190790
|
+
}));
|
|
190791
|
+
retry(error, readCandidates);
|
|
190792
|
+
}
|
|
190793
|
+
});
|
|
190794
|
+
};
|
|
190795
|
+
readCandidates();
|
|
189916
190796
|
return () => {
|
|
189917
190797
|
controller.abort();
|
|
189918
|
-
|
|
189919
|
-
moreBusy.current = false;
|
|
190798
|
+
retryTimers.forEach(clearTimeout);
|
|
189920
190799
|
};
|
|
189921
190800
|
}, [
|
|
189922
190801
|
accountKey,
|
|
189923
190802
|
refreshRevision,
|
|
189924
|
-
|
|
189925
|
-
loadPresence,
|
|
189926
|
-
loadUnmarked
|
|
190803
|
+
directory
|
|
189927
190804
|
]);
|
|
189928
190805
|
(0, react$1.useEffect)(() => {
|
|
189929
190806
|
const state = presence.result?.state;
|
|
189930
|
-
if (presence.error !== "" || state !== "building" && state !== "stale") return;
|
|
190807
|
+
if (presence.loading || presence.error !== "" || state !== "building" && state !== "stale" && state !== "failed") return;
|
|
189931
190808
|
const controller = new AbortController();
|
|
189932
190809
|
const timer = setTimeout(() => {
|
|
189933
|
-
|
|
190810
|
+
directory.refreshPresence(accountKey, controller.signal).then((result) => {
|
|
189934
190811
|
if (!controller.signal.aborted) setPresence({
|
|
189935
190812
|
loading: false,
|
|
189936
190813
|
result,
|
|
@@ -189950,56 +190827,53 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
189950
190827
|
};
|
|
189951
190828
|
}, [
|
|
189952
190829
|
accountKey,
|
|
189953
|
-
|
|
190830
|
+
refreshRevision,
|
|
190831
|
+
directory,
|
|
190832
|
+
presence.loading,
|
|
189954
190833
|
presence.error,
|
|
189955
190834
|
presence.result
|
|
189956
190835
|
]);
|
|
189957
|
-
const
|
|
189958
|
-
|
|
189959
|
-
|
|
189960
|
-
|
|
189961
|
-
|
|
189962
|
-
|
|
189963
|
-
|
|
189964
|
-
|
|
190836
|
+
const refreshPresenceVersion = (0, react$1.useCallback)(() => {
|
|
190837
|
+
setPresence({
|
|
190838
|
+
loading: false,
|
|
190839
|
+
result: {
|
|
190840
|
+
state: "stale",
|
|
190841
|
+
scope: "all-history",
|
|
190842
|
+
items: [],
|
|
190843
|
+
retryAfterMs: 1e3
|
|
190844
|
+
},
|
|
189965
190845
|
error: ""
|
|
189966
|
-
}));
|
|
189967
|
-
loadUnmarked(unmarked.nextCursor, controller.signal).then((page) => {
|
|
189968
|
-
if (controller.signal.aborted) return;
|
|
189969
|
-
if (page.section !== "unmarked-speakers") throw new Error("未标记说话人列表响应无效");
|
|
189970
|
-
if (page.cursorStale === true) {
|
|
189971
|
-
refresh();
|
|
189972
|
-
return;
|
|
189973
|
-
}
|
|
189974
|
-
setUnmarked((previous) => ({
|
|
189975
|
-
...previous,
|
|
189976
|
-
loadingMore: false,
|
|
189977
|
-
items: [...new Map([...previous.items, ...page.items.filter((item) => item.kind === "unmarked-speaker")].map((item) => [item.candidateRef, item])).values()],
|
|
189978
|
-
nextCursor: page.nextCursor ?? "",
|
|
189979
|
-
hasMore: page.hasMore,
|
|
189980
|
-
projectionState: page.projectionState ?? previous.projectionState,
|
|
189981
|
-
error: ""
|
|
189982
|
-
}));
|
|
189983
|
-
}).catch((error) => {
|
|
189984
|
-
if (!controller.signal.aborted) setUnmarked((previous) => ({
|
|
189985
|
-
...previous,
|
|
189986
|
-
loadingMore: false,
|
|
189987
|
-
error: failureMessage(error)
|
|
189988
|
-
}));
|
|
189989
|
-
}).finally(() => {
|
|
189990
|
-
moreBusy.current = false;
|
|
189991
190846
|
});
|
|
190847
|
+
}, []);
|
|
190848
|
+
const rows = (0, react$1.useMemo)(() => identifiedSpeakerRows(marked.items, unmarked.items), [marked.items, unmarked.items]);
|
|
190849
|
+
const hasSelf = rows.some((row) => row.kind === "marked" && row.isCurrentUser);
|
|
190850
|
+
(0, react$1.useEffect)(() => {
|
|
190851
|
+
if (readAccount.current !== accountKey || marked.loading || marked.error !== "") return;
|
|
190852
|
+
if (rows.length > 0 || !unmarked.loading && unmarked.complete) recognizedSpeakerTracker.acknowledge(accountKey);
|
|
190853
|
+
if (!unmarked.loading && unmarked.complete && unmarked.error === "") recognizedSpeakerTracker.observe(accountKey, marked.items, unmarked.items, true);
|
|
189992
190854
|
}, [
|
|
189993
|
-
|
|
189994
|
-
|
|
189995
|
-
|
|
190855
|
+
accountKey,
|
|
190856
|
+
marked.loading,
|
|
190857
|
+
marked.error,
|
|
190858
|
+
marked.items,
|
|
189996
190859
|
unmarked.loading,
|
|
189997
|
-
unmarked.
|
|
190860
|
+
unmarked.complete,
|
|
190861
|
+
unmarked.error,
|
|
190862
|
+
unmarked.items,
|
|
190863
|
+
rows.length
|
|
189998
190864
|
]);
|
|
189999
|
-
const
|
|
190000
|
-
const presenceByOption = (0, react$1.useMemo)(() => new Map(presence.result?.items.map((item) => [item.optionKey, item]) ?? []), [presence.result]);
|
|
190865
|
+
const presenceByOption = (0, react$1.useMemo)(() => new Map(presence.error === "" && presence.result?.state === "fresh" ? presence.result.items.map((item) => [item.optionKey, item]) : []), [presence.result, presence.error]);
|
|
190001
190866
|
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
190002
|
-
const
|
|
190867
|
+
const orderValue = (row) => {
|
|
190868
|
+
const stat = row.kind === "marked" ? presenceByOption.get(row.optionKey) : unmarked.projectionState === void 0 || unmarked.projectionState === "fresh" ? row : void 0;
|
|
190869
|
+
return {
|
|
190870
|
+
key: `${row.kind}:${row.key}`,
|
|
190871
|
+
name: row.name,
|
|
190872
|
+
dayCount: stat?.dayCount,
|
|
190873
|
+
lastSeenAt: stat?.lastSeenAt
|
|
190874
|
+
};
|
|
190875
|
+
};
|
|
190876
|
+
const visible = rows.filter((row) => (filter === "all" || row.kind === filter) && (normalizedQuery === "" || row.name.toLocaleLowerCase().includes(normalizedQuery) || row.kind === "unmarked" && row.subtitle.toLocaleLowerCase().includes(normalizedQuery))).sort((left, right) => Number(right.kind === "marked" && right.isCurrentUser) - Number(left.kind === "marked" && left.isCurrentUser) || compareRecognizedSpeakers(orderValue(left), orderValue(right), order));
|
|
190003
190877
|
const loading = marked.loading || unmarked.loading;
|
|
190004
190878
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190005
190879
|
style: styles$20.root,
|
|
@@ -190047,33 +190921,57 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
190047
190921
|
}),
|
|
190048
190922
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190049
190923
|
style: styles$20.filters,
|
|
190050
|
-
children: [
|
|
190051
|
-
[
|
|
190052
|
-
|
|
190053
|
-
|
|
190054
|
-
|
|
190055
|
-
|
|
190056
|
-
|
|
190057
|
-
|
|
190058
|
-
|
|
190059
|
-
|
|
190060
|
-
|
|
190061
|
-
|
|
190062
|
-
|
|
190063
|
-
|
|
190064
|
-
|
|
190065
|
-
|
|
190066
|
-
|
|
190067
|
-
|
|
190068
|
-
|
|
190069
|
-
|
|
190070
|
-
|
|
190071
|
-
|
|
190072
|
-
|
|
190073
|
-
|
|
190074
|
-
|
|
190075
|
-
|
|
190924
|
+
children: [
|
|
190925
|
+
[
|
|
190926
|
+
["all", "全部"],
|
|
190927
|
+
["marked", "已标记"],
|
|
190928
|
+
["unmarked", "未标记"]
|
|
190929
|
+
].map(([kind, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
190930
|
+
type: "button",
|
|
190931
|
+
"aria-pressed": filter === kind,
|
|
190932
|
+
style: {
|
|
190933
|
+
...styles$20.filter,
|
|
190934
|
+
...filter === kind ? styles$20.selectedFilter : {}
|
|
190935
|
+
},
|
|
190936
|
+
onClick: () => {
|
|
190937
|
+
setFilter(kind);
|
|
190938
|
+
setSelectedCandidate(void 0);
|
|
190939
|
+
setSelectedMarked(void 0);
|
|
190940
|
+
},
|
|
190941
|
+
children: tr$1(label)
|
|
190942
|
+
}, kind)),
|
|
190943
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
190944
|
+
"aria-label": tr$1("搜索说话人"),
|
|
190945
|
+
placeholder: tr$1("搜索说话人"),
|
|
190946
|
+
value: query,
|
|
190947
|
+
onChange: (event) => {
|
|
190948
|
+
setQuery(event.target.value);
|
|
190949
|
+
},
|
|
190950
|
+
style: styles$20.search
|
|
190951
|
+
}),
|
|
190952
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
190953
|
+
"aria-label": tr$1("说话人排序"),
|
|
190954
|
+
value: order,
|
|
190955
|
+
onChange: (event) => {
|
|
190956
|
+
const next = event.target.value === "recent" ? "recent" : "frequent";
|
|
190957
|
+
setOrderPreference({
|
|
190958
|
+
accountKey,
|
|
190959
|
+
value: next
|
|
190960
|
+
});
|
|
190961
|
+
writeRecognizedSpeakerOrder(accountKey, next);
|
|
190962
|
+
},
|
|
190963
|
+
style: styles$20.sort,
|
|
190964
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
190965
|
+
value: "frequent",
|
|
190966
|
+
children: tr$1("经常出现")
|
|
190967
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
190968
|
+
value: "recent",
|
|
190969
|
+
children: tr$1("最近出现")
|
|
190970
|
+
})]
|
|
190971
|
+
})
|
|
190972
|
+
]
|
|
190076
190973
|
}),
|
|
190974
|
+
!marked.loading && marked.error === "" && !hasSelf && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SpeakerSelfGuide, { onOpenRecordings: onBack }, accountKey),
|
|
190077
190975
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190078
190976
|
className: "arkme-recognized-speakers-grid",
|
|
190079
190977
|
"data-detail-open": selectedCandidate === void 0 && selectedMarked === void 0 ? "false" : "true",
|
|
@@ -190081,9 +190979,15 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
190081
190979
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190082
190980
|
className: "arkme-recognized-speakers-list",
|
|
190083
190981
|
children: [
|
|
190084
|
-
|
|
190982
|
+
filter !== "marked" && unmarked.loading && !unmarked.complete && rows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
190983
|
+
role: "status",
|
|
190984
|
+
style: styles$20.note,
|
|
190985
|
+
children: tr$1("正在补齐说话人列表,排序仍在更新…")
|
|
190986
|
+
}),
|
|
190987
|
+
filter !== "marked" && !unmarked.loading && !unmarked.complete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
190988
|
+
role: "status",
|
|
190085
190989
|
style: styles$20.note,
|
|
190086
|
-
children: tr$1("
|
|
190990
|
+
children: tr$1("列表尚未完整,当前仅对已加载的说话人排序和搜索。")
|
|
190087
190991
|
}),
|
|
190088
190992
|
marked.error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
190089
190993
|
role: "alert",
|
|
@@ -190128,7 +191032,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
190128
191032
|
children: loading ? tr$1("正在更新说话人…") : rows.length === 0 && marked.error === "" && unmarked.error === "" && (unmarked.projectionState === void 0 || unmarked.projectionState === "fresh") ? tr$1("暂无已识别说话人") : tr$1("暂无可显示的说话人")
|
|
190129
191033
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
190130
191034
|
style: styles$20.list,
|
|
190131
|
-
children: visible.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: row.kind === "unmarked" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
191035
|
+
children: visible.slice(0, visibleCount).map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: row.kind === "unmarked" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
190132
191036
|
type: "button",
|
|
190133
191037
|
className: "arkme-recognized-speakers-row",
|
|
190134
191038
|
"aria-current": selectedCandidate === row.candidateRef ? "true" : void 0,
|
|
@@ -190196,22 +191100,16 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
190196
191100
|
]
|
|
190197
191101
|
}) }, `${row.kind}:${row.key}`))
|
|
190198
191102
|
}),
|
|
190199
|
-
|
|
191103
|
+
visible.length > visibleCount && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
190200
191104
|
type: "button",
|
|
190201
191105
|
style: {
|
|
190202
191106
|
...styles$20.button,
|
|
190203
191107
|
marginTop: 14
|
|
190204
191108
|
},
|
|
190205
|
-
|
|
190206
|
-
|
|
190207
|
-
children: unmarked.loadingMore ? tr$1("正在加载…") : tr$1("加载更多未标记说话人")
|
|
190208
|
-
}),
|
|
190209
|
-
unmarked.hasMore && query.trim() !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
190210
|
-
style: {
|
|
190211
|
-
...styles$20.meta,
|
|
190212
|
-
marginTop: 10
|
|
191109
|
+
onClick: () => {
|
|
191110
|
+
setVisibleCount((count) => count + 100);
|
|
190213
191111
|
},
|
|
190214
|
-
children: tr$1("
|
|
191112
|
+
children: tr$1("显示更多说话人")
|
|
190215
191113
|
})
|
|
190216
191114
|
]
|
|
190217
191115
|
}),
|
|
@@ -190247,7 +191145,9 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
190247
191145
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkedSpeakerDetail, {
|
|
190248
191146
|
accountKey,
|
|
190249
191147
|
speaker: selectedMarked,
|
|
190250
|
-
loadMembers: loadMarkedMembers
|
|
191148
|
+
loadMembers: loadMarkedMembers,
|
|
191149
|
+
version: presence.result?.version,
|
|
191150
|
+
onVersionChanged: refreshPresenceVersion
|
|
190251
191151
|
}, `${accountKey}:${selectedMarked.speakerRef}`)]
|
|
190252
191152
|
})
|
|
190253
191153
|
]
|
|
@@ -210658,7 +211558,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
210658
211558
|
const c$3 = e$20;
|
|
210659
211559
|
//#endregion
|
|
210660
211560
|
//#region package.json
|
|
210661
|
-
var version = "0.1.
|
|
211561
|
+
var version = "0.1.84";
|
|
210662
211562
|
//#endregion
|
|
210663
211563
|
//#region src/client/arkme-membership.ts
|
|
210664
211564
|
function membershipLabel(state) {
|
|
@@ -212051,6 +212951,9 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
212051
212951
|
}
|
|
212052
212952
|
//#endregion
|
|
212053
212953
|
//#region src/client/ArkmeAccountUsage.tsx
|
|
212954
|
+
function formatWholePoints(value) {
|
|
212955
|
+
return (pointsUnits(value) / 10000000n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
212956
|
+
}
|
|
212054
212957
|
function useUsage(operation, scope, revision) {
|
|
212055
212958
|
const [result, setResult] = (0, react$1.useState)();
|
|
212056
212959
|
(0, react$1.useEffect)(() => {
|
|
@@ -212200,7 +213103,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
212200
213103
|
children: tr$1("AI 额度")
|
|
212201
213104
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
212202
213105
|
className: "arkme-usage-summary-total",
|
|
212203
|
-
children: points.status === "ready" ? `${
|
|
213106
|
+
children: points.status === "ready" ? `${formatWholePoints(points.value.availablePoints)} ${tr$1("积分")}` : status(points)
|
|
212204
213107
|
})]
|
|
212205
213108
|
}),
|
|
212206
213109
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSummaryRow, {
|
|
@@ -212295,14 +213198,14 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
212295
213198
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
212296
213199
|
tr$1("可用"),
|
|
212297
213200
|
" ",
|
|
212298
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children:
|
|
213201
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatWholePoints(points.value.availablePoints) }),
|
|
212299
213202
|
" ",
|
|
212300
213203
|
tr$1("积分")
|
|
212301
213204
|
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
212302
213205
|
className: "arkme-usage-points-sources",
|
|
212303
213206
|
children: tr$1("赠送 {v0} · 充值 {v1}", {
|
|
212304
|
-
v0:
|
|
212305
|
-
v1:
|
|
213207
|
+
v0: formatWholePoints(points.value.grantedPoints),
|
|
213208
|
+
v1: formatWholePoints(points.value.purchasedPoints)
|
|
212306
213209
|
})
|
|
212307
213210
|
})]
|
|
212308
213211
|
}), points.value.grants.some((grant) => grant.expiresAt > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
|
|
@@ -234358,6 +235261,42 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
234358
235261
|
} : detailRow;
|
|
234359
235262
|
const detailTopicPresentation = detailItem === void 0 ? void 0 : arkmeTimelineSelfTopicPresentation(detailItem, source, selfSources);
|
|
234360
235263
|
const detailTopicPath = detailItem === void 0 ? void 0 : detailTopicPresentation?.displayLabel ?? detailItem.selfTopic?.title ?? (source?.kind === "topic" ? source.displayName : void 0);
|
|
235264
|
+
const detailConversationBadge = source !== void 0 && (source.kind === "private_chat" || source.kind === "group_chat") ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
235265
|
+
"data-arkme-feedback": "neutral",
|
|
235266
|
+
"data-arkme-detail-conversation-source": true,
|
|
235267
|
+
type: "button",
|
|
235268
|
+
style: {
|
|
235269
|
+
...arkmeDetailSourceBadgeStyle,
|
|
235270
|
+
cursor: "pointer"
|
|
235271
|
+
},
|
|
235272
|
+
"aria-label": tr$1("来源:{v0}", { v0: source.displayName }),
|
|
235273
|
+
onClick: (event) => {
|
|
235274
|
+
event.stopPropagation();
|
|
235275
|
+
setDrawer(void 0);
|
|
235276
|
+
setDetailBackStack([]);
|
|
235277
|
+
pendingExtensionParentDetailRef.current = void 0;
|
|
235278
|
+
},
|
|
235279
|
+
children: [
|
|
235280
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeDirectorySourceAvatar, {
|
|
235281
|
+
source,
|
|
235282
|
+
size: 16
|
|
235283
|
+
}),
|
|
235284
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
235285
|
+
style: {
|
|
235286
|
+
minWidth: 0,
|
|
235287
|
+
overflow: "hidden",
|
|
235288
|
+
textOverflow: "ellipsis",
|
|
235289
|
+
whiteSpace: "nowrap"
|
|
235290
|
+
},
|
|
235291
|
+
children: source.displayName
|
|
235292
|
+
}),
|
|
235293
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(s$21, {
|
|
235294
|
+
size: 12,
|
|
235295
|
+
"aria-hidden": true,
|
|
235296
|
+
style: { flex: "none" }
|
|
235297
|
+
})
|
|
235298
|
+
]
|
|
235299
|
+
}) : void 0;
|
|
234361
235300
|
const openExtensionParentDetail = (parent) => {
|
|
234362
235301
|
if (source === void 0 || detailItem === void 0 || parent.itemUid === detailItem.itemUid) return;
|
|
234363
235302
|
const from = {
|
|
@@ -239291,6 +240230,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
239291
240230
|
}),
|
|
239292
240231
|
detailItem.forwardRecords !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ForwardRecordsDetail, {
|
|
239293
240232
|
item: detailItem,
|
|
240233
|
+
sourceBadge: detailConversationBadge,
|
|
239294
240234
|
onPrivateChatOpened: activateSource,
|
|
239295
240235
|
onClose: () => {
|
|
239296
240236
|
setDrawer(void 0);
|
|
@@ -239314,6 +240254,7 @@ registerProcessor('arkme-pcm-journal', ArkmePcmJournal);
|
|
|
239314
240254
|
}, `${authenticatedAccountKey}:${conversationOverlayKey}:${detailItem.itemUid}`),
|
|
239315
240255
|
activeConversation && drawer === "detail" && detailItem !== void 0 && detailItem.callRecord === void 0 && detailItem.forwardRecords === void 0 && detailSharedRecording === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeTimelineDetailDrawer, {
|
|
239316
240256
|
item: detailItem,
|
|
240257
|
+
sourceBadge: detailConversationBadge,
|
|
239317
240258
|
sourceRef: source?.sourceRef,
|
|
239318
240259
|
sourceIdentityKey: conversationKey,
|
|
239319
240260
|
canExtend: !archiveReadOnly,
|