@takboo/dsh-session-bin 0.1.1 → 0.2.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/README.md CHANGED
@@ -6,19 +6,19 @@
6
6
 
7
7
  ## 功能
8
8
 
9
- - 按会话名称及工作区元数据搜索,按工作区筛选。
9
+ - 默认按工作区分组;按会话名称及工作区元数据搜索、筛选。
10
10
  - 单项或批量取消归档,让会话回到原生会话列表。
11
11
  - 单项永久删除、固定选择的批量永久删除,以及清空点击时的全部归档。
12
- - 删除前展示确认和阻止原因,删除后显示逐项结果;中断或断线后可查询结果并明确继续。
12
+ - 简洁的删除确认,可在设置中全局关闭;批量操作显示进度和日志,完成后保留简短统计及失败项。中断或断线后可查询结果并明确继续。
13
13
  - 中英文界面,使用宿主控件、浅色和深色主题。
14
14
 
15
- 当前版本为 `0.1.1`,包名为 `@takboo/dsh-session-bin`。GitHub Release 提供预编译 tarball;npm 通过 trusted publishing 自动发布同一份产物,dsh-market 收录另行提交。核心功能已完成跨平台验收;运行证据见 [Host 验证](docs/verification/host-lifecycle.md#跨平台生产删除资格晋级验证)和[客户端验证](docs/verification/client-interface.md#跨平台生产删除客户端验证)。
15
+ 当前版本为 `0.2.0`,包名为 `@takboo/dsh-session-bin`。GitHub Release 提供预编译 tarball;npm 通过 trusted publishing 自动发布同一份产物,dsh-market 收录另行提交。核心功能已完成跨平台验收;运行证据见 [Host 验证](docs/verification/host-lifecycle.md#跨平台生产删除资格晋级验证)和[客户端验证](docs/verification/client-interface.md#跨平台生产删除客户端验证)。
16
16
 
17
17
  ## 界面预览
18
18
 
19
- ![原生归档管理与批量选择](https://raw.githubusercontent.com/takboo/dsh-session-bin/v0.1.0/docs/images/archives-light.png)
19
+ ![原生归档管理与批量选择](https://raw.githubusercontent.com/takboo/dsh-session-bin/v0.2.0/docs/images/archives-light.png)
20
20
 
21
- [深色界面](docs/images/archives-dark.png) · [批量永久删除确认](docs/images/batch-deletion.png)。截图来自 `0.1.0` 的真实安装验收,使用隔离测试会话。
21
+ [深色界面](docs/images/archives-dark.png) · [批量永久删除确认](docs/images/batch-deletion.png)。截图来自 `0.2.0` 的真实安装验收,使用隔离测试会话。
22
22
 
23
23
  ## 兼容性
24
24
 
@@ -38,7 +38,7 @@
38
38
 
39
39
  ```sh
40
40
  mise exec -- pnpm exec npm pack --ignore-scripts
41
- dsh plugin --profile web add ./takboo-dsh-session-bin-0.1.1.tgz
41
+ dsh plugin --profile web add ./takboo-dsh-session-bin-0.2.0.tgz
42
42
  ```
43
43
 
44
44
  以上命令使用已安装的 DSH `0.2.0-rc.2`,将完整插件 bundle 安装到 `web` profile;该路径已通过真实 CLI/GUI 验证。启动或重新启动该 profile 后,从侧栏打开“会话回收站”(Session Bin)。tarball 包含预编译 Host 和 Client,使用者安装时无需编译 TypeScript。
@@ -49,7 +49,7 @@ dsh plugin --profile web add ./takboo-dsh-session-bin-0.1.1.tgz
49
49
  dsh plugin --profile web remove @takboo/dsh-session-bin
50
50
  ```
51
51
 
52
- 也可下载 [v0.1.1 Release](https://github.com/takboo/dsh-session-bin/releases/tag/v0.1.1) 中的 `dsh-session-bin.tgz`,通过同一个 `dsh plugin --profile web add` 命令安装。也可从 npm 安装:`dsh plugin --profile web add @takboo/dsh-session-bin@0.1.1`。
52
+ 也可下载 [v0.2.0 Release](https://github.com/takboo/dsh-session-bin/releases/tag/v0.2.0) 中的 `dsh-session-bin.tgz`,通过同一个 `dsh plugin --profile web add` 命令安装。也可从 npm 安装:`dsh plugin --profile web add @takboo/dsh-session-bin@0.2.0`。
53
53
 
54
54
  如安装过早期未加 scope 的开发包,先从同一 profile 卸载 `dsh-session-bin`,再安装 scoped 包,避免重复注册;原生归档和已有操作记录保留。分发契约见[发布文档](docs/release.md)。
55
55
 
@@ -63,8 +63,8 @@ dsh plugin --profile web remove @takboo/dsh-session-bin
63
63
 
64
64
  1. 使用 Harness 原生“归档会话”操作归档目标会话。
65
65
  2. 打开“会话回收站”,搜索或筛选已有归档;选择单项或多项取消归档。
66
- 3. 永久删除时,先核对确认窗口中的对象、范围和阻止原因,再明确确认执行。
67
- 4. 如出现部分失败或连接中断,查看逐项结果,检查操作状态后再决定是否继续。
66
+ 3. 永久删除时,核对确认窗口中的对象和阻止原因,再确认执行。设置中的“永久删除会话前进行确认”默认开启;关闭后,点击单项删除、删除所选或清空将直接开始永久删除。
67
+ 4. 批量操作期间查看进度和日志,完成后只保留统计及需要处理的项。如出现部分失败或连接中断,先检查操作状态,再决定是否继续。
68
68
 
69
69
  **“清空全部归档”包含点击时的全部归档,搜索和工作区筛选不会缩小其范围。** 批量删除固定开始时的对象,后来新增的归档不会加入。
70
70
 
@@ -637,10 +637,11 @@ function frozenPurgeKey(plan) {
637
637
  ]);
638
638
  }
639
639
  var SessionBinClientModel = class {
640
- constructor(api, createStream, cache) {
640
+ constructor(api, createStream, cache, preferences) {
641
641
  this.api = api;
642
642
  this.createStream = createStream;
643
643
  this.cache = cache;
644
+ this.preferences = preferences;
644
645
  try {
645
646
  this.state = { ...this.state, pending: pendingPlans(cache?.load()) };
646
647
  } catch {
@@ -696,7 +697,12 @@ var SessionBinClientModel = class {
696
697
  }
697
698
  const purgeCacheBlocked = Boolean(cache?.isPurgeCacheBlocked?.()) || purgeCacheOverflow(rawPurgePlans, rawPurgeGrants, rawPurgeObservations, rawPurgeBatchOperations);
698
699
  this.state = { ...this.state, purgeCacheBlocked };
700
+ try {
701
+ this.state.confirmDeletion = preferences?.load() !== false;
702
+ } catch {
703
+ }
699
704
  this.snapshot = structuredClone(this.state);
705
+ this.stopPreferences = preferences?.subscribe?.((confirmDeletion) => this.publish({ confirmDeletion }));
700
706
  }
701
707
  state = {
702
708
  phase: "loading",
@@ -711,7 +717,8 @@ var SessionBinClientModel = class {
711
717
  purgeResults: [],
712
718
  purgeBatch: null,
713
719
  purgeBatchOperationIds: [],
714
- purgeCacheBlocked: false
720
+ purgeCacheBlocked: false,
721
+ confirmDeletion: true
715
722
  };
716
723
  snapshot = structuredClone(this.state);
717
724
  listeners = /* @__PURE__ */ new Set();
@@ -733,6 +740,14 @@ var SessionBinClientModel = class {
733
740
  purgeBatch = null;
734
741
  purgeBatchRun = null;
735
742
  purgePreparationEpoch = 0;
743
+ stopPreferences;
744
+ setConfirmDeletion(confirmDeletion) {
745
+ try {
746
+ this.preferences?.save(confirmDeletion);
747
+ } catch {
748
+ }
749
+ this.publish({ confirmDeletion });
750
+ }
736
751
  getSnapshot = () => this.snapshot;
737
752
  subscribe = (listener) => {
738
753
  this.listeners.add(listener);
@@ -781,6 +796,7 @@ var SessionBinClientModel = class {
781
796
  })();
782
797
  }
783
798
  async dispose() {
799
+ this.stopPreferences?.();
784
800
  this.lifetime.abort();
785
801
  ++this.epoch;
786
802
  await this.stream?.dispose();
@@ -929,6 +945,25 @@ var SessionBinClientModel = class {
929
945
  return { plan: null, reason: "connection-failed" };
930
946
  }
931
947
  }
948
+ /** Only a fresh user click can opt out of the presentation confirmation. */
949
+ async requestPurge(entry, title) {
950
+ const skip = !this.state.confirmDeletion;
951
+ const epoch = this.epoch;
952
+ const plan = await this.preparePurge(entry, title);
953
+ if (skip && !this.state.confirmDeletion && epoch === this.epoch && plan && this.confirmation?.plan.operationId === plan.operationId) {
954
+ this.acknowledgePurge(true);
955
+ await this.confirmPurge();
956
+ }
957
+ }
958
+ async requestPurgeBatch(scope, titles = {}) {
959
+ const skip = !this.state.confirmDeletion;
960
+ const epoch = this.epoch;
961
+ const batch = await this.preparePurgeBatch(scope, titles);
962
+ if (skip && !this.state.confirmDeletion && epoch === this.epoch && batch?.phase === "confirming" && this.purgeBatch?.batchId === batch.batchId && batch.items.some((item) => item.state === "ready")) {
963
+ this.acknowledgePurgeBatch(true);
964
+ await this.runPurgeBatch();
965
+ }
966
+ }
932
967
  async preparePurge(entry, title) {
933
968
  const target = { sessionId: entry.sessionId, entryId: entry.entryId, title };
934
969
  if (this.rejectPurgeCacheCapacity() || this.state.phase !== "ready" || this.state.busy.includes(target.sessionId) || this.confirmation || this.hasActivePurgeBatch() || this.state.purgePending.length > 0 || this.state.pending.some((plan) => plan.schemaVersion === 2 && plan.sessionId === target.sessionId) || this.lifetime.signal.aborted) return null;
@@ -1666,8 +1701,32 @@ function browserPendingCache(storage) {
1666
1701
  }
1667
1702
  };
1668
1703
  }
1704
+ function browserDeletionPreferences(storage, events) {
1705
+ const key2 = "dsh-session-bin.preferences.v1";
1706
+ const parse = (raw) => {
1707
+ try {
1708
+ const value2 = JSON.parse(raw ?? "null");
1709
+ return !(value2?.schemaVersion === 1 && value2.confirmDeletion === false);
1710
+ } catch {
1711
+ return true;
1712
+ }
1713
+ };
1714
+ return {
1715
+ load: () => parse(storage.getItem(key2)),
1716
+ save: (confirmDeletion) => storage.setItem(key2, JSON.stringify({ schemaVersion: 1, confirmDeletion })),
1717
+ subscribe: (listener) => {
1718
+ const changed = (event) => {
1719
+ const update = event;
1720
+ if (update.storageArea === storage && (update.key === key2 || update.key === null)) listener(parse(update.newValue));
1721
+ };
1722
+ events?.addEventListener("storage", changed);
1723
+ return () => events?.removeEventListener("storage", changed);
1724
+ }
1725
+ };
1726
+ }
1669
1727
  export {
1670
1728
  SessionBinClientModel,
1729
+ browserDeletionPreferences,
1671
1730
  browserPendingCache,
1672
1731
  retirementManifestDigest
1673
1732
  };