@clowder-ai/companion 0.1.0-alpha.14 → 0.1.0-alpha.19
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/manifest.json +2 -2
- package/package.json +3 -3
- package/plugin.yaml +2 -2
- package/renderer/client.mjs +1 -0
- package/renderer/decision-view.mjs +107 -11
- package/renderer/index.html +2 -1
- package/renderer/style.css +8 -2
- package/renderer/surface.mjs +46 -14
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"pluginId": "official.companion",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.19",
|
|
4
4
|
"contractVersion": "0.1.0",
|
|
5
5
|
"name": "猫猫球",
|
|
6
6
|
"icon": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"bridgeVersion": "1.3.0",
|
|
41
41
|
"surface": {
|
|
42
42
|
"entrypoint": "renderer/index.html",
|
|
43
|
-
"integrity": "sha256-
|
|
43
|
+
"integrity": "sha256-jaXXDHzwGVDNnFoOhrj5nvqAXMlf02Jw8CeC7Xay538="
|
|
44
44
|
},
|
|
45
45
|
"presentation": {
|
|
46
46
|
"width": 300,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clowder-ai/companion",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.19",
|
|
4
4
|
"description": "The desktop voice body for your Clowder companion",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"prepack": "pnpm build"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@clowder-ai/plugin-contract": "0.1.0-beta.
|
|
31
|
-
"@clowder-ai/plugin-sdk": "0.1.0-beta.
|
|
30
|
+
"@clowder-ai/plugin-contract": "0.1.0-beta.24",
|
|
31
|
+
"@clowder-ai/plugin-sdk": "0.1.0-beta.20",
|
|
32
32
|
"playwright": "1.61.1"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
package/plugin.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"pluginId": "official.companion",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.19",
|
|
4
4
|
"contractVersion": "0.1.0",
|
|
5
5
|
"name": "猫猫球",
|
|
6
6
|
"icon": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"bridgeVersion": "1.3.0",
|
|
41
41
|
"surface": {
|
|
42
42
|
"entrypoint": "renderer/index.html",
|
|
43
|
-
"integrity": "sha256-
|
|
43
|
+
"integrity": "sha256-jaXXDHzwGVDNnFoOhrj5nvqAXMlf02Jw8CeC7Xay538="
|
|
44
44
|
},
|
|
45
45
|
"presentation": {
|
|
46
46
|
"width": 300,
|
package/renderer/client.mjs
CHANGED
|
@@ -37,6 +37,7 @@ export function createCompanionClient(bridge) {
|
|
|
37
37
|
screenClose: () => invoke({ kind: 'screen.close' }, 'ok'),
|
|
38
38
|
openConversation: () => invoke({ kind: 'conversation.open' }, 'navigation'),
|
|
39
39
|
readDecisions: (offset = 0, limit = 20) => invoke({ kind: 'decisions.read', offset, limit }, 'decisions'),
|
|
40
|
+
openDecision: (variantRef, target) => invoke({ kind: 'decision.open', variantRef, target }, 'navigation'),
|
|
40
41
|
inspectF221: (proposalId) => invoke({ kind: 'f221.inspect', proposalId }, 'decision-trial'),
|
|
41
42
|
resize: (expanded) => invoke({ kind: 'view.resize', expanded }, 'ok'),
|
|
42
43
|
layout: (panel, width, height) => invoke({ kind: 'view.layout', panel, width, height }, 'layout'),
|
|
@@ -1,28 +1,124 @@
|
|
|
1
|
-
|
|
1
|
+
function unified(page) {
|
|
2
|
+
return page?.version === 1 && Array.isArray(page.items);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function knownRows(page) {
|
|
6
|
+
if (unified(page)) return page.items.length;
|
|
7
|
+
return (page?.approvals?.length ?? 0) + (page?.otherNeedsMe?.length ?? 0);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function authenticationRequired(page) {
|
|
11
|
+
if (!unified(page)) return false;
|
|
12
|
+
const sources = Object.values(page.sources ?? {});
|
|
13
|
+
return sources.length > 0 && sources.every(source => source.status === 'unauthenticated');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Exact totals exist only on a complete, consistent unified read. Legacy pages never invent a sum. */
|
|
2
17
|
export function decisionBadge(page) {
|
|
3
|
-
if (!page
|
|
18
|
+
if (!page) return { visible: true, label: '?', title: '待办暂不可读', state: 'unavailable' };
|
|
19
|
+
if (unified(page)) {
|
|
20
|
+
if (page.status === 'partial') {
|
|
21
|
+
return { visible: true, label: page.items.length > 0 ? '•' : '!', title: '仅部分读取', state: 'partial' };
|
|
22
|
+
}
|
|
23
|
+
if (page.status === 'unavailable') {
|
|
24
|
+
return authenticationRequired(page)
|
|
25
|
+
? { visible: true, label: '!', title: '需要登录', state: 'authentication' }
|
|
26
|
+
: { visible: true, label: '!', title: '待办暂不可读', state: 'unavailable' };
|
|
27
|
+
}
|
|
28
|
+
if (Number.isInteger(page.totalCount)) {
|
|
29
|
+
return page.totalCount === 0
|
|
30
|
+
? { visible: false, label: '0', title: '暂无待办', state: 'empty' }
|
|
31
|
+
: { visible: true, label: String(page.totalCount), title: `待办 · ${page.totalCount} 件`, state: 'available' };
|
|
32
|
+
}
|
|
33
|
+
return { visible: true, label: page.items.length > 0 ? '•' : '!', title: '数量未确认', state: 'uncertain' };
|
|
34
|
+
}
|
|
35
|
+
if (page.status !== 'available')
|
|
4
36
|
return { visible: true, label: '?', title: '待办暂不可读', state: 'unavailable' };
|
|
5
|
-
const hasKnownRows = (page
|
|
37
|
+
const hasKnownRows = knownRows(page) > 0
|
|
6
38
|
|| page.approvalCount > 0 || page.needsMeCount > 0 || page.otherNeedsMeCount > 0;
|
|
7
39
|
if (hasKnownRows) return { visible: true, label: '有待办', title: '有待办', state: 'available' };
|
|
8
40
|
return { visible: false, label: '0', title: '现在没有待办', state: 'empty' };
|
|
9
41
|
}
|
|
10
42
|
|
|
11
|
-
|
|
12
|
-
if (!page || page.status !== 'available') return [];
|
|
43
|
+
function approvalMeta(approval) {
|
|
13
44
|
const state = {
|
|
14
45
|
open: '待你决定', accepted: '已接纳 · 待核结果', rejected: '已拒绝',
|
|
15
46
|
closed_without_decision: '已关闭',
|
|
16
47
|
};
|
|
48
|
+
const materialization = approval.materializationState === 'outcome_unknown' ? '结果未知'
|
|
49
|
+
: approval.materializationState === 'failed' ? '执行失败'
|
|
50
|
+
: approval.linkedNeedsMe ? '已关联待办' : '原处卡片';
|
|
51
|
+
return `审批 · ${state[approval.resolution] ?? '状态待核'} · ${materialization}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function navigation(item) {
|
|
55
|
+
const priorities = item.kind === 'approval'
|
|
56
|
+
? [['approval_card', '打开审批'], ['action', '打开处理入口'], ['origin', '打开原处']]
|
|
57
|
+
: [['action', '打开处理入口'], ['origin', '打开原处'], ['approval_card', '打开审批']];
|
|
58
|
+
const selected = priorities.find(([target]) => item.navigation.targets.includes(target));
|
|
59
|
+
return selected ? { variantRef: item.variantRef, target: selected[0], label: selected[1] } : undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function decisionRows(page) {
|
|
63
|
+
if (unified(page)) {
|
|
64
|
+
if (page.status === 'unavailable') return [];
|
|
65
|
+
return page.items.map(item => ({
|
|
66
|
+
title: item.summary || '待处理事项',
|
|
67
|
+
meta: item.kind === 'approval' ? approvalMeta(item.approval)
|
|
68
|
+
: item.kind === 'judgment' ? '等你判断 · 请在原处处理' : '需要修复 · 请在原处处理',
|
|
69
|
+
variantRef: item.variantRef,
|
|
70
|
+
navigation: navigation(item),
|
|
71
|
+
previewable: false,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
if (!page || page.status !== 'available') return [];
|
|
17
75
|
return [
|
|
18
|
-
...page.approvals.map(item => ({
|
|
76
|
+
...(page.approvals ?? []).map(item => ({
|
|
19
77
|
title: item.summary || '待决策事项',
|
|
20
|
-
meta:
|
|
78
|
+
meta: approvalMeta(item),
|
|
21
79
|
proposalId: item.proposalId,
|
|
22
|
-
previewable: item.sourceFeatureId === 'F221'
|
|
23
|
-
/^[A-Za-z0-9_-]{1,200}$/.test(item.proposalId)
|
|
24
|
-
item.resolution === 'open' && item.materializationState === 'not_started',
|
|
80
|
+
previewable: item.sourceFeatureId === 'F221'
|
|
81
|
+
&& /^[A-Za-z0-9_-]{1,200}$/.test(item.proposalId)
|
|
82
|
+
&& item.resolution === 'open' && item.materializationState === 'not_started',
|
|
25
83
|
})),
|
|
26
|
-
...page.otherNeedsMe.map(item => ({ title: item.summary || '待处理事项', meta: '其他待处理 · 请向猫猫询问详情' })),
|
|
84
|
+
...(page.otherNeedsMe ?? []).map(item => ({ title: item.summary || '待处理事项', meta: '其他待处理 · 请向猫猫询问详情' })),
|
|
27
85
|
];
|
|
28
86
|
}
|
|
87
|
+
|
|
88
|
+
export function decisionPresentation(page) {
|
|
89
|
+
const badge = decisionBadge(page);
|
|
90
|
+
if (!page) return { badge, message: '待办暂不可读 · 请稍后刷新', reloadLabel: '重试', pending: null, hasMore: false, renderRows: false };
|
|
91
|
+
if (unified(page)) {
|
|
92
|
+
const pending = Number.isInteger(page.totalCount) ? page.totalCount > 0 : page.items.length > 0 ? true : null;
|
|
93
|
+
if (page.status === 'partial') return {
|
|
94
|
+
badge, message: '仅部分读取 · 其余待办未能读取', reloadLabel: '重试', pending,
|
|
95
|
+
hasMore: page.page.hasMore, renderRows: true,
|
|
96
|
+
};
|
|
97
|
+
if (page.status === 'unavailable') return {
|
|
98
|
+
badge, message: authenticationRequired(page) ? '待办需要登录 · 请登录后重试' : '待办暂不可读 · 请稍后重试',
|
|
99
|
+
reloadLabel: '重试', pending: null, hasMore: false, renderRows: false,
|
|
100
|
+
};
|
|
101
|
+
if (page.totalCount === 0) return {
|
|
102
|
+
badge, message: '暂无待办', reloadLabel: '刷新', pending: false,
|
|
103
|
+
hasMore: page.page.hasMore, renderRows: true,
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
badge,
|
|
107
|
+
message: Number.isInteger(page.totalCount)
|
|
108
|
+
? `已读取 ${page.totalCount} 件待办`
|
|
109
|
+
: '已显示读取到的待办 · 数量未确认',
|
|
110
|
+
reloadLabel: '刷新', pending,
|
|
111
|
+
hasMore: page.page.hasMore, renderRows: true,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (page.status !== 'available') return {
|
|
115
|
+
badge, message: '待办暂不可读 · 请稍后刷新', reloadLabel: '重试', pending: null, hasMore: false, renderRows: false,
|
|
116
|
+
};
|
|
117
|
+
return {
|
|
118
|
+
badge,
|
|
119
|
+
message: badge.state === 'empty' ? '现在没有待你处理的事项' : '已显示读取到的待办 · 暂无总数',
|
|
120
|
+
reloadLabel: '刷新', pending: badge.state === 'empty' ? false : true,
|
|
121
|
+
hasMore: page.page.hasMoreApprovals || page.page.hasMoreNeedsMe,
|
|
122
|
+
renderRows: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
package/renderer/index.html
CHANGED
|
@@ -103,9 +103,10 @@
|
|
|
103
103
|
</section>
|
|
104
104
|
<section id="transcript" class="floating call-transcript" data-expanded="false" aria-label="这次通话的字幕" hidden>
|
|
105
105
|
<div id="transcript-call-context" class="call-context transcript-call-context">
|
|
106
|
-
<span class="status-dot" aria-hidden="true"></span><strong id="transcript-call-state"></strong><span id="transcript-call-mic-state"></span
|
|
106
|
+
<span class="status-dot" aria-hidden="true"></span><strong id="transcript-call-state"></strong><span id="transcript-call-mic-state"></span>
|
|
107
107
|
<small id="transcript-call-work" hidden></small>
|
|
108
108
|
<div class="call-context-actions">
|
|
109
|
+
<button id="transcript-return" class="transcript-return" type="button" data-action="transcript-return"><span aria-hidden="true">‹</span><span>返回通话</span></button>
|
|
109
110
|
<button id="transcript-mic" data-action="mute" aria-label="静音"><svg class="icon" aria-hidden="true"><use id="transcript-mic-icon" href="#i-mic"/></svg></button>
|
|
110
111
|
<button id="transcript-expand" data-action="transcript-expand"><svg class="icon" aria-hidden="true"><use href="#i-expand"/></svg><span id="transcript-expand-label">展开</span></button>
|
|
111
112
|
<button data-action="stop" class="destructive compact">挂断</button>
|
package/renderer/style.css
CHANGED
|
@@ -139,8 +139,14 @@ button:disabled { opacity: .45; cursor: default; }
|
|
|
139
139
|
#chat small { color: var(--cafe-text-muted); font-size: 10px; padding: 0 14px 10px; }
|
|
140
140
|
.call-transcript { width: 420px; height: 210px; display: flex; flex-direction: column; overflow: hidden; }
|
|
141
141
|
.call-transcript[data-expanded="true"] { height: 500px; }
|
|
142
|
-
.transcript-call-context { flex: none; grid-template-columns: auto
|
|
143
|
-
.
|
|
142
|
+
.transcript-call-context { flex: none; grid-template-columns: auto minmax(0, 1fr) auto; gap: 5px; padding: 7px 8px; }
|
|
143
|
+
.transcript-call-context #transcript-call-state { min-width: 0; overflow-wrap: anywhere; }
|
|
144
|
+
.transcript-call-context #transcript-call-mic-state { grid-column: 2 / 4; grid-row: 2; min-width: 0; white-space: normal; overflow-wrap: anywhere; font-size: 11px; }
|
|
145
|
+
.transcript-call-context .call-context-actions { grid-column: 3; grid-row: 1; gap: 2px; }
|
|
146
|
+
.transcript-call-context .call-context-actions button { padding: 6px; }
|
|
147
|
+
.transcript-call-context .destructive.compact { min-width: 64px; padding-inline: 9px; }
|
|
148
|
+
.transcript-return { display: inline-flex; align-items: center; gap: 2px; border: 1px solid var(--desktop-line) !important; background: var(--desktop-work) !important; color: var(--desktop-body); padding: 3px 6px !important; font-size: 11px; font-weight: 500 !important; white-space: nowrap; }
|
|
149
|
+
.transcript-return:hover:not(:disabled) { background: var(--desktop-rail) !important; }
|
|
144
150
|
#call-transcript-log { min-height: 0; flex: 1 1 auto; overflow-y: auto; padding: 8px 12px 5px; }
|
|
145
151
|
.call-transcript-row { margin: 0 0 7px; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.45; }
|
|
146
152
|
.call-transcript-row.voice.user { color: var(--desktop-muted); font-size: 13px; font-weight: 400; }
|
package/renderer/surface.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { PetMotion } from './pet-motion.mjs';
|
|
|
11
11
|
import { LivingBody } from './living-body.mjs';
|
|
12
12
|
import { detectDockedEdge } from './living-edge.mjs';
|
|
13
13
|
import { bindPetControls } from './pet-controls.mjs';
|
|
14
|
-
import { decisionBadge, decisionRows } from './decision-view.mjs';
|
|
14
|
+
import { decisionBadge, decisionPresentation, decisionRows } from './decision-view.mjs';
|
|
15
15
|
import { nativeWorkLabel, normalizeNativeWork } from './native-work-motion.mjs';
|
|
16
16
|
import { NativeWindowTravel } from './native-window-travel.mjs';
|
|
17
17
|
import { currentCompanionIdentity } from './companion-identity.mjs';
|
|
@@ -44,6 +44,10 @@ let didMove = false, decisionLoading = false, decisionOffset = 0, threadTitle, s
|
|
|
44
44
|
const ambientPanel = active => active ? 'actions' : 'none';
|
|
45
45
|
const setTexts = (ids, text) => { for (const id of ids) $(id).textContent = text; };
|
|
46
46
|
const setHidden = (ids, hidden) => { for (const id of ids) $(id).hidden = hidden; };
|
|
47
|
+
const decisionReadBasis = page => page?.version === 1
|
|
48
|
+
? [page.status, page.totalCount ?? 'unknown', ...['approvals', 'needsMe']
|
|
49
|
+
.flatMap(key => [page.sources?.[key]?.status, page.sources?.[key]?.coverage])].join('|')
|
|
50
|
+
: page ? 'legacy' : null;
|
|
47
51
|
if (!window.clowderCompanion) {
|
|
48
52
|
$('actions').hidden = false; $('status').hidden = false;
|
|
49
53
|
status('请从 Clowder 的聊聊入口打开猫猫球');
|
|
@@ -77,6 +81,7 @@ if (!window.clowderCompanion) {
|
|
|
77
81
|
if (kind === 'share') toggleScreen();
|
|
78
82
|
if (kind === 'documents') void conversation.documents(conversation.identity?.documentsAllowed === false);
|
|
79
83
|
if (kind === 'hide') void client.hide().catch(error => status(explainError(error)));
|
|
84
|
+
if (kind === 'transcript-return') void controls.show('actions');
|
|
80
85
|
if (kind === 'transcript-expand') {
|
|
81
86
|
const expanded = $('transcript').dataset.expanded !== 'true';
|
|
82
87
|
$('transcript').dataset.expanded = String(expanded);
|
|
@@ -278,20 +283,39 @@ if (!window.clowderCompanion) {
|
|
|
278
283
|
decisionLoading = true;
|
|
279
284
|
if (!more && controls.panel === 'decisions') $('decision-status').textContent = '正在读取待办…';
|
|
280
285
|
try {
|
|
286
|
+
const previousReadBasis = decisionReadBasis(latestDecisionPage);
|
|
281
287
|
const page = await client.readDecisions(more ? decisionOffset : 0, 10);
|
|
282
|
-
|
|
288
|
+
const presentation = decisionPresentation(page);
|
|
289
|
+
const changedRead = more && presentation.renderRows && previousReadBasis !== null
|
|
290
|
+
&& decisionReadBasis(page) !== previousReadBasis;
|
|
283
291
|
showDecisionBadge(page);
|
|
284
|
-
motion.setPendingDecision(
|
|
292
|
+
motion.setPendingDecision(presentation.pending);
|
|
285
293
|
if (controls.panel !== 'decisions') return;
|
|
286
294
|
const list = $('decision-list');
|
|
287
|
-
if (!more) { list.replaceChildren(); list.scrollTop = 0; }
|
|
288
|
-
|
|
295
|
+
if (!more || changedRead) { list.replaceChildren(); list.scrollTop = 0; }
|
|
296
|
+
const retainedRows = more && !presentation.renderRows && list.children.length > 0;
|
|
297
|
+
const knownVariantRefs = new Set(Array.from(list.children)
|
|
298
|
+
.map(item => item.dataset.variantRef).filter(Boolean));
|
|
299
|
+
for (const row of presentation.renderRows && !changedRead ? decisionRows(page) : []) {
|
|
300
|
+
if (row.variantRef && knownVariantRefs.has(row.variantRef)) continue;
|
|
289
301
|
const item = document.createElement('li');
|
|
302
|
+
if (row.variantRef) { item.dataset.variantRef = row.variantRef; knownVariantRefs.add(row.variantRef); }
|
|
290
303
|
const title = document.createElement('strong');
|
|
291
304
|
const meta = document.createElement('span');
|
|
292
305
|
title.textContent = row.title; meta.textContent = row.meta;
|
|
293
306
|
item.append(title, meta); list.append(item);
|
|
294
|
-
if (row.
|
|
307
|
+
if (row.navigation) {
|
|
308
|
+
const button = document.createElement('button');
|
|
309
|
+
button.type = 'button'; button.textContent = row.navigation.label;
|
|
310
|
+
button.onclick = async () => {
|
|
311
|
+
try {
|
|
312
|
+
const result = await client.openDecision(row.navigation.variantRef, row.navigation.target);
|
|
313
|
+
$('decision-status').textContent = result.delivery === 'requested'
|
|
314
|
+
? '已请求打开对应事项' : '打开对应事项尚未确认 · 请从 Cat Café 查看';
|
|
315
|
+
} catch { $('decision-status').textContent = '暂时无法打开对应事项 · 请稍后重试'; }
|
|
316
|
+
};
|
|
317
|
+
item.append(button);
|
|
318
|
+
} else if (row.previewable) {
|
|
295
319
|
const button = document.createElement('button');
|
|
296
320
|
button.type = 'button'; button.textContent = '查看确认演练';
|
|
297
321
|
button.onclick = async () => {
|
|
@@ -307,17 +331,25 @@ if (!window.clowderCompanion) {
|
|
|
307
331
|
item.append(button);
|
|
308
332
|
}
|
|
309
333
|
}
|
|
310
|
-
decisionOffset = page.page.offset + page.page.limit;
|
|
311
|
-
|
|
312
|
-
$('decision-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
: '
|
|
316
|
-
|
|
334
|
+
decisionOffset = changedRead ? 0 : page.page.offset + page.page.limit;
|
|
335
|
+
$('decision-reload').textContent = changedRead ? '刷新' : presentation.reloadLabel;
|
|
336
|
+
$('decision-status').textContent = changedRead && page.totalCount !== 0
|
|
337
|
+
? '待办已变化 · 请刷新查看最新列表'
|
|
338
|
+
: retainedRows
|
|
339
|
+
? `${presentation.badge.state === 'authentication' ? '待办需要登录' : '待办暂不可读'} · 以下为上次读到的内容`
|
|
340
|
+
: presentation.message;
|
|
341
|
+
$('decision-more').hidden = changedRead || !presentation.hasMore;
|
|
317
342
|
} catch {
|
|
318
343
|
showDecisionBadge(undefined);
|
|
319
344
|
motion.setPendingDecision(null);
|
|
320
|
-
if (controls.panel === 'decisions')
|
|
345
|
+
if (controls.panel === 'decisions') {
|
|
346
|
+
const retained = $('decision-list').children.length > 0;
|
|
347
|
+
$('decision-status').textContent = retained
|
|
348
|
+
? '待办暂不可读 · 以下为上次读到的内容'
|
|
349
|
+
: '待办暂不可读 · 请稍后刷新';
|
|
350
|
+
$('decision-reload').textContent = '重试';
|
|
351
|
+
$('decision-more').hidden = true;
|
|
352
|
+
}
|
|
321
353
|
} finally { decisionLoading = false; }
|
|
322
354
|
}
|
|
323
355
|
$('share-badge').onclick = toggleScreen;
|