@linxin666/dsh-client-ui-task-board 0.3.1 → 0.3.3
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.i18n.yaml +2 -2
- package/README.md +6 -2
- package/README.zh.md +6 -2
- package/lib/client.js +72 -1
- package/lib/client.js.map +1 -1
- package/lib/index.js +3 -3
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/settings-form.d.ts +1 -1
- package/lib/types/client/telemetry.d.ts +26 -0
- package/lib/types/http.d.ts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/loopback.d.ts +1 -1
- package/lib/types/mount-once.d.ts +1 -1
- package/package.json +2 -4
- package/src/client/board/TaskBoard.tsx +1 -1
- package/src/client/index.ts +6 -1
- package/src/client/settings-form.ts +1 -1
- package/src/client/telemetry.ts +105 -0
- package/src/http.ts +1 -1
- package/src/index.ts +1 -1
- package/src/loopback.ts +1 -1
- package/src/mount-once.ts +2 -2
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 5d3759c240ffba90ca040961757c50e8a4aef277
|
|
6
|
+
README.zh.md: e7bac03d88d9874e9c86f83d867745651adffba7
|
package/README.md
CHANGED
|
@@ -41,8 +41,8 @@ dsh plugin --profile web add @linxin666/dsh-client-ui-task-board@latest
|
|
|
41
41
|
For local development:
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
git clone https://github.com/zhu1090093659/dsh-web
|
|
45
|
-
cd dsh-web
|
|
44
|
+
git clone https://github.com/zhu1090093659/dsh-web.git
|
|
45
|
+
cd dsh-web
|
|
46
46
|
pnpm install
|
|
47
47
|
pnpm build
|
|
48
48
|
dsh plugin --profile web add link:$(pwd)/packages/dsh-task-board
|
|
@@ -113,3 +113,7 @@ Set `DSH_POWER_SMOKE=1` to opt into the native helper smoke test on Windows, mac
|
|
|
113
113
|
- Linux requires systemd-logind and policy permission for the current user to acquire an idle block lock. Containers, WSL, hosts without a system bus, and non-systemd systems may report `unsupported` or `error`. Whether a desktop also associates a logind idle lock with display idleness is desktop policy; the plugin does not request a screensaver or display inhibitor.
|
|
114
114
|
- Keeping enabled schedules armed may increase battery consumption because protection starts before their future trigger time.
|
|
115
115
|
- Host execution consumes the same API quota as an ordinary DSH agent session.
|
|
116
|
+
|
|
117
|
+
## Telemetry
|
|
118
|
+
|
|
119
|
+
The browser half sends one anonymous install heartbeat per UTC day to dsh-market.com: a random localStorage id plus this package's name, nothing else. The server stores only a salted hash of that id, never IP addresses, and exposes aggregate counts only. See [docs/telemetry.md](../../docs/telemetry.md) for the full contract.
|
package/README.zh.md
CHANGED
|
@@ -41,8 +41,8 @@ dsh plugin --profile web add @linxin666/dsh-client-ui-task-board@latest
|
|
|
41
41
|
本地开发安装:
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
git clone https://github.com/zhu1090093659/dsh-web
|
|
45
|
-
cd dsh-web
|
|
44
|
+
git clone https://github.com/zhu1090093659/dsh-web.git
|
|
45
|
+
cd dsh-web
|
|
46
46
|
pnpm install
|
|
47
47
|
pnpm build
|
|
48
48
|
dsh plugin --profile web add link:$(pwd)/packages/dsh-task-board
|
|
@@ -113,3 +113,7 @@ pnpm --filter @linxin666/dsh-client-ui-task-board build
|
|
|
113
113
|
- Linux 需要 systemd-logind 及允许当前用户取得 idle block lock 的策略;容器、WSL、无 system bus 或非 systemd 系统可能显示 `unsupported` 或 `error`。桌面环境是否把 logind idle lock 与显示器空闲联动属于其自身策略,插件不请求屏保或显示器 inhibitor。
|
|
114
114
|
- 已启用计划会从未来触发点之前持续持锁,因此可能增加电池消耗。
|
|
115
115
|
- Host 执行消耗与普通 DSH agent 会话相同的 API 额度。
|
|
116
|
+
|
|
117
|
+
## 数据遥测
|
|
118
|
+
|
|
119
|
+
浏览器半区每个 UTC 日向 dsh-market.com 发送一次匿名安装心跳:仅含一个 localStorage 随机 ID 与本包名,无其他数据。服务端只存储该 ID 的加盐哈希,不存 IP,且只暴露聚合计数。完整契约见 [docs/telemetry.md](../../docs/telemetry.md)。
|
package/lib/client.js
CHANGED
|
@@ -3298,7 +3298,7 @@ window.__ModuleLoader__.load({
|
|
|
3298
3298
|
/**
|
|
3299
3299
|
* Write every staged edit, then re-seed from what the Host accepted.
|
|
3300
3300
|
*
|
|
3301
|
-
* When the scope carries the optional batch surface (the dsh-web
|
|
3301
|
+
* When the scope carries the optional batch surface (the dsh-web
|
|
3302
3302
|
* bridge scope), every planned write rides one mutation so cross-field
|
|
3303
3303
|
* validate hooks (baseURL+model) judge the batch as a unit instead of
|
|
3304
3304
|
* deadlocking on per-field writes. Otherwise the per-field loop runs.
|
|
@@ -3668,6 +3668,76 @@ window.__ModuleLoader__.load({
|
|
|
3668
3668
|
}
|
|
3669
3669
|
};
|
|
3670
3670
|
//#endregion
|
|
3671
|
+
//#region src/client/telemetry.ts
|
|
3672
|
+
const VISITOR_KEY = "dsh-web-ui-telemetry-visitor";
|
|
3673
|
+
const DAY_KEY_PREFIX = "dsh-web-ui-telemetry-day:";
|
|
3674
|
+
const ENDPOINT = "https://dsh-market.com/api/telemetry/event";
|
|
3675
|
+
/** The building package's version, when the bundle carries it. */
|
|
3676
|
+
function bakedVersion() {
|
|
3677
|
+
try {
|
|
3678
|
+
return "0.3.3";
|
|
3679
|
+
} catch {
|
|
3680
|
+
return;
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
/** Read or lazily create the anonymous visitor id; null when storage is unavailable. */
|
|
3684
|
+
function visitorId() {
|
|
3685
|
+
try {
|
|
3686
|
+
const existing = localStorage.getItem(VISITOR_KEY);
|
|
3687
|
+
if (existing && /^[A-Za-z0-9_-]{16,64}$/.test(existing)) return existing;
|
|
3688
|
+
const fresh = crypto.randomUUID().replaceAll("-", "");
|
|
3689
|
+
localStorage.setItem(VISITOR_KEY, fresh);
|
|
3690
|
+
return fresh;
|
|
3691
|
+
} catch {
|
|
3692
|
+
return null;
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
/** Drop stale per-day dedup keys so localStorage does not grow forever. */
|
|
3696
|
+
function pruneDayKeys(today) {
|
|
3697
|
+
try {
|
|
3698
|
+
for (let index = localStorage.length - 1; index >= 0; index -= 1) {
|
|
3699
|
+
const key = localStorage.key(index);
|
|
3700
|
+
if (key !== null && key.startsWith(DAY_KEY_PREFIX) && key !== DAY_KEY_PREFIX + today) localStorage.removeItem(key);
|
|
3701
|
+
}
|
|
3702
|
+
} catch {}
|
|
3703
|
+
}
|
|
3704
|
+
/**
|
|
3705
|
+
* Fire the daily heartbeat for the given items at most once per UTC day per
|
|
3706
|
+
* browser. Never throws and never blocks the caller. Items without an explicit
|
|
3707
|
+
* version inherit the bundle's baked build version.
|
|
3708
|
+
*/
|
|
3709
|
+
function reportDailyHeartbeat(items) {
|
|
3710
|
+
try {
|
|
3711
|
+
if (items.length === 0) return;
|
|
3712
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3713
|
+
if (navigator.webdriver) return;
|
|
3714
|
+
if (localStorage.getItem(DAY_KEY_PREFIX + today) !== null) return;
|
|
3715
|
+
const visitor = visitorId();
|
|
3716
|
+
if (visitor === null) return;
|
|
3717
|
+
pruneDayKeys(today);
|
|
3718
|
+
const payloadItems = items.map((item) => {
|
|
3719
|
+
const out = { name: item.name };
|
|
3720
|
+
const version = item.version ?? bakedVersion();
|
|
3721
|
+
if (version !== void 0) out.version = version;
|
|
3722
|
+
if (item.channel !== void 0) out.channel = item.channel;
|
|
3723
|
+
return out;
|
|
3724
|
+
});
|
|
3725
|
+
const body = JSON.stringify({
|
|
3726
|
+
kind: "heartbeat",
|
|
3727
|
+
visitor,
|
|
3728
|
+
items: payloadItems
|
|
3729
|
+
});
|
|
3730
|
+
fetch(ENDPOINT, {
|
|
3731
|
+
method: "POST",
|
|
3732
|
+
headers: { "content-type": "application/json" },
|
|
3733
|
+
body,
|
|
3734
|
+
keepalive: true
|
|
3735
|
+
}).then((response) => {
|
|
3736
|
+
if (response.ok) localStorage.setItem(DAY_KEY_PREFIX + today, "1");
|
|
3737
|
+
}).catch(() => {});
|
|
3738
|
+
} catch {}
|
|
3739
|
+
}
|
|
3740
|
+
//#endregion
|
|
3671
3741
|
//#region src/client/index.ts
|
|
3672
3742
|
/** Locale namespace this plugin owns. */
|
|
3673
3743
|
const NS = "task-board";
|
|
@@ -3688,6 +3758,7 @@ window.__ModuleLoader__.load({
|
|
|
3688
3758
|
* @param ctx - client root context (services: sessions, workspaces).
|
|
3689
3759
|
*/
|
|
3690
3760
|
function apply(ctx) {
|
|
3761
|
+
reportDailyHeartbeat([{ name: "@linxin666/dsh-client-ui-task-board" }]);
|
|
3691
3762
|
if (!claimTaskboardApply()) return;
|
|
3692
3763
|
ctx.effect(() => releaseTaskboardApply, "task-board: apply claim");
|
|
3693
3764
|
ctx.effect(() => {
|