dsh-notify-me 1.10.4 → 1.10.5
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/CHANGELOG.md +10 -0
- package/README.en.md +5 -5
- package/README.md +5 -5
- package/lib/client.js +43 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **dsh-notify-me** are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.10.5] — 2026-10-21
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
|
|
9
|
+
- **桌面端窗口被遮住时「回复完成」不提醒**:本插件判断「你离开了」只看 `document.hidden` / `visibilityState`,而桌面壳里把 DSH 窗口切到别的应用后面、或被别的窗口盖住时,页面依然是 `visible` —— 只有最小化或整窗被遮挡才会变成 `hidden`。于是「只在后台提醒」的回复完成提醒在窗口只是被盖住时被静默丢弃(1.10.5 之前只在真正最小化时才响)。现在把窗口焦点也算进「离开」:页面失焦即视为后台,失焦瞬间同样补发此前因为「就在你眼前」而被压下的审批提醒;窗口回到前台后照常安静。设置页三个相关开关的文案同步改为「窗口在前台时也提醒」,说明里点明「切走 / 被遮挡 / 最小化」都算后台。
|
|
10
|
+
|
|
11
|
+
### 测试
|
|
12
|
+
|
|
13
|
+
- 冒烟新增 `awayWithoutHiding` 用例:焦点在时回复完成静默、失焦后同一页发出提醒、回焦再次静默、`visibilityState` 全程保持 `visible`、失焦时补发被压下的审批提醒。
|
|
14
|
+
|
|
5
15
|
## [1.10.4] — 2026-10-21
|
|
6
16
|
|
|
7
17
|
### 新增
|
package/README.en.md
CHANGED
|
@@ -75,7 +75,7 @@ The Electron application manages the `desktop` profile. Do not change the Web co
|
|
|
75
75
|
|
|
76
76
|
1. Click once in the DSH page and allow notifications when prompted. If you previously declined, allow them in the browser's site settings. The operating system must also allow notifications from the browser / DSH Desktop.
|
|
77
77
|
2. Open **Settings → Notify me**. Confirm that the section and plugin version at its foot appear, and leave the master switch, the alert type on system notifications, and sound enabled.
|
|
78
|
-
3. Click **Test "reply finished"** on the settings page. A test notification should appear and sound according to your cue settings. This local test does not forward to external endpoints and ignores the "while the
|
|
78
|
+
3. Click **Test "reply finished"** on the settings page. A test notification should appear and sound according to your cue settings. This local test does not forward to external endpoints and ignores the "while the window is in front" toggle.
|
|
79
79
|
|
|
80
80
|
Web users can also test approval buttons. On Desktop the shell cannot register a Service Worker, so this test draws an in-page card with Approve / Reject in the window corner (since 1.10.4; earlier versions sent a plain notification).
|
|
81
81
|
|
|
@@ -110,7 +110,7 @@ dsh-notify-me decouples **supervision** from **sitting in front of the screen**:
|
|
|
110
110
|
|
|
111
111
|
**Input needed** covers approval requests, plan review, and questions (`ask_user_question`). Approvals carry Approve / Reject: on Web as a system notification with buttons, on Desktop (which cannot register a Service Worker) as a card drawn in the window corner.
|
|
112
112
|
|
|
113
|
-
**Reply finished** also covers background sessions. A finished but unread session keeps the `✅ Reply finished ·` title marker until opened. Title markers are independent of the "while the
|
|
113
|
+
**Reply finished** also covers background sessions. A finished but unread session keeps the `✅ Reply finished ·` title marker until opened. Title markers are independent of the "while the window is in front" toggles.
|
|
114
114
|
|
|
115
115
|
> **Background** subagent child sessions are **not** alerted about by default: DSH lists each of them as its own session, but they are steps inside the parent conversation's turn, so an alert for them is only noise. The subagent session you have open is not part of this and alerts as usual. Settings → "Ignore subagent sessions" turns the mute off.
|
|
116
116
|
|
|
@@ -143,9 +143,9 @@ The overlay only knows which screen the window is on, not which screen you are l
|
|
|
143
143
|
|
|
144
144
|
### When to alert
|
|
145
145
|
|
|
146
|
-
- **Also alert "needs you" while the
|
|
147
|
-
- **Stay quiet for the conversation on screen** (on): a wait belonging to the conversation you are looking at keeps only the tab marker so the approval card stays readable;
|
|
148
|
-
- **Also alert "reply finished" while the
|
|
146
|
+
- **Also alert "needs you" while the window is in front** (on): turn it off to hear only once the window goes to the background — another app focused, the window covered, or minimized all count;
|
|
147
|
+
- **Stay quiet for the conversation on screen** (on): a wait belonging to the conversation you are looking at keeps only the tab marker so the approval card stays readable; moving the window to the background restores alerts;
|
|
148
|
+
- **Also alert "reply finished" while the window is in front** (off): by default only background finishes alert (a covered Desktop window counts as background since 1.10.5, not only a minimized one);
|
|
149
149
|
- **Ignore subagent sessions** (on): skip background sessions spawned by a subagent — the parent conversation covers them; the one you have open still alerts;
|
|
150
150
|
- **Click a toast to open that conversation** (on): the click switches to the conversation that raised it; in a browser it also brings the window forward, while on the Desktop shell it is flaky — sometimes the window comes forward, sometimes only the conversation switches (see [How the Desktop window gets raised](#how-the-desktop-window-gets-raised)); with several tabs open only one is raised, and off means a click does nothing.
|
|
151
151
|
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ dsh plugin --profile web add dsh-notify-me
|
|
|
75
75
|
|
|
76
76
|
1. 在 DSH 页面上点击一次,按提示允许通知;若此前拒绝过,在浏览器站点设置中允许通知。操作系统也需要允许对应浏览器 / DSH Desktop 显示通知。
|
|
77
77
|
2. 打开 **设置 → 通知提醒**,确认出现该分区及底部插件版本号,保持「启用提醒」「提示音」开启,通知类型先留「系统通知」。
|
|
78
|
-
3.
|
|
78
|
+
3. 点击设置页的「测试『回复完成』」按钮:应出现一条测试通知,并按当前音效设置播放声音。这个本地测试不会转发到外部通知端点,也不受「窗口在前台时也提醒」开关限制。
|
|
79
79
|
|
|
80
80
|
Web 用户可再测试审批按钮。桌面端拿不到 Service Worker,这条测试会在窗口角落画一张带「同意 / 拒绝」的卡片(1.10.4 起;之前的版本这里只发普通通知)。
|
|
81
81
|
|
|
@@ -106,7 +106,7 @@ dsh-notify-me 把「监督」和「守在屏幕前」解耦:只在真的出现
|
|
|
106
106
|
|
|
107
107
|
**需要你操作**包括审批请求、方案待确认(plan review)和提问(`ask_user_question`)。审批带「同意 / 拒绝」:Web 走带按钮的系统通知,桌面端(注册不了 Service Worker)改画在窗口角落的卡片上。
|
|
108
108
|
|
|
109
|
-
**回复完成**也覆盖后台会话;完成但还没看时,标题带 `✅ 回复完成 ·`
|
|
109
|
+
**回复完成**也覆盖后台会话;完成但还没看时,标题带 `✅ 回复完成 ·` 标记,打开对应会话即撤。标题标记不受「窗口在前台时也提醒」开关限制。
|
|
110
110
|
|
|
111
111
|
> **后台**子代理(subagent)子会话的等待与完成默认**不提醒**:DSH 把每个子代理子会话列成独立会话,但它们是所属主对话那一轮里的步骤,提醒只会是噪音。你当前打开的那个子代理会话不算在内,照常提醒。设置页「子代理会话不提醒」可关掉这个静音。
|
|
112
112
|
|
|
@@ -139,9 +139,9 @@ Windows 的系统通知横幅固定画在主屏上,系统没有设置项、浏
|
|
|
139
139
|
|
|
140
140
|
### 什么时候提醒
|
|
141
141
|
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
142
|
+
- **窗口在前台时也提醒「需要你」**(默认开):窗口在前台也提醒;关掉后只有窗口转到后台才提醒——切到别的应用、被别的窗口遮住、最小化都算后台;
|
|
143
|
+
- **当前对话不弹通知**(默认开):等待就发生在你正看着的对话里时只留标签页标记,免得挡住审批卡片;窗口转到后台后照常提醒,若你已处理掉就作废;
|
|
144
|
+
- **窗口在前台时也提醒「回复完成」**(默认关):默认只在窗口转到后台时提醒,避免打扰(桌面端窗口被遮住也算后台,1.10.5 起不再要求最小化);
|
|
145
145
|
- **子代理会话不提醒**(默认开):跳过后台子代理(subagent)会话——它们是主对话那一轮的步骤,完成由主对话自己的提醒覆盖;你当前打开的那个子代理会话照常提醒;
|
|
146
146
|
- **点击通知回到对应对话**(默认开):点通知切到提醒所属的对话;浏览器里同时把窗口带到前台;桌面端不稳定——有时窗口会上前,有时只切对话(见[桌面端怎么抬窗的](#桌面端怎么抬窗的));多个标签页同时开着时只调起一个(优先当前可见的那个);关掉后点通知不做任何事。
|
|
147
147
|
|
package/lib/client.js
CHANGED
|
@@ -1392,6 +1392,25 @@
|
|
|
1392
1392
|
|
|
1393
1393
|
function hidden() { return document.hidden || document.visibilityState === "hidden"; }
|
|
1394
1394
|
|
|
1395
|
+
// "Background" is not the same as "hidden": a desktop window sitting behind
|
|
1396
|
+
// another app, or a browser tab on a second monitor, still reports itself as
|
|
1397
|
+
// visible. Only a minimised or fully occluded window flips document.hidden,
|
|
1398
|
+
// so the reminders that are meant to reach a user who walked away stayed
|
|
1399
|
+
// silent whenever the window was merely covered. Window focus is the missing
|
|
1400
|
+
// half of the signal: an unfocused page counts as away.
|
|
1401
|
+
var pageFocused = true;
|
|
1402
|
+
try {
|
|
1403
|
+
if (typeof document.hasFocus === "function") pageFocused = document.hasFocus() !== false;
|
|
1404
|
+
} catch (e) {}
|
|
1405
|
+
function onPageFocus() { pageFocused = true; }
|
|
1406
|
+
function onPageBlur() {
|
|
1407
|
+
pageFocused = false;
|
|
1408
|
+
// Walking away is what re-arms the waits kept quiet because they belonged
|
|
1409
|
+
// to the conversation on screen; a blur alone never fires visibilitychange.
|
|
1410
|
+
try { flushQuieted(); } catch (e) {}
|
|
1411
|
+
}
|
|
1412
|
+
function away() { return hidden() || !pageFocused; }
|
|
1413
|
+
|
|
1395
1414
|
// Deliver one alert regardless of visibility rules (used by the test
|
|
1396
1415
|
// buttons); respects the master switch and permission state. The title
|
|
1397
1416
|
// marker is NOT touched here — its ownership belongs to the watchers
|
|
@@ -1417,13 +1436,13 @@
|
|
|
1417
1436
|
}
|
|
1418
1437
|
function fire(kind, title, body, isCurrent, sessionId, quick) {
|
|
1419
1438
|
if (!config.enabled) return false;
|
|
1420
|
-
if (kind === "attention" && config.attentionHiddenOnly && !
|
|
1439
|
+
if (kind === "attention" && config.attentionHiddenOnly && !away()) return false;
|
|
1421
1440
|
// The wait belongs to the conversation the user is looking at right now:
|
|
1422
1441
|
// the approval card is already on screen, so a toast would only cover the
|
|
1423
1442
|
// thing it is asking about. The caller keeps the tab marker, and
|
|
1424
1443
|
// flushQuieted() re-delivers the alert the moment the page is backgrounded.
|
|
1425
1444
|
if (kind === "attention" && quietedByVisibleSession(isCurrent)) return false;
|
|
1426
|
-
if (kind === "done" && config.doneHiddenOnly && !
|
|
1445
|
+
if (kind === "done" && config.doneHiddenOnly && !away()) return false;
|
|
1427
1446
|
deliver(kind, title, body, sessionId, quick);
|
|
1428
1447
|
// The alert reached the user locally (or would have, had the tab a
|
|
1429
1448
|
// voice): mirror the same copy to the outside world. Fire-and-forget —
|
|
@@ -1435,7 +1454,7 @@
|
|
|
1435
1454
|
// session already on screen. Kept separate from fire() so the caller can
|
|
1436
1455
|
// queue exactly this case and nothing else.
|
|
1437
1456
|
function quietedByVisibleSession(isCurrent) {
|
|
1438
|
-
return !!(isCurrent && config.currentHiddenOnly && !
|
|
1457
|
+
return !!(isCurrent && config.currentHiddenOnly && !away());
|
|
1439
1458
|
}
|
|
1440
1459
|
// Queued copies of the alerts that rule suppressed. Delivered by key so a
|
|
1441
1460
|
// wait that got answered while the user was still on the page never fires.
|
|
@@ -1443,7 +1462,7 @@
|
|
|
1443
1462
|
if (key && copy) quietedAttention[key] = copy;
|
|
1444
1463
|
}
|
|
1445
1464
|
function flushQuieted() {
|
|
1446
|
-
if (!config.enabled || !
|
|
1465
|
+
if (!config.enabled || !away()) return;
|
|
1447
1466
|
var keys = Object.keys(quietedAttention);
|
|
1448
1467
|
for (var i = 0; i < keys.length; i++) {
|
|
1449
1468
|
var copy = quietedAttention[keys[i]];
|
|
@@ -2047,7 +2066,7 @@
|
|
|
2047
2066
|
});
|
|
2048
2067
|
} catch (e) {}
|
|
2049
2068
|
// keep in sync with package.json "version" on every release
|
|
2050
|
-
api.version = "1.10.
|
|
2069
|
+
api.version = "1.10.5";
|
|
2051
2070
|
api.setConfig = function (patch) { return setConfigLocal(patch); };
|
|
2052
2071
|
api.resetConfig = function () {
|
|
2053
2072
|
try {
|
|
@@ -2149,6 +2168,8 @@
|
|
|
2149
2168
|
actionKeys: Object.keys(pendingActions),
|
|
2150
2169
|
permission: ("Notification" in window) ? Notification.permission : "n/a",
|
|
2151
2170
|
visibility: hidden() ? "hidden" : "visible",
|
|
2171
|
+
focused: pageFocused,
|
|
2172
|
+
away: away(),
|
|
2152
2173
|
uiSession: uiPending ? "bound" : "unbound",
|
|
2153
2174
|
uiSessionNote: uiBindNote,
|
|
2154
2175
|
uiSessionSource: uiSource,
|
|
@@ -2249,12 +2270,12 @@
|
|
|
2249
2270
|
externalCountFailed: "失败 ",
|
|
2250
2271
|
externalNoTargets: "先添加至少一个推送目标。",
|
|
2251
2272
|
externalOffHint: "先打开「转发外部通知」。",
|
|
2252
|
-
attentionVisible: "
|
|
2253
|
-
attentionVisibleHint: "
|
|
2273
|
+
attentionVisible: "窗口在前台时也提醒「需要你」",
|
|
2274
|
+
attentionVisibleHint: "窗口在前台也提醒。关掉后只在窗口转到后台(切走、被遮挡或最小化)时提醒。",
|
|
2254
2275
|
currentQuiet: "当前对话不弹通知",
|
|
2255
|
-
currentQuietHint: "
|
|
2256
|
-
doneVisible: "
|
|
2257
|
-
doneVisibleHint: "
|
|
2276
|
+
currentQuietHint: "等待就发生在你正看着的对话里时只留标签页标记,免得挡住审批卡片;窗口转到后台后照常提醒。",
|
|
2277
|
+
doneVisible: "窗口在前台时也提醒「回复完成」",
|
|
2278
|
+
doneVisibleHint: "窗口在前台也提醒。默认只在窗口转到后台时提醒,避免打扰。",
|
|
2258
2279
|
subagentQuiet: "子代理会话不提醒",
|
|
2259
2280
|
subagentQuietHint: "跳过后台子代理会话(结果由所属主对话的提醒覆盖);你正打开的那个照常提醒。",
|
|
2260
2281
|
autoFocus: "点击通知回到对应对话",
|
|
@@ -2379,12 +2400,12 @@
|
|
|
2379
2400
|
externalCountFailed: "failed ",
|
|
2380
2401
|
externalNoTargets: "Add at least one push target first.",
|
|
2381
2402
|
externalOffHint: "Turn on \"Forward to external targets\" first.",
|
|
2382
|
-
attentionVisible: "Also alert \"needs you\" while the
|
|
2383
|
-
attentionVisibleHint: "Alert even while the
|
|
2403
|
+
attentionVisible: "Also alert \"needs you\" while the window is in front",
|
|
2404
|
+
attentionVisibleHint: "Alert even while the window has focus. Turn off to hear only once the window goes to the background (another app, covered, or minimised).",
|
|
2384
2405
|
currentQuiet: "Stay quiet for the conversation on screen",
|
|
2385
|
-
currentQuietHint: "A wait belonging to the conversation on screen keeps only the tab marker, so the approval card stays readable;
|
|
2386
|
-
doneVisible: "Also alert \"reply finished\" while the
|
|
2387
|
-
doneVisibleHint: "Alert even while the
|
|
2406
|
+
currentQuietHint: "A wait belonging to the conversation on screen keeps only the tab marker, so the approval card stays readable; moving the window to the background restores alerts.",
|
|
2407
|
+
doneVisible: "Also alert \"reply finished\" while the window is in front",
|
|
2408
|
+
doneVisibleHint: "Alert even while the window has focus. By default only finishes in the background alert.",
|
|
2388
2409
|
subagentQuiet: "Ignore subagent sessions",
|
|
2389
2410
|
subagentQuietHint: "Skip sessions spawned by a subagent (the parent conversation covers them); the one you have open still alerts.",
|
|
2390
2411
|
autoFocus: "Click a toast to open that conversation",
|
|
@@ -3381,6 +3402,13 @@
|
|
|
3381
3402
|
var onVisibility = function () { try { flushQuieted(); } catch (e) {} };
|
|
3382
3403
|
try { document.addEventListener("visibilitychange", onVisibility); } catch (e) {}
|
|
3383
3404
|
unsubs.push(function () { try { document.removeEventListener("visibilitychange", onVisibility); } catch (e) {} });
|
|
3405
|
+
// Same re-arm for the other half of "went away": losing window focus.
|
|
3406
|
+
try { window.addEventListener("focus", onPageFocus); } catch (e) {}
|
|
3407
|
+
try { window.addEventListener("blur", onPageBlur); } catch (e) {}
|
|
3408
|
+
unsubs.push(function () {
|
|
3409
|
+
try { window.removeEventListener("focus", onPageFocus); } catch (e) {}
|
|
3410
|
+
try { window.removeEventListener("blur", onPageBlur); } catch (e) {}
|
|
3411
|
+
});
|
|
3384
3412
|
// Quick-decision bridge: register the worker half of this bundle (a
|
|
3385
3413
|
// no-op where quickActions is off or a worker cannot run) and start
|
|
3386
3414
|
// listening for toast-button relays.
|