@xrn1997/dsh-session-delete 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +141 -129
- package/cordis.patch.yml +3 -3
- package/lib/client.js +2811 -1264
- package/lib/index.js +2368 -1277
- package/lib/types/api/attachment-orphans.d.ts +11 -0
- package/lib/types/api/attachment.d.ts +23 -0
- package/lib/types/api/dispatch.d.ts +13 -29
- package/lib/types/api/request-trust.d.ts +45 -0
- package/lib/types/api/route-table.d.ts +52 -18
- package/lib/types/api/trash-rows.d.ts +3 -3
- package/lib/types/client/attachment-view.d.ts +27 -0
- package/lib/types/client/batch-bar.d.ts +1 -1
- package/lib/types/client/batch-confirm.d.ts +2 -2
- package/lib/types/client/batch-menu-item.d.ts +1 -1
- package/lib/types/client/batch-select.d.ts +1 -1
- package/lib/types/client/busy-gate.d.ts +6 -2
- package/lib/types/client/confirm-close.d.ts +14 -0
- package/lib/types/client/context.d.ts +3 -2
- package/lib/types/client/copy.d.ts +102 -42
- package/lib/types/client/delete-confirm.d.ts +1 -3
- package/lib/types/client/delete-menu-item.d.ts +1 -1
- package/lib/types/client/host-rows.d.ts +5 -1
- package/lib/types/client/main-view.d.ts +1 -1
- package/lib/types/client/maintenance-parts.d.ts +25 -0
- package/lib/types/client/maintenance-settings.d.ts +22 -0
- package/lib/types/client/markdown.d.ts +9 -2
- package/lib/types/client/orphan-maintenance.d.ts +16 -13
- package/lib/types/client/receipt.d.ts +44 -2
- package/lib/types/client/remote.d.ts +38 -50
- package/lib/types/client/store.d.ts +14 -3
- package/lib/types/client/trash-confirm.d.ts +2 -15
- package/lib/types/client/trash-detail.d.ts +48 -6
- package/lib/types/client/trash-entry.d.ts +1 -1
- package/lib/types/client/trash-nav.d.ts +12 -8
- package/lib/types/client/trash-panel.d.ts +4 -3
- package/lib/types/client/ui/Checkbox.d.ts +1 -1
- package/lib/types/client/ui/Modal.d.ts +2 -2
- package/lib/types/client/ui/Toast.d.ts +3 -1
- package/lib/types/client/ui/icons.d.ts +7 -12
- package/lib/types/client/ui/top-layer.d.ts +10 -0
- package/lib/types/client/undo-notices.d.ts +52 -0
- package/lib/types/client/undo-toast.d.ts +6 -59
- package/lib/types/client/use-column-resize.d.ts +9 -20
- package/lib/types/client/use-maintenance-section.d.ts +52 -0
- package/lib/types/client/use-maintenance.d.ts +17 -0
- package/lib/types/client/use-panel-width.d.ts +1 -1
- package/lib/types/client/use-trash-panel-controller.d.ts +54 -16
- package/lib/types/client/use-trash-query.d.ts +39 -34
- package/lib/types/client/use-trash-selection.d.ts +15 -12
- package/lib/types/client/write-seats.d.ts +36 -28
- package/lib/types/client/write-settlement.d.ts +11 -17
- package/lib/types/client/write.d.ts +21 -8
- package/lib/types/deps.d.ts +18 -7
- package/lib/types/domain/closure.d.ts +44 -0
- package/lib/types/index.d.ts +6 -2
- package/lib/types/log/session-log.d.ts +4 -3
- package/lib/types/log/zstd-frames.d.ts +13 -8
- package/lib/types/ports/agent-handles.d.ts +1 -1
- package/lib/types/ports/connection-port.d.ts +33 -0
- package/lib/types/ports/fs-port.d.ts +24 -9
- package/lib/types/ports/host-port.d.ts +21 -50
- package/lib/types/ports/presence-port.d.ts +31 -0
- package/lib/types/shared/wire.d.ts +175 -38
- package/lib/types/trash/attachments.d.ts +92 -0
- package/lib/types/trash/detail.d.ts +46 -16
- package/lib/types/trash/entry.d.ts +10 -4
- package/lib/types/trash/groups.d.ts +9 -11
- package/lib/types/trash/manifest.d.ts +4 -4
- package/lib/types/trash/storage-manifest.d.ts +1 -1
- package/lib/types/verbs/batch-carried.d.ts +1 -3
- package/lib/types/verbs/delete-session.d.ts +2 -2
- package/lib/types/verbs/errors.d.ts +2 -0
- package/lib/types/verbs/live-admission.d.ts +4 -7
- package/lib/types/verbs/member-journal.d.ts +3 -4
- package/lib/types/verbs/member-presence.d.ts +16 -37
- package/lib/types/verbs/move-group.d.ts +2 -1
- package/lib/types/verbs/orphan-subagents.d.ts +19 -12
- package/lib/types/verbs/permanent-removal.d.ts +60 -25
- package/lib/types/verbs/restore-session.d.ts +7 -13
- package/lib/types/verbs/trash-scope.d.ts +36 -0
- package/package.json +117 -106
- package/lib/types/verbs/purge-trash.d.ts +0 -30
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 本插件 UI
|
|
3
|
-
*
|
|
2
|
+
* 本插件 UI 层要用的图标(逐条抄自 `@deepseek-ai/dsh-client-ui-primitives` 的明文产物;
|
|
3
|
+
* 出处与改写规则见 `ui.css` 头注)。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* 关闭叉(对话框)、圆圈对勾(撤销提示的 success 档)、对勾(行尾兜底勾选开关,2026-10-17 加;
|
|
7
|
-
* 行首主勾选走原生 Checkbox)、下折与右折 chevron(清单的分组折叠头,
|
|
8
|
-
* 2026-10-15 加:`DisclosureRow` 那套折叠行的两态 glyph)。「刷新」那枚随按钮一起删了
|
|
9
|
-
* (2026-10-16,见 `trash-panel.tsx` 工具排的注释)——本文件不留无人消费的几何。
|
|
5
|
+
* 只留本插件用到的:垃圾桶、警示、打开的项目文件夹、关闭叉、圆圈对勾、对勾、下折/右折 chevron。
|
|
10
6
|
* **几何、`viewBox`、`strokeWidth` 逐字不动**——它们是官方图标集的形状,改了就不再与宿主同屏同形。
|
|
11
7
|
*
|
|
12
8
|
* 两条与官方实现的差异(都是减法,不是改写):
|
|
13
|
-
* - 只暴露 `size
|
|
14
|
-
*
|
|
15
|
-
* - 不做 `ICON_REGULAR_STROKE` / `ICON_MEDIUM_STROKE` 常量:只有一个档位,直接写 1。
|
|
9
|
+
* - 只暴露 `size`:调用处只传 `size`,不摊开官方整个图标 API。
|
|
10
|
+
* - 不做 stroke 常量:只有一个档位,直接写 1。
|
|
16
11
|
*/
|
|
17
12
|
import type { ReactElement } from 'react';
|
|
18
13
|
/** 宿主图标组件的实际使用面:一个方形边长,色走 `currentColor`。 */
|
|
19
14
|
export interface IconProps {
|
|
20
|
-
size?: number;
|
|
15
|
+
size?: number | undefined;
|
|
21
16
|
}
|
|
22
17
|
export declare function IconTrashOutlineRegular({ size }: IconProps): ReactElement;
|
|
23
18
|
export declare function IconWarningOutlineRegular({ size }: IconProps): ReactElement;
|
|
@@ -25,7 +20,7 @@ export declare function IconFolderOpenOutlineRegular({ size }: IconProps): React
|
|
|
25
20
|
export declare function IconCloseOutlineRegular({ size }: IconProps): ReactElement;
|
|
26
21
|
/** 撤销提示 success 档的前导 glyph(官方 `Toast` 在 `tone="success"` 时自带的那一枚)。 */
|
|
27
22
|
export declare function IconCheckCircleOutlineRegular({ size }: IconProps): ReactElement;
|
|
28
|
-
/**
|
|
23
|
+
/** 行尾兜底勾选开关那枚对勾(状态点/归档行;官方几何逐字)。 */
|
|
29
24
|
export declare function IconCheckOutlineRegular({ size }: IconProps): ReactElement;
|
|
30
25
|
/** 分组头「展开中」那一枚(官方 `IconChevronDownOutlineRegular`,`viewBox`/`d` 逐字)。 */
|
|
31
26
|
export declare function IconChevronDownOutlineRegular({ size }: IconProps): ReactElement;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 「谁在最上层收 Escape」的名单与判据。`Modal` 的关闭键和清单的 Esc 退下钻共用这一份:
|
|
3
|
+
* 两份各写一次选择器,菜单/对话框换代时必然只剩一处跟上。
|
|
4
|
+
*
|
|
5
|
+
* 名单与官方 `modalSelector` 同形:模态对话框 + 菜单。文档序里最后一个是「最上层」。
|
|
6
|
+
*/
|
|
7
|
+
/** 文档里是否还有打开的顶层浮层。清单只问「有没有」,它自己不是其中一员。 */
|
|
8
|
+
export declare function hasTopLayer(doc: Document): boolean;
|
|
9
|
+
/** 自己是不是文档里最上面的那一层。Modal 只在这时收 Escape。 */
|
|
10
|
+
export declare function isTopLayer(element: HTMLElement): boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一次待撤销的事。两形:单条删除(主语是会话名)/批量删除(主语是条数)。
|
|
3
|
+
* 同一个 Toast 宿主、同一停留时长;撤销动作按形分派(单条 / 批量),两条都走同一个外部恢复座位
|
|
4
|
+
* (`write-seats.ts` 的 `restoreFromUndo`),单条带 `single: true` 的读法(null 是协议错,不冒充幂等成功)。
|
|
5
|
+
*/
|
|
6
|
+
export type UndoNotice = {
|
|
7
|
+
/** 每次发布递增:Toast 靠它重挂载,同一段文案连续出现两次也能重新计一次停留。 */
|
|
8
|
+
seq: number;
|
|
9
|
+
/** 撤销失败时把原因顶上来:这时不再有「撤销」动作,只剩原文。 */
|
|
10
|
+
failure?: string;
|
|
11
|
+
} & ({
|
|
12
|
+
kind: 'one';
|
|
13
|
+
/** 回收站条目 id——撤销就是拿它去 `restore`。 */
|
|
14
|
+
entryId: string;
|
|
15
|
+
/** 删除那一刻的会话名(菜单槽投影的 `displayTitle`;取不到时是空串)。 */
|
|
16
|
+
title: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'batch';
|
|
19
|
+
/** 撤销名单:只收成功支里非 null 的条目 id(「被同批带走」的成员跟着组走,不单列)。 */
|
|
20
|
+
entryIds: readonly string[];
|
|
21
|
+
/** 横幅那句的条数 = 那一次成功支的条数(含幂等带走的)——与撤销名单是两个数,各说各的。 */
|
|
22
|
+
n: number;
|
|
23
|
+
});
|
|
24
|
+
/** 删除成功后发布一条撤销提示(单条)。 */
|
|
25
|
+
export declare function publishUndoNotice(input: {
|
|
26
|
+
entryId: string;
|
|
27
|
+
title: string;
|
|
28
|
+
}): void;
|
|
29
|
+
/** 批量删除成功后发布一条撤销提示:覆盖上一条,只报这一次移走的条数。 */
|
|
30
|
+
export declare function publishUndoBatchNotice(input: {
|
|
31
|
+
entryIds: readonly string[];
|
|
32
|
+
n: number;
|
|
33
|
+
}): void;
|
|
34
|
+
/** 整条横幅不再留:撤销成了、停留时间走完,或清空回收站把所有落点一起清了。
|
|
35
|
+
* 与 `dismissUndoNotice` 的分别是「整条不再留」与「按条目匹配」——清空之后没有条目还能撤销,
|
|
36
|
+
* 所以那一路不需要名单。 */
|
|
37
|
+
export declare function clearUndoNotice(): void;
|
|
38
|
+
/**
|
|
39
|
+
* 某个条目已经在别处恢复:把指向它的横幅熄掉。
|
|
40
|
+
* 批量里任一命中就清整条——名单少了、计数没变,留着就是一条会骗人的「撤销」动作。
|
|
41
|
+
*/
|
|
42
|
+
export declare function dismissUndoNotice(entryIds: readonly string[]): void;
|
|
43
|
+
/** 供组件订阅。 */
|
|
44
|
+
export declare function useUndoNotice(): UndoNotice | null;
|
|
45
|
+
/** 测试专用:现场与 seq 归零,用例之间互不串味。 */
|
|
46
|
+
export declare function resetUndoNotice(): void;
|
|
47
|
+
/** 提示停留时长。**6 秒** 定死在本行(比 Toast 默认的 3 秒长)——`docs/ui-spec.md` §2 状态 ③ 只指到这里,不抄这个数。 */
|
|
48
|
+
export declare const UNDO_HOLD_MS = 6000;
|
|
49
|
+
/** 这次撤销开始时的那条横幅还在吗——期间被新删除覆盖、或由面板恢复熄灭时,旧请求不许改写它。 */
|
|
50
|
+
export declare function ownsNotice(current: UndoNotice): boolean;
|
|
51
|
+
/** 撤销失败:把原因换到同一条横幅上(seq 递增 ⇒ Toast 重挂载、重新计停留)。 */
|
|
52
|
+
export declare function failNotice(current: UndoNotice, message: string): void;
|
|
@@ -1,71 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 撤销提示(docs/ui-spec.md 状态 ③):删除成功后一条可撤销的横幅。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `rowToastInjected = () => ({ hooks: { toast: rowToast }, dismissToast, undoArchive: unarchiveSession })`)。
|
|
10
|
-
* 本文件就是那份 store + 那个常驻组件。
|
|
11
|
-
*
|
|
12
|
-
* 状态源走 `store.ts` 的 `createStore`(内部用 React 自带的 `useSyncExternalStore`)——
|
|
13
|
-
* 不引 `@deepseek-ai/dsh-client-store`(它在平台表内,但这里用不着;React 就够,少一条平台依赖)。
|
|
4
|
+
* 现场与发布住在 `undo-notices.ts`;本文件只做组件:画通知台已有的事实,「撤销」整趟按下交给
|
|
5
|
+
* `write-seats.ts` 的 `restoreFromUndo`(编排归恢复座位,见 ADR-0018 的边界)。
|
|
6
|
+
* 为什么组件要独立:宿主的菜单行随菜单**一起卸载**(真产物 Menu 的注释原文
|
|
7
|
+
* "the rows unmount with the list"),而提示要在菜单关掉之后还活着。宿主的官方配方同形——
|
|
8
|
+
* 会话行的动作把请求写进一个模块级 store,`shell.overlay` 里的 `workspace.row-toast` 读它。
|
|
14
9
|
*/
|
|
15
10
|
import { type Translate } from './copy.js';
|
|
16
11
|
import type { OneShotDeps } from './remote.js';
|
|
17
12
|
export type UndoToastDeps = OneShotDeps;
|
|
18
|
-
/**
|
|
19
|
-
* 一次待撤销的事。两形(2026-10-17 起):单条删除(主语是会话名)/批量删除(主语是条数)。
|
|
20
|
-
* 同一个 Toast 宿主、同一停留时长;撤销动作按形分派(单条 / 批量),两条都走同一个外部恢复座位
|
|
21
|
-
* (`write-seats.ts` 的 `restoreFromUndo`),单条带 `single: true` 的读法(null 是协议错,不冒充幂等成功)。
|
|
22
|
-
*/
|
|
23
|
-
export type UndoNotice = {
|
|
24
|
-
/** 每次发布递增:Toast 靠它重挂载,同一段文案连续出现两次也能重新计一次停留。 */
|
|
25
|
-
seq: number;
|
|
26
|
-
/** 撤销失败时把原因顶上来:这时不再有「撤销」动作,只剩原文。 */
|
|
27
|
-
failure?: string;
|
|
28
|
-
} & ({
|
|
29
|
-
kind: 'one';
|
|
30
|
-
/** 回收站条目 id——撤销就是拿它去 `restore`。 */
|
|
31
|
-
entryId: string;
|
|
32
|
-
/** 删除那一刻的会话名(菜单槽投影的 `displayTitle`;取不到时是空串)。 */
|
|
33
|
-
title: string;
|
|
34
|
-
} | {
|
|
35
|
-
kind: 'batch';
|
|
36
|
-
/** 撤销名单:只收成功支里非 null 的条目 id(「被同批带走」的成员跟着组走,不单列)。 */
|
|
37
|
-
entryIds: readonly string[];
|
|
38
|
-
/** 横幅那句的条数 = 那一次成功支的条数(含幂等带走的)——与撤销名单是两个数,各说各的。 */
|
|
39
|
-
n: number;
|
|
40
|
-
});
|
|
41
|
-
/** 删除成功后发布一条撤销提示(单条)。 */
|
|
42
|
-
export declare function publishUndoNotice(input: {
|
|
43
|
-
entryId: string;
|
|
44
|
-
title: string;
|
|
45
|
-
}): void;
|
|
46
|
-
/** 批量删除成功后发布一条撤销提示(2026-10-17):覆盖上一条,只报这一次移走的条数。 */
|
|
47
|
-
export declare function publishUndoBatchNotice(input: {
|
|
48
|
-
entryIds: readonly string[];
|
|
49
|
-
n: number;
|
|
50
|
-
}): void;
|
|
51
|
-
/** 整条横幅不再留:撤销成了、停留时间走完,或清空回收站把所有落点一起清了。
|
|
52
|
-
* 与下面 `dismissUndoNotice` 的分别是「整条不再留」与「按条目匹配」——清空之后没有条目还能撤销,
|
|
53
|
-
* 所以那一路不需要名单。 */
|
|
54
|
-
export declare function clearUndoNotice(): void;
|
|
55
|
-
/**
|
|
56
|
-
* 某个条目已经在别处恢复:把指向它的横幅熄掉。
|
|
57
|
-
* 批量里任一命中就清整条——名单少了、计数没变,留着就是一条会骗人的「撤销」动作。
|
|
58
|
-
*/
|
|
59
|
-
export declare function dismissUndoNotice(entryIds: readonly string[]): void;
|
|
60
|
-
/** 供组件订阅。 */
|
|
61
|
-
export declare function useUndoNotice(): UndoNotice | null;
|
|
62
|
-
/** 测试专用:现场与 seq 归零,用例之间互不串味。 */
|
|
63
|
-
export declare function resetUndoNotice(): void;
|
|
64
|
-
/** 提示停留时长。**6 秒** 定死在本行(比 Toast 默认的 3 秒长)——`docs/ui-spec.md` §2 状态 ③ 只指到这里,不抄这个数。 */
|
|
65
|
-
export declare const UNDO_HOLD_MS = 6000;
|
|
66
13
|
/**
|
|
67
14
|
* 常驻的撤销提示宿主。挂 `shell.overlay`(框架级浮层;槽位说明原文 "a toast stack or a status
|
|
68
|
-
* pill all belong here"
|
|
15
|
+
* pill all belong here"):没有待撤销的事时什么都不渲染。
|
|
69
16
|
*/
|
|
70
17
|
export declare function UndoToast({ deps, t }: {
|
|
71
18
|
deps: UndoToastDeps;
|
|
@@ -1,26 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 清单列与详情列之间那根可拖的宽度把手(docs/ui-spec.md 的「面板与清单」)。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* ①
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* 它就成了假数,而 900 那档的真实读数是**清单被夹到 411**(比默认窄 9px,还能往里拖)。
|
|
11
|
-
* ② **夹在"读"的时候也做一次**。窗口变窄不触发任何写入,若只在写入时夹,之前拖出来的超宽
|
|
12
|
-
* 清单会一直留到下次交互 ⇒ `listWidth` 每次渲染都按当前 `panelWidth` 重算。
|
|
13
|
-
* ③ **按下才算在拖**。指针捕获挂在把手元素上(`setPointerCapture`),move 只可能来自这一根把手;
|
|
14
|
-
* `origin === null` 时 move 直接返回——鼠标扫过不该改布局。抬起不用显式 release:规范里
|
|
15
|
-
* pointerup/pointercancel 会隐式释放捕获,多写那一行只会引入"指针已不活跃"的抛错面。
|
|
16
|
-
* **但"结束"不能只挂在把手上**:拖动途中把手会被卸载(面板窄过断点、或清单被读空 ⇒ `split`
|
|
17
|
-
* 翻了),而卸载后的节点收不到任何事件 ⇒ `resizing` 永远挂着:面板根留着 `.sd-resizing`
|
|
18
|
-
* (关文字选中),下次变宽时把手还带着 `data-dragging` 长回来。所以拖住期间另在 window 上兜
|
|
19
|
-
* 一层 `pointerup`/`pointercancel`(复用同一个 `stop`)。move 仍然只认把手,捕获那套一点没动。
|
|
4
|
+
* 三件事住在这里:
|
|
5
|
+
* ① 宽度夹在两个界之间:下限由调用方给,上限 = 面板宽 − reserve。
|
|
6
|
+
* reserve 的数值与来历住在调用方(DETAIL_RESERVE),这一层不复制算式。
|
|
7
|
+
* ② 夹在“读”的时候也做一次:窗口变窄不触发写入,listWidth 每次渲染按当前 panelWidth 重算。
|
|
8
|
+
* ③ 按下才算在拖:指针捕获挂在把手元素上;拖动途中把手可能卸载,所以 window 上另兜一层
|
|
9
|
+
* pointerup/pointercancel 复用 stop;move 仍只认把手。
|
|
20
10
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* 所以焦点态的可见性由 `ui.css` 里 `.sd-width-handle:focus-visible::after` 那一条负责。
|
|
11
|
+
* 键盘:role=separator、←→ 各一格、Home 回默认、End 到上限;焦点态可见性由 ui.css 的
|
|
12
|
+
* .sd-width-handle:focus-visible::after 负责。
|
|
24
13
|
*/
|
|
25
14
|
import { type KeyboardEvent, type PointerEvent } from 'react';
|
|
26
15
|
export interface ColumnResizeArgs {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { RemoteOutcome } from './remote.js';
|
|
2
|
+
/** 一段在飞的动作:检查只读,清理会写。状态行靠它分开说「检查中…」与「清理中…」;`null` = 空闲。 */
|
|
3
|
+
export type MaintenancePhase = 'scanning' | 'cleaning';
|
|
4
|
+
/** 一段维护交给界面的全部:三份读数(报告 / 失败 / 中性提示)、一个确认框、一档忙碌,加四个动作。 */
|
|
5
|
+
export interface MaintenanceSectionView<R> {
|
|
6
|
+
/** `null` = 还没检查(或上一次检查失败——失败在 `failure` 单独一格,不折成零条)。 */
|
|
7
|
+
readonly report: R | null;
|
|
8
|
+
readonly failure: string | null;
|
|
9
|
+
/** 「这一组已经不在」/ 上一趟清理的回执——不是失败:单独一条中性提示。 */
|
|
10
|
+
readonly notice: string | null;
|
|
11
|
+
readonly confirm: boolean;
|
|
12
|
+
readonly phase: MaintenancePhase | null;
|
|
13
|
+
/** 段自己给的忙碌(在飞即忙),不再作为 prop 传递。 */
|
|
14
|
+
readonly busy: boolean;
|
|
15
|
+
/** 手动检查(也是失败块的重试)。 */
|
|
16
|
+
scan: () => Promise<void>;
|
|
17
|
+
/** 唯一开门:先清旧失败与旧提示再开确认框。 */
|
|
18
|
+
openPreview: () => void;
|
|
19
|
+
/** 清完必重查;回执句子由 config 拼。 */
|
|
20
|
+
clean: () => Promise<void>;
|
|
21
|
+
/** 只收确认框,不碰提示 / 失败。 */
|
|
22
|
+
cancel: () => void;
|
|
23
|
+
}
|
|
24
|
+
/** `settle` 拼出的这一趟要摆的句子;**缺席的格子表示"不碰"**(重查刚摆上的状态保持原样)。 */
|
|
25
|
+
export interface MaintenanceSettlePlan {
|
|
26
|
+
readonly notice?: string | null;
|
|
27
|
+
readonly failure?: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface MaintenanceSectionConfig<R, C> {
|
|
30
|
+
/** 手动检查(也是失败块的重试)。交回的已是落地面——glue 用 `callRemote` 包装、不会抛,module 不再包一层。 */
|
|
31
|
+
scan(): Promise<RemoteOutcome<R>>;
|
|
32
|
+
/** 清理写动作;入参是点击那一刻的报告(清理输入由各段自己从里面点名)。报告没活可干时
|
|
33
|
+
* 同步回 `null`:不发请求、只收确认框——"没活"的判据各段不同,是各段的业务。
|
|
34
|
+
* 同样交回落地面、不抛。`C` 是这一段的回执形状:状态机不认识它,只把它原样递给
|
|
35
|
+
* `beforeRescan` / `settle`,段那边就不必把 `outcome.value` 擦回 `unknown` 再 `as` 一次。 */
|
|
36
|
+
clean(report: R): Promise<RemoteOutcome<C>> | null;
|
|
37
|
+
/** 清理落地后、必发的重查起飞前先摆的读数;`null` = 不动。附件段用它把"已清空"先收成 0:
|
|
38
|
+
* 旧报告不再可信,别让旧横幅在重查飞着时冒充"没清"。 */
|
|
39
|
+
beforeRescan?(outcome: RemoteOutcome<C>): R | null;
|
|
40
|
+
/** 检查读不到时的上屏句;本地化前缀各段自己给。 */
|
|
41
|
+
scanFailureText(message: string): string;
|
|
42
|
+
/** 这一趟检查**赢了**(没被更晚的检查顶掉)之后顺手收掉的东西;输家不调用。它在赢家的读数
|
|
43
|
+
* 落地**之前**触发,故只许写自己那份不属于读数的状态。孤儿会话段用它清上一趟清理的附件回执
|
|
44
|
+
* ——「收掉旧回执」属于最新读数成立的一部分,放在发请求之前会让被顶掉的输家也清掉赢家的回执。 */
|
|
45
|
+
onScanWon?: () => void;
|
|
46
|
+
/** 清理回执(含顶层失败)→ 这一趟的句子。重查赢了才调用;段独有的第二回执(如孤儿会话段顺带
|
|
47
|
+
* 清掉的附件读数)由它顺手写自己的状态——那不是这台状态机的格子。
|
|
48
|
+
* `report` 是**这一趟**点击那一刻的报告:回执要按请求名单逐条判读,名单只能随这一趟交下来;
|
|
49
|
+
* 段自己存一份"最近一次清理的名单"会在两趟交错时把上一趟的回执按后一趟的名单判读。 */
|
|
50
|
+
settle(outcome: RemoteOutcome<C>, report: R): MaintenanceSettlePlan;
|
|
51
|
+
}
|
|
52
|
+
export declare function useMaintenanceSection<R, C>(config: MaintenanceSectionConfig<R, C>): MaintenanceSectionView<R>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Translate } from './copy.js';
|
|
2
|
+
import { type AttachmentOrphanReportWire, type OrphanReportWire, type SessionDeleteRemote } from './remote.js';
|
|
3
|
+
import { type MaintenanceSectionView } from './use-maintenance-section.js';
|
|
4
|
+
/** 维护卡只需要这四段:两份报告 + 孤儿会话的批量写 + 孤儿附件的聚合写。 */
|
|
5
|
+
export type MaintenanceDeps = Pick<SessionDeleteRemote, 'scanOrphans' | 'applyOutcomes' | 'scanAttachmentOrphans' | 'cleanAttachmentOrphans'>;
|
|
6
|
+
export interface Maintenance {
|
|
7
|
+
/** 孤儿会话段 + 它独有的第二回执:这一趟清理顺带清掉的附件读数(`.dsh` 内独占图片副本)。
|
|
8
|
+
* 重查读不出来,和段的 `notice` 一样是过去那一趟的回执;下一次检查 / 清理会被收掉。 */
|
|
9
|
+
readonly orphans: MaintenanceSectionView<OrphanReportWire> & {
|
|
10
|
+
readonly attachmentNotice: string | null;
|
|
11
|
+
};
|
|
12
|
+
readonly attachments: MaintenanceSectionView<AttachmentOrphanReportWire>;
|
|
13
|
+
}
|
|
14
|
+
export declare function useMaintenance({ deps, t }: {
|
|
15
|
+
deps: MaintenanceDeps;
|
|
16
|
+
t: Translate;
|
|
17
|
+
}): Maintenance;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* 量的是**盒子的 border-box 宽**(`getBoundingClientRect().width`),不是 `contentRect.width`:
|
|
8
8
|
* 后者已经扣掉内边距,而"多宽才分两栏"那个阈值说的是整块盒子——拿扣过内边垫的数去比就是**扣两次**,
|
|
9
|
-
*
|
|
9
|
+
* 结果明明够宽却退化成下钻(真机反馈后定的判据)。
|
|
10
10
|
*
|
|
11
11
|
* 首帧读一次当前宽度,之后跟着 RO 走;读到 0 就是窄档 ⇒ **窄档是默认、宽档要被证明**。
|
|
12
12
|
* RO 缺席(不可能的宿主)时停在窄档:功能一条不少,只是同屏两栏变成下钻。
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import type { BusyGate } from './busy-gate.js';
|
|
2
2
|
import { type SessionDeleteRemote, type TrashEntryLike } from './remote.js';
|
|
3
|
-
import type {
|
|
4
|
-
import type { TrashDetailState } from './trash-detail.js';
|
|
5
|
-
import type
|
|
3
|
+
import type { TrashEntryWire } from '../shared/wire.js';
|
|
4
|
+
import type { DetailNav, TrashDetailState } from './trash-detail.js';
|
|
5
|
+
import { type TrashQuery } from './use-trash-query.js';
|
|
6
|
+
/** 待确认的动作:一条记录、整个回收站、或多选挑出来的一批(`ids` 已按清单顺序排好)。
|
|
7
|
+
* 类型归状态机,视图只 import 它来渲染。 */
|
|
8
|
+
export type PendingAction = {
|
|
9
|
+
kind: 'entry';
|
|
10
|
+
entry: TrashEntryLike;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'all';
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'entries';
|
|
15
|
+
ids: readonly string[];
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'restore';
|
|
18
|
+
ids: readonly string[];
|
|
19
|
+
};
|
|
6
20
|
/**
|
|
7
|
-
* 控制器要的面。`query` 取四样:清单(选中从它里面找)、`
|
|
8
|
-
*
|
|
9
|
-
* "屏幕上的顺序"(只含展开的组),
|
|
10
|
-
*
|
|
21
|
+
* 控制器要的面。`query` 取四样:清单(选中从它里面找)、`reload`(挂载、显式重试、失效与写后
|
|
22
|
+
* 都是同一条读)、清空(面板的写动作那一半)、`noteAttachmentCleanup`(purge 回执里
|
|
23
|
+
* 附件那半句交给查询侧拼句子上屏)。`ordered` 是键盘/自动选中用的"屏幕上的顺序"(只含展开的组),
|
|
24
|
+
* 由面板算好传进来——布局常量不搬进控制器。输入的引用**不需稳定**:失效 effect 的判据只有
|
|
25
|
+
* `revision`,reload 回调经 `useLatest` 读最新那一份(判据住 `store.ts`)。
|
|
11
26
|
*/
|
|
12
27
|
export interface TrashPanelControllerInput {
|
|
13
28
|
deps: Pick<SessionDeleteRemote, 'detail' | 'applyOutcomes'>;
|
|
14
29
|
gate: BusyGate;
|
|
15
|
-
query: Pick<TrashQuery, '
|
|
30
|
+
query: Pick<TrashQuery, 'list' | 'reload' | 'emptyTrash' | 'noteAttachmentCleanup'>;
|
|
16
31
|
ordered: readonly TrashEntryLike[];
|
|
17
32
|
canAutoSelect: boolean;
|
|
18
33
|
}
|
|
@@ -20,23 +35,46 @@ export interface TrashPanelController {
|
|
|
20
35
|
readonly busy: boolean;
|
|
21
36
|
readonly selected: TrashEntryLike | null;
|
|
22
37
|
readonly selectedId: string | null;
|
|
38
|
+
/** 正在看哪个孩子(离清单的详情导航态;null = 看清单选中那条)。单级是设计(ADR-0029):
|
|
39
|
+
* 只有一个槽,`openChild` 换槽不叠栈,返回交还清单选中那条。 */
|
|
40
|
+
readonly childView: TrashEntryWire | null;
|
|
41
|
+
/** 详情的导航面(开孩子 / 回父)。ADR-0029 单级判据的**唯一实现**:面板只转交它,
|
|
42
|
+
* 不再自己拼 openChild / parentContext 两个派生块(判据有第二个家,视图与测试就得各自复述语义)。 */
|
|
43
|
+
readonly detailNav: DetailNav;
|
|
44
|
+
/** 打开一个孩子(父详情子会话段点进来):读它的详情,但清单选中不动。 */
|
|
45
|
+
openChild(child: TrashEntryWire): Promise<void>;
|
|
46
|
+
/** 回到父详情(宽档头部那颗「返回父会话」;窄档 back/Esc 的第一程也走它)。 */
|
|
47
|
+
closeChild(): void;
|
|
23
48
|
readonly drilled: boolean;
|
|
24
49
|
readonly detail: TrashDetailState;
|
|
50
|
+
/** 更早一页正在读(只对当前详情主体有意义:孩子视图开着就是孩子)。 */
|
|
51
|
+
readonly loadingOlder: boolean;
|
|
52
|
+
/** 更早一页读失败的原文(只对当前详情主体有意义;正文本身仍是 ready)。 */
|
|
53
|
+
readonly olderFailure: string | null;
|
|
25
54
|
/** 待确认的那一批(确认框的开合);确认落地后由控制器收起。 */
|
|
26
55
|
readonly pending: PendingAction | null;
|
|
56
|
+
/** 恢复确认框要摆的这一批(按勾选顺序;清单里已找不到的 id 滤掉)。 */
|
|
57
|
+
readonly pendingEntries: readonly TrashEntryLike[];
|
|
27
58
|
/** 恢复/彻底删除/批量 的失败原文,按条目 id 存:切走再回来还在。 */
|
|
28
59
|
readonly actionFailure: Readonly<Record<string, string>>;
|
|
29
|
-
|
|
60
|
+
/** 下面是面板会**摘下来转交**的动作(导航的 `select`/`back`、确认框的 `cancelPending`):
|
|
61
|
+
* 属性声明而不是方法简写,实现体都不读 `this`。方法简写的隐式 `this` 会让 `unbound-method`
|
|
62
|
+
* 把转交报成可疑;改形状是纯类型面,零运行时改动。 */
|
|
63
|
+
select: (entry: TrashEntryLike, options?: {
|
|
30
64
|
drill?: boolean;
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
65
|
+
}) => Promise<void>;
|
|
66
|
+
/** 按当前详情的 `olderCursor` 读更早一页,拼到现有块前面。 */
|
|
67
|
+
loadOlder: () => Promise<void>;
|
|
68
|
+
retry: () => void;
|
|
69
|
+
back: () => void;
|
|
70
|
+
/** 构造待确认动作(唯一入口:新增一种确认只改 `PendingAction` 与确认框,不再加一串转调)。 */
|
|
71
|
+
request: (action: PendingAction) => void;
|
|
72
|
+
cancelPending: () => void;
|
|
35
73
|
/** 单条恢复(`/apply` 的 N=1):成功后丢缓存,写完无论成败都重读清单,失败原文落回这一行。 */
|
|
36
|
-
restore(entry: TrashEntryLike)
|
|
74
|
+
restore: (entry: TrashEntryLike) => Promise<void>;
|
|
37
75
|
/** 确认框上的「确认」:按 `pending.kind` 分派到空清或 `confirmApply`。 */
|
|
38
|
-
confirmPurge()
|
|
76
|
+
confirmPurge: () => Promise<void>;
|
|
39
77
|
/** 一组 id 上的同一个动作:逐条成败落成行上原文/缓存失效,整批只重读一次清单。 */
|
|
40
|
-
confirmApply(action: 'purge' | 'restore', ids: readonly string[])
|
|
78
|
+
confirmApply: (action: 'purge' | 'restore', ids: readonly string[]) => Promise<void>;
|
|
41
79
|
}
|
|
42
80
|
export declare function useTrashPanelController(input: TrashPanelControllerInput): TrashPanelController;
|
|
@@ -1,43 +1,48 @@
|
|
|
1
1
|
import type { BusyGate } from './busy-gate.js';
|
|
2
|
-
import { type
|
|
3
|
-
import type { WriteOutcome } from './write.js';
|
|
2
|
+
import { type SessionDeleteRemote, type TrashEntryLike } from './remote.js';
|
|
4
3
|
import type { Translate } from './copy.js';
|
|
5
|
-
import type {
|
|
6
|
-
export type TrashQueryDeps = Pick<SessionDeleteRemote, 'list' | '
|
|
7
|
-
/**
|
|
8
|
-
export type
|
|
4
|
+
import type { AttachmentCleanupWire } from '../shared/wire.js';
|
|
5
|
+
export type TrashQueryDeps = Pick<SessionDeleteRemote, 'list' | 'emptyTrash'>;
|
|
6
|
+
/** 清单的唯一状态:加载中 / 有行 / 未知。`unknown` 不向下游交出任何行——旧行不许继续可操作。 */
|
|
7
|
+
export type TrashListState = {
|
|
8
|
+
readonly status: 'loading';
|
|
9
|
+
} | {
|
|
10
|
+
readonly status: 'ready';
|
|
11
|
+
readonly rows: readonly TrashEntryLike[];
|
|
12
|
+
} | {
|
|
13
|
+
readonly status: 'unknown';
|
|
14
|
+
readonly failure: string;
|
|
15
|
+
};
|
|
16
|
+
/** 清单状态对视图的**唯一解读**:行、失败原文、加载中与空态一次交出。
|
|
17
|
+
* 面板与控制器不再各自从 `status` 反推——"未知"不是"空",也不许把失败折成空态。 */
|
|
18
|
+
export interface TrashListView {
|
|
19
|
+
readonly rows: readonly TrashEntryLike[] | null;
|
|
20
|
+
readonly failure: string | null;
|
|
21
|
+
readonly loading: boolean;
|
|
22
|
+
readonly empty: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function listView(list: TrashListState): TrashListView;
|
|
9
25
|
export interface TrashQuery {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
readonly
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
rescanOrphans(): Promise<void>;
|
|
27
|
-
/** 先读清单、成了再扫残留;挂载与显式「重试」用它。 */
|
|
28
|
-
refreshAll(): Promise<void>;
|
|
29
|
-
/** 写后/失效:只重读清单;是否顺带重扫残留由这次的 `outcome` 从 action / ids / 当前清单自行派生
|
|
30
|
-
* (判据住 `needsOrphanRescan`)。失效通告不带 outcome:报告未知或非空才重扫。输给后发读时由赢家补扫;
|
|
31
|
-
* 清单读失败时清空报告与提示。 */
|
|
32
|
-
refreshAfterWrite(outcome?: WriteOutcome<ApplyAction>): Promise<void>;
|
|
33
|
-
/** 清理那批无主子会话(一段 `/apply` 的第五个动作),逐条结果落成"已不在了 / N 组未清理"。 */
|
|
34
|
-
cleanOrphans(): Promise<void>;
|
|
35
|
-
/** 清空回收站(聚合回执):成功就熄掉撤销横幅并重读,失败就把原文摆到清单那块。交回是否成功。 */
|
|
36
|
-
emptyTrash(): Promise<boolean>;
|
|
26
|
+
readonly list: TrashListState;
|
|
27
|
+
/** 最近一次写动作(purge / 清空)的附件读数,已经拼成一句话:**最新的写赢**。
|
|
28
|
+
* 一次没有附件读数的 purge / 清空、或这一趟写失败(没拿到回执)都会把它清成 `null`,不让上一条的
|
|
29
|
+
* 读数冒充这一趟;删除与恢复不碰它。它是**过去那一趟的回执**、不是清单状态:清单重读读不出来。 */
|
|
30
|
+
readonly attachmentNotice: string | null;
|
|
31
|
+
/** 把一份附件读数摆上屏(`undefined` = 这一趟没有读数,旧提示收掉);句子怎么拼归这里,调用方只管转交。 */
|
|
32
|
+
noteAttachmentCleanup: (a: AttachmentCleanupWire | undefined) => void;
|
|
33
|
+
/** 重读清单:挂载、显式「重试」、写后与失效通告都走这一条读——问的是同一件事("清单现在长什么样")。
|
|
34
|
+
* 曾经分作 `refreshAll` / `refreshAfterWrite` 两个名字,那是调用点问的两件事("用户要看现在的"与
|
|
35
|
+
* "别处动过了,跟上"),不是两条路径,合一为 `reload`。面板没有第二条扫描:孤儿检查是设置页
|
|
36
|
+
* 维护卡的手动动作(ADR-0021)。清单读失败时旧行进 `unknown`。 */
|
|
37
|
+
reload: () => Promise<void>;
|
|
38
|
+
/** 清空回收站(聚合回执):成功就熄掉撤销横幅并重读,失败就把清单置为未知并摆上原文。
|
|
39
|
+
* 三种形状各有意思:`true` = 清空落地了;`false` = 这一趟跑了但没清成(原文已在清单那块上屏);
|
|
40
|
+
* `undefined` = 闸把这一趟挡回来了、什么都没跑(调用方不收框,等在飞那一趟的结论)。 */
|
|
41
|
+
emptyTrash: () => Promise<boolean | undefined>;
|
|
37
42
|
}
|
|
38
43
|
export declare function useTrashQuery({ deps, t, gate, }: {
|
|
39
44
|
deps: TrashQueryDeps;
|
|
40
45
|
t: Translate;
|
|
41
|
-
/**
|
|
46
|
+
/** 面板的一枚全局闸:清空这条写动作把整趟包在里面(面板的 `busy`)。 */
|
|
42
47
|
gate: BusyGate;
|
|
43
48
|
}): TrashQuery;
|
|
@@ -9,22 +9,25 @@ export interface TrashSelection {
|
|
|
9
9
|
/** 键盘 ↑↓ 与下钻走这个顺序:**只含展开的组**(折叠的行不在 DOM 里,方向键别停过去)。 */
|
|
10
10
|
readonly ordered: readonly TrashEntryLike[];
|
|
11
11
|
readonly allCollapsed: boolean;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
/** 方法一律写成**属性声明**:面板会把它们摘下来传给导航/行组件,实现体也都不读 `this`。
|
|
13
|
+
* 方法简写带来的隐式 `this: TrashSelection` 会让 `unbound-method` 误报,且会诱导调用点
|
|
14
|
+
* 为了消警报去包箭头函数——那会让 `TrashSelection` 每次渲染换新身份(见 ADR 外的回归教训)。 */
|
|
15
|
+
isCollapsed: (projectDir: string) => boolean;
|
|
16
|
+
enterSelect: () => void;
|
|
17
|
+
exitSelect: () => void;
|
|
18
|
+
toggleGroup: (projectDir: string) => void;
|
|
19
|
+
toggleAllGroups: () => void;
|
|
20
|
+
toggleCheck: (entryId: string) => void;
|
|
18
21
|
/** 组头那颗:说的是"这个项目的全部会话",折叠起来的条目也算。勾满再点 = 整组取消。 */
|
|
19
|
-
toggleGroupCheck(group: {
|
|
22
|
+
toggleGroupCheck: (group: {
|
|
20
23
|
entries: readonly TrashEntryLike[];
|
|
21
|
-
})
|
|
22
|
-
groupFullyChecked(group: {
|
|
24
|
+
}) => void;
|
|
25
|
+
groupFullyChecked: (group: {
|
|
23
26
|
entries: readonly TrashEntryLike[];
|
|
24
|
-
})
|
|
25
|
-
groupPartiallyChecked(group: {
|
|
27
|
+
}) => boolean;
|
|
28
|
+
groupPartiallyChecked: (group: {
|
|
26
29
|
entries: readonly TrashEntryLike[];
|
|
27
|
-
})
|
|
30
|
+
}) => boolean;
|
|
28
31
|
}
|
|
29
32
|
export declare function useTrashSelection({ entries, groups, }: {
|
|
30
33
|
entries: readonly TrashEntryLike[] | null;
|
|
@@ -1,52 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 逐条 `/apply`
|
|
2
|
+
* 逐条 `/apply` 的写入座位:一次写入发生在哪个界面位置,就在哪个函数里绑定呈现材质、闸与重读通道。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 收尾顺序(`write-settlement.ts`,ADR-0013)与重读策略(`use-trash-query.ts`,ADR-0016)不动;
|
|
4
|
+
* 收尾顺序住 `write-settlement.ts`(ADR-0013),面板的重读策略住 `use-trash-query.ts`;
|
|
6
5
|
* 座位只拥有「这次是谁在写、交哪些材质、闸在哪」。
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* 边界:不自己判读回执(verdict 判读住 `receipt.ts`,失败表怎么上屏归各写入面——撤销那一趟的
|
|
8
|
+
* 横幅改写住 `restoreFromUndo`)、不决定收尾顺序、不拥有各面的本地状态;面板座位的闸由面板传入,
|
|
9
|
+
* 不另造第二枚;闸挡回来的那一趟**什么都不落地**——座位交回 `undefined`,不伪造 outcome,
|
|
10
|
+
* 收尾留给在飞的那一趟。
|
|
11
|
+
* 无主子会话清理**不是**座位:它只在插件设置页的维护卡里手动触发(ADR-0021),
|
|
12
|
+
* 读数、闸与重查都归 `use-maintenance.ts`。
|
|
10
13
|
*/
|
|
14
|
+
import type { Translate } from './copy.js';
|
|
11
15
|
import type { BusyGate } from './busy-gate.js';
|
|
12
16
|
import type { OneShotDeps, TrashEntryLike } from './remote.js';
|
|
17
|
+
import { type UndoNotice } from './undo-notices.js';
|
|
13
18
|
import { type WriteOutcome } from './write.js';
|
|
14
|
-
/** 会话行菜单的单删座位:一条会话、`single` 读法、成功发单条撤销横幅。交回这条会话的失败原文。
|
|
19
|
+
/** 会话行菜单的单删座位:一条会话、`single` 读法、成功发单条撤销横幅。交回这条会话的失败原文。
|
|
20
|
+
* 三种形状各有意思,不许互相冒充:字符串 = 这一条失败了(原文);`null` = 跑了、这一条没有失败要说;
|
|
21
|
+
* `undefined` = 闸把这一趟挡回来了、什么都没跑(框不收,等在飞那一趟的结论——先收就会把它的失败原文
|
|
22
|
+
* 落在已经卸载的确认框上)。 */
|
|
15
23
|
export declare function deleteSessionFromMenu(deps: OneShotDeps, input: {
|
|
16
24
|
sessionId: string;
|
|
17
25
|
title: string;
|
|
18
|
-
}, gate: BusyGate): Promise<string | null>;
|
|
26
|
+
}, gate: BusyGate): Promise<string | null | undefined>;
|
|
19
27
|
/** 批量删除座位(宿主会话列表的多选 → 批量确认框):一次 `/apply`,撤销名单只收 ok 支的条目 id(跟着组走的幂等条不单列)。
|
|
20
|
-
* 只收 id
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
* 只收 id:标题是浮条的呈现,不参与这一次写入。**被闸挡回时交回 `undefined`**——这一趟没跑,
|
|
29
|
+
* 浮条与确认框都不许照着它收缩名单或关框(那会吞掉在飞那一趟的结果)。 */
|
|
30
|
+
export declare function deleteSessionsFromBatch(deps: OneShotDeps, ids: readonly string[], gate: BusyGate): Promise<ReadonlyMap<string, string> | undefined>;
|
|
31
|
+
/** 外部恢复座位:拥有整趟——ids 组装、runWrite、三种回执形状各改写一次横幅、成功收自己。
|
|
32
|
+
* 闸在调用方(横幅组件每条通知一枚);座位不传闸(双套会让外层 busy 提前落)。
|
|
33
|
+
* 单条与批量都走**一次** `applyOutcomes('restore', ids)`(`runWrite` 判读;单条带 `single: true`,
|
|
34
|
+
* null 是协议错);失败就把原因换到同一条横幅上,不静默。多条逐条失败时横幅要说清**条数与各条
|
|
35
|
+
* 原因**(原因去重)——只显第一条会把条数与其余原因折没(issue #8 第 5 条);单条失败仍原文上屏。
|
|
36
|
+
* settlement 负责重开删除时被关掉的会话(只认 main-view 自己记过的)并让清单重读;
|
|
37
|
+
* 座位**不传 `dismissUndo`**——部分失败的回滚会让 settlement 先熄灭横幅,随后 `failNotice` 因
|
|
38
|
+
* `ownsNotice` 落空而吞掉失败原文。 */
|
|
39
|
+
export declare function restoreFromUndo(deps: OneShotDeps, notice: UndoNotice, t: Translate): Promise<void>;
|
|
27
40
|
/** 面板两个 `/apply` 座位共用的那一半:依赖、条目 id、闸、重读与缓存失效。 */
|
|
28
41
|
interface PanelWriteInput<A extends 'restore' | 'purge'> {
|
|
29
42
|
deps: OneShotDeps;
|
|
30
43
|
ids: readonly string[];
|
|
31
44
|
gate: BusyGate;
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
/** 属性声明:这两枚回调被摘下来交给 `runWrite`(转交而不是当方法调),实现不读 `this`。 */
|
|
46
|
+
refreshAfterWrite: (outcome: WriteOutcome<A>) => Promise<void>;
|
|
47
|
+
clearDetailCache: (ids: readonly string[]) => void;
|
|
34
48
|
}
|
|
35
49
|
/** 面板恢复另要两样:单条读法,以及 already-gone 回执缺行时反查 sessionId 的当前清单。 */
|
|
36
50
|
interface PanelRestoreInput extends PanelWriteInput<'restore'> {
|
|
37
51
|
single?: boolean;
|
|
38
52
|
entries: readonly TrashEntryLike[] | null;
|
|
39
53
|
}
|
|
40
|
-
/** 面板恢复座位:面板已替这条完成「回来」的结算 ⇒ `panelSeat`;撤销横幅与详情缓存都按落地条目收。
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
ids: readonly string[];
|
|
47
|
-
gate: BusyGate;
|
|
48
|
-
refreshAfterWrite(outcome: WriteOutcome<'orphan-clean'>): Promise<void>;
|
|
49
|
-
}
|
|
50
|
-
/** 无主子会话清理座位:不碰回收站失效与撤销,回执判读仍归 `use-trash-query.ts`。 */
|
|
51
|
-
export declare function cleanOrphansFromPanel(input: OrphanCleanSeatInput): Promise<WriteOutcome<'orphan-clean'>>;
|
|
54
|
+
/** 面板恢复座位:面板已替这条完成「回来」的结算 ⇒ `panelSeat`;撤销横幅与详情缓存都按落地条目收。
|
|
55
|
+
* 闸被面板那一趟占着时交回 `undefined`(连点不发第二条),面板照它什么都不改。 */
|
|
56
|
+
export declare function restoreFromPanel(input: PanelRestoreInput): Promise<WriteOutcome<'restore'> | undefined>;
|
|
57
|
+
/** 面板彻底删除座位:永久删除也让指向这些条目的撤销横幅熄灭(settlement 的 purge 支负责)。
|
|
58
|
+
* 与恢复座位同一条:闸被占着时交回 `undefined`,这一趟不改任何界面后果。 */
|
|
59
|
+
export declare function purgeFromPanel(input: PanelWriteInput<'purge'>): Promise<WriteOutcome<'purge'> | undefined>;
|
|
52
60
|
export {};
|