dsh-notify-me 1.10.2 → 1.10.4
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 +24 -0
- package/README.en.md +16 -15
- package/README.md +19 -20
- package/lib/client.js +108 -25
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **dsh-notify-me** are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.10.4] — 2026-10-21
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
|
|
9
|
+
- **桌面端审批按钮落到页内卡片**:桌面壳在 `dsh-app:` 协议下拿不到 Service Worker(注册被拒),带按钮的审批通知因此只剩标题、点不出「同意 / 拒绝」。现在这种拿不到 SW 的情形会在窗口角落画一张卡片:审批标题与正文、`同意` / `拒绝` 两个按钮、正文过长时可就地展开「详情」,12 秒自动收起,同一条审批不叠第二张卡。按钮走的是和系统通知完全同一条裁决路径(`allowed-once` / `rejected`),裁完即撤卡。Web 端(SW 可用)行为不变,仍是带按钮的系统通知。
|
|
10
|
+
|
|
11
|
+
### 修复
|
|
12
|
+
|
|
13
|
+
- 页面里写的 `api.version` 与 `package.json` 对齐(1.10.3 的发版提交只改了 `package.json`,页内版本号停在 1.10.2,冒烟断言因此一开始就是红的)。
|
|
14
|
+
|
|
15
|
+
### 测试
|
|
16
|
+
|
|
17
|
+
- 冒烟新增 12 组断言覆盖桌面降级卡片:出现时机、两个按钮、详情展开/收起、点卡片本体不撤卡、同意、拒绝、审批从状态里消失时撤卡、同一条审批不叠卡、开关关闭时不画卡、12 秒回收、Web 路径不回归。
|
|
18
|
+
|
|
19
|
+
## [1.10.3] — 2026-10-21
|
|
20
|
+
|
|
21
|
+
### 修复
|
|
22
|
+
|
|
23
|
+
- **桌面端同类系统通知只弹第一条**(#15):普通通知的 `tag` 原本按类别固定(`dsh-notify-me-<kind>`),靠 `renotify: true` 让同 tag 的新通知替换并重新提示;Electron 不认这个标志,同 tag 的第二条被静默替换,横幅不再出现。现改为每条普通通知独立 tag(`dsh-notify-me-<kind>-<seq>-<ts>`,计数器防同毫秒碰撞)。审批通知的 tag 保持稳定,`closeNotificationTag()` 撤回逻辑不变。
|
|
24
|
+
|
|
25
|
+
### 测试
|
|
26
|
+
|
|
27
|
+
- 冒烟新增 `uniqueToastTags()` 回归用例:连发三次「回复完成」断言三条 tag 互不相同、审批 tag 前缀不变;`npm test` 两套件通过。
|
|
28
|
+
|
|
5
29
|
## [1.10.2] — 2026-10-21
|
|
6
30
|
|
|
7
31
|
### 变更
|
package/README.en.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
[](https://www.npmjs.com/package/dsh-notify-me)
|
|
14
14
|
[](LICENSE)
|
|
15
15
|
[](#installation)
|
|
16
|
-
[](https://www.npmjs.com/package/dsh-notify-me)
|
|
17
17
|
[](#compatibility)
|
|
18
18
|
[](https://awesome-dsh-plugin.com)
|
|
19
19
|
|
|
@@ -47,7 +47,7 @@ A notification plugin for DSH Web / Desktop, so you can keep full access off wit
|
|
|
47
47
|
|
|
48
48
|

|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Just the plugin panel (the real component, v1.10.2 defaults) without the DSH navigation sidebar. Alert type is a segmented control, and row explanations live in a hover tooltip that appears when the pointer rests on a title, which is why only the titles show here.
|
|
51
51
|
</details>
|
|
52
52
|
|
|
53
53
|
## Installation
|
|
@@ -74,17 +74,17 @@ The Electron application manages the `desktop` profile. Do not change the Web co
|
|
|
74
74
|
## First-use check
|
|
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
|
-
2. Open **Settings → Notify me**. Confirm that the section and plugin version at its foot appear, and leave the master switch, system notifications, and sound enabled.
|
|
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
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 page is open" toggle.
|
|
79
79
|
|
|
80
|
-
Web users can also test approval buttons. On Desktop
|
|
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
|
|
|
82
82
|
**Optional console check** — in environments with DevTools, you can also run:
|
|
83
83
|
|
|
84
84
|
```js
|
|
85
85
|
window.__dshNotifyMe.test("done") // "reply finished" sample
|
|
86
86
|
window.__dshNotifyMe.test("attention") // "needs your input" sample
|
|
87
|
-
window.__dshNotifyMe.test("approval") // Approve / Reject with an active Web bridge;
|
|
87
|
+
window.__dshNotifyMe.test("approval") // Approve / Reject with an active Web bridge; an in-page card on Desktop
|
|
88
88
|
window.__dshNotifyMe.debug() // the bridge field reports the button channel: "active" = buttons work
|
|
89
89
|
```
|
|
90
90
|
|
|
@@ -108,7 +108,7 @@ dsh-notify-me decouples **supervision** from **sitting in front of the screen**:
|
|
|
108
108
|
| 🔔 Input needed | Alerts even in the foreground; the conversation on screen keeps only a title marker |
|
|
109
109
|
| ✅ Reply finished | Alerts while the page is hidden / backgrounded |
|
|
110
110
|
|
|
111
|
-
**Input needed** covers approval requests, plan review, and questions (`ask_user_question`).
|
|
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
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 page is open" toggles.
|
|
114
114
|
|
|
@@ -123,9 +123,9 @@ Open **Settings → Notify me**. The page runs as how you get told, when to aler
|
|
|
123
123
|
- **Enable reminders**: master switch — off means no toasts, no sounds, and the tab title is left alone;
|
|
124
124
|
- **Alert type (pick one)**: one segmented control — system notifications on the left, in-page overlay on the right; whichever you pick is the only channel used;
|
|
125
125
|
- **System notifications** (default): native toasts landing in the Windows / macOS notification center; needs notification permission;
|
|
126
|
-
- **In-page overlay**: cards drawn in the page corner, on whichever display the window sits on — system notifications only land on the primary display. No permission needed, and the Desktop shell can Approve / Reject right on the card.
|
|
126
|
+
- **In-page overlay**: cards drawn in the page corner, on whichever display the window sits on — system notifications only land on the primary display. No permission needed, and the Desktop shell can Approve / Reject right on the card. With the overlay chosen, a Corner row appears; open it to pick one of four positions. See [Secondary displays and the overlay](#secondary-displays-and-the-overlay);
|
|
127
127
|
- **Sound / Volume**: the switch is direct; the slider folds into that row — click the title (▸ turns into ▾) to reveal it. What it plays comes from Advanced → Alert sound;
|
|
128
|
-
- **Decide approvals from the toast** (on by default):
|
|
128
|
+
- **Decide approvals from the toast** (on by default): approvals carry Approve / Reject that settle the request in place. On Web that is a system notification with buttons; on Desktop `dsh-app://` cannot register a Service Worker, so the buttons are drawn on a card in the window corner (auto-dismissed after 12 s, one card per approval). You can also switch the channel to the in-page overlay and decide there.
|
|
129
129
|
|
|
130
130
|
### Secondary displays and the overlay
|
|
131
131
|
|
|
@@ -133,10 +133,10 @@ Windows draws system notification banners on the primary display only. There is
|
|
|
133
133
|
|
|
134
134
|
The **in-page overlay** skips the notification center and draws the card inside the DSH page instead: wherever the window is, the card is there too.
|
|
135
135
|
|
|
136
|
-
- **Position** —
|
|
136
|
+
- **Position** — with the in-page overlay chosen, a Corner row appears showing the current value (bottom right by default); click it open (▸ turns into ▾), then pick top right / bottom right / top left / bottom left. Changes apply immediately;
|
|
137
137
|
- **No notification permission needed** — it works when permission was never granted, and on the Desktop shell where buttonless toasts are all the OS channel can do;
|
|
138
138
|
- **Approval cards carry Approve / Reject** — the same decision as Allow once / Reject on the approval card, and they work on the Desktop too (no Service Worker involved). Clicking the card body opens its conversation;
|
|
139
|
-
- **Lifetime** — "needs you"
|
|
139
|
+
- **Lifetime** — "needs you" and "reply finished" cards retire after 5s each, an approval card with buttons after 12s (system toasts use the same two numbers); a card or its close button retires one earlier. At most 4 cards stack at once;
|
|
140
140
|
- **Relation to system notifications** — it is one or the other. Both used to be switchable at once, which meant every alert arrived twice and the pair covered each other; 1.10.0 made it a single choice, and 1.10.2 turns that into one segmented row. An old config with the overlay on migrates to it.
|
|
141
141
|
|
|
142
142
|
The overlay only knows which screen the window is on, not which screen you are looking at. If the window stays on the primary display while you watch another one, it stays invisible — same as a toast.
|
|
@@ -189,7 +189,7 @@ The last block inside Advanced. The page protocol is detected automatically to t
|
|
|
189
189
|
<summary>Alert language, Desktop window raising, reset</summary>
|
|
190
190
|
|
|
191
191
|
- **Alert language**: follow the UI / Simplified Chinese / English — governs alert copy and the `🔔 …` title marker;
|
|
192
|
-
- **How the Desktop window is raised**: `window.focus()` cannot lift a native Electron window, so since 1.5.2 the page drives the app's own `dsh://open` deep link —
|
|
192
|
+
- **How the Desktop window is raised**: `window.focus()` cannot lift a native Electron window, so since 1.5.2 the page drives the app's own `dsh://open` deep link — measured working on DSH Desktop 0.2.0-rc.2, flaky on 0.2.1-rc.2 / Windows (see the next section);
|
|
193
193
|
- **Reset settings**: restores every switch and cue setting to the factory defaults (webhook targets and chosen audio files are kept).
|
|
194
194
|
|
|
195
195
|
</details>
|
|
@@ -200,8 +200,9 @@ The last block inside Advanced. The page protocol is detected automatically to t
|
|
|
200
200
|
|
|
201
201
|
## How it alerts
|
|
202
202
|
|
|
203
|
-
- **
|
|
204
|
-
- **
|
|
203
|
+
- **Alert channel (pick one — the two never run together)**:
|
|
204
|
+
- **System notification** — a toast through the browser into the Windows action center / macOS Notification Center (clicking it opens the conversation it came from; supported Web environments offer approval buttons, Desktop does not)
|
|
205
|
+
- **In-page overlay** — an alert card drawn in the corner of the DSH page, on whatever display the window is on, optionally with Approve / Reject buttons; see [Secondary displays and the overlay](#secondary-displays-and-the-overlay)
|
|
205
206
|
- **Sound** — WebAudio beeps by default (distinct patterns for "needs you" vs "done"); each kind can instead play a picked audio file, or hand the sound over to the operating system's own notification sound
|
|
206
207
|
- **Tab title marker** — while something is waiting on you, the tab title is prefixed with `🔔 Action needed · …` / `🔔 需要你 · …`; while a background session is **finished but unread**, with `✅ Reply finished · …` / `✅ 回复完成 · …`, gone once you open that session (or it starts running again). Both kinds can be up together, "needs you" first; a host title change is rebased under the markers
|
|
207
208
|
- **External notifications** (optional, default off) — the same alert is also forwarded to the push targets you configure: Discord Webhook / Bark / Gotify / custom webhook — so the push channel on your phone picks it up while you step away from the machine
|
|
@@ -214,7 +215,7 @@ Per-release adaptation records live in [package.json](package.json), under `dsh.
|
|
|
214
215
|
|
|
215
216
|
Verified to actually activate on `0.1.2-rc.1`, `0.1.5-rc.1`, `0.1.5-rc.2` and `0.2.0-rc.2` (each booted in its own profile: the plugin entry lands in the boot page's `__DSH_BOOT__` with its inject dependencies resolved, `/plugins/??dsh-notify-me/client.js&rev=…` serves a build containing the new code, and the Settings → Notifications section registers, i.e. the plugin's `apply` really runs), and previously on `0.1.1-rc.2`.
|
|
216
217
|
|
|
217
|
-
`0.2.1-rc.2` (current latest) got its own isolated run: an isolated `DSH_HOME` booting `dsh web` (70 boot entries) placed the plugin entry 59th, in the `application` batch, with all three inject targets present and ordered before it; `/plugins/??dsh-notify-me/client.js&rev=…` served the 1.7.0 source build (140,153 B); loaded in a headless Chromium page, `apply` ran — `window.__dshNotifyMe.debug()` reported `uiSession: bound`, `uiSessionSource: sessionStatus`, `bridge: active`. Host-side shapes match `0.2.0-rc.2`; no plugin code change was needed.
|
|
218
|
+
`0.2.1-rc.2` (current latest) got its own isolated run: an isolated `DSH_HOME` booting `dsh web` (70 boot entries) placed the plugin entry 59th, in the `application` batch, with all three inject targets present and ordered before it; `/plugins/??dsh-notify-me/client.js&rev=…` served the then-installed 1.7.0 source build (140,153 B); loaded in a headless Chromium page, `apply` ran — `window.__dshNotifyMe.debug()` reported `uiSession: bound`, `uiSessionSource: sessionStatus`, `bridge: active`. Host-side shapes match `0.2.0-rc.2`; no plugin code change was needed.
|
|
218
219
|
|
|
219
220
|
<details>
|
|
220
221
|
<summary>Host generations and adaptation diagnostics</summary>
|
|
@@ -298,7 +299,7 @@ The reminder core stays dependency-free and self-contained: notification copy re
|
|
|
298
299
|
|
|
299
300
|
Action buttons (`actions`) belong to persistent notifications shown through `ServiceWorkerRegistration.showNotification()`; passing `actions` to the `new Notification()` constructor throws a `TypeError`. That is a browser rule no plugin can route around, so the bundle holds two jobs in the same bytes: the page half registers the reminder factory as it always did, and the very same file is registered as a Service Worker whose only task is relaying which button was clicked back to the page. The decision itself happens in the page, through the same `PendingApproval.answer('allowed-once' | 'rejected')` the approval card uses — which is why "Approve" is exactly "Allow once" and nothing broader. The "raise a window and switch its conversation" part of a body click is scheduled on the worker half too: `client.focus()` raises exactly one window (a visible one first) and routes the conversation switch to that window alone, so several open DSH tabs never fight over focus or all switch at once.
|
|
300
301
|
|
|
301
|
-
Every button toast is booked against its interaction key, so it can only decide the request it was raised for. Once the page answers that request or a newer one replaces it, clicking the leftover buttons decides nothing and just closes the notification. Button toasts
|
|
302
|
+
Every button toast is booked against its interaction key, so it can only decide the request it was raised for. Once the page answers that request or a newer one replaces it, clicking the leftover buttons decides nothing and just closes the notification. Button toasts stay 12s (plain ones 5s) and retire on their own, so an approval left undecided there still waits for you in the page.
|
|
302
303
|
|
|
303
304
|
### How the Desktop window gets raised
|
|
304
305
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
[](https://www.npmjs.com/package/dsh-notify-me)
|
|
14
14
|
[](LICENSE)
|
|
15
15
|
[](#安装)
|
|
16
|
-
[](https://www.npmjs.com/package/dsh-notify-me)
|
|
17
17
|
[](#兼容性)
|
|
18
18
|
[](https://awesome-dsh-plugin.com)
|
|
19
19
|
|
|
@@ -26,9 +26,9 @@ DSH Web / Desktop 的通知插件,让你敢不开完整访问,也不必一
|
|
|
26
26
|
- **需要你操作时**:审批、方案确认、提问,用通知、提示音和标题标记提醒。
|
|
27
27
|
- **后台回复完成时**:及时回来查看结果,点击通知可回到对应对话。
|
|
28
28
|
- **离开电脑时**:可选转发到 Discord、Bark、Gotify 或自己的 Webhook。
|
|
29
|
-
-
|
|
29
|
+
- **不看主屏时**:把「通知类型」切成「浮层提醒」,卡片就跟着 DSH 窗口出现在你正看着的那块屏(系统通知只会出现在主屏)。
|
|
30
30
|
|
|
31
|
-
> 页面或桌面应用需保持运行,后台 / 最小化可以。系统通知需要通知权限;审批按钮在支持 Service Worker 的 Web 环境(如 `http://127.0.0.1` 或 `https
|
|
31
|
+
> 页面或桌面应用需保持运行,后台 / 最小化可以。系统通知需要通知权限;审批按钮在支持 Service Worker 的 Web 环境(如 `http://127.0.0.1` 或 `https`)由通知提供,桌面端的通知没有按钮——把「通知类型」选成「浮层提醒」后可在浮层上直接裁决(见[副屏与浮层提醒](#副屏与浮层提醒))。
|
|
32
32
|
|
|
33
33
|
> 🔎 想找这个插件?可以搜:`dsh-notify-me`、**消息提醒**、**可操作提醒**、**桌面通知**、**需要你操作**、**回复完成提醒**、**后台完成提醒**、**外部通知**、**Discord / Bark / Gotify 推送**(npm 关键词已含以上中英文词)。
|
|
34
34
|
|
|
@@ -47,7 +47,7 @@ DSH Web / Desktop 的通知插件,让你敢不开完整访问,也不必一
|
|
|
47
47
|
|
|
48
48
|

|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
只截插件自己的面板(真实组件、v1.10.2 默认配置),不带 DSH 左侧导航栏;「通知类型」是分段选择器,每行说明在鼠标停在标题文字上时才出现,所以这里只看到标题。
|
|
51
51
|
</details>
|
|
52
52
|
|
|
53
53
|
## 安装
|
|
@@ -74,17 +74,17 @@ dsh plugin --profile web add dsh-notify-me
|
|
|
74
74
|
## 首次验证
|
|
75
75
|
|
|
76
76
|
1. 在 DSH 页面上点击一次,按提示允许通知;若此前拒绝过,在浏览器站点设置中允许通知。操作系统也需要允许对应浏览器 / DSH Desktop 显示通知。
|
|
77
|
-
2. 打开 **设置 →
|
|
77
|
+
2. 打开 **设置 → 通知提醒**,确认出现该分区及底部插件版本号,保持「启用提醒」「提示音」开启,通知类型先留「系统通知」。
|
|
78
78
|
3. 点击设置页的「测试『回复完成』」按钮:应出现一条测试通知,并按当前音效设置播放声音。这个本地测试不会转发到外部通知端点,也不受「页面打开时也提醒」开关限制。
|
|
79
79
|
|
|
80
|
-
Web
|
|
80
|
+
Web 用户可再测试审批按钮。桌面端拿不到 Service Worker,这条测试会在窗口角落画一张带「同意 / 拒绝」的卡片(1.10.4 起;之前的版本这里只发普通通知)。
|
|
81
81
|
|
|
82
82
|
**控制台验证(可选)** — 支持 DevTools 的环境也可执行:
|
|
83
83
|
|
|
84
84
|
```js
|
|
85
85
|
window.__dshNotifyMe.test("done") // 「完成」示例
|
|
86
86
|
window.__dshNotifyMe.test("attention") // 「需要你」示例
|
|
87
|
-
window.__dshNotifyMe.test("approval") //
|
|
87
|
+
window.__dshNotifyMe.test("approval") // 桥可用时带「同意 / 拒绝」按钮;桌面端画在窗口角落的卡片上
|
|
88
88
|
window.__dshNotifyMe.debug() // 桥接状态看 bridge 字段,active = 按钮可用
|
|
89
89
|
```
|
|
90
90
|
|
|
@@ -104,7 +104,7 @@ dsh-notify-me 把「监督」和「守在屏幕前」解耦:只在真的出现
|
|
|
104
104
|
| 🔔 需要你操作 | 页面可见也提醒;当前对话只留标题标记 |
|
|
105
105
|
| ✅ 回复完成 | 页面隐藏 / 后台时提醒 |
|
|
106
106
|
|
|
107
|
-
**需要你操作**包括审批请求、方案待确认(plan review)和提问(`ask_user_question
|
|
107
|
+
**需要你操作**包括审批请求、方案待确认(plan review)和提问(`ask_user_question`)。审批带「同意 / 拒绝」:Web 走带按钮的系统通知,桌面端(注册不了 Service Worker)改画在窗口角落的卡片上。
|
|
108
108
|
|
|
109
109
|
**回复完成**也覆盖后台会话;完成但还没看时,标题带 `✅ 回复完成 ·` 标记,打开对应会话即撤。标题标记不受「页面打开时也提醒」开关限制。
|
|
110
110
|
|
|
@@ -119,9 +119,9 @@ dsh-notify-me 把「监督」和「守在屏幕前」解耦:只在真的出现
|
|
|
119
119
|
- **启用提醒** 总开关:关闭后不弹通知、不响提示音,也不改标签页标题;
|
|
120
120
|
- **通知类型(二选一)**:一行分段选择器,左边「系统通知」、右边「浮层提醒」,点哪个就只走哪个;
|
|
121
121
|
- **系统通知**(默认):进 Windows / macOS 通知中心,需要通知权限;
|
|
122
|
-
- **页面浮层**:在 DSH 页面角落画提醒卡片,窗口在哪块屏它就在哪块屏——系统通知只会画在主屏,主屏不看时用它;不需要通知权限,桌面端也能在卡片上直接「同意 /
|
|
122
|
+
- **页面浮层**:在 DSH 页面角落画提醒卡片,窗口在哪块屏它就在哪块屏——系统通知只会画在主屏,主屏不看时用它;不需要通知权限,桌面端也能在卡片上直接「同意 / 拒绝」。选中后卡片里会多出「浮层位置」子行,点开可选四个角落,见[副屏与浮层提醒](#副屏与浮层提醒);
|
|
123
123
|
- **提示音 / 音量**:开关直接切;音量滑块收在该行里,点一下标题(▸ 变成 ▾)展开。具体播什么由「高级设置 → 音效来源」决定;
|
|
124
|
-
-
|
|
124
|
+
- **审批通知上直接裁决**(默认开):审批带「同意 / 拒绝」,点一下即完成裁决,不用切回页面。Web 走带按钮的系统通知;桌面端 `dsh-app://` 注册不了 Service Worker,于是把按钮画在窗口角落的卡片上(12 秒自动收起,同一条审批不叠第二张卡)。也可以把「通知类型」换成「页面浮层」,改在浮层卡片上裁决。
|
|
125
125
|
|
|
126
126
|
### 副屏与浮层提醒
|
|
127
127
|
|
|
@@ -129,10 +129,10 @@ Windows 的系统通知横幅固定画在主屏上,系统没有设置项、浏
|
|
|
129
129
|
|
|
130
130
|
「页面浮层提醒」绕开系统通知中心,直接在 DSH 页面里画一张卡片:窗口在哪块屏,卡片就出现在哪块屏。
|
|
131
131
|
|
|
132
|
-
-
|
|
132
|
+
- **位置**:选中「浮层提醒」后,「浮层位置」子行出现,行上直接显示当前值(默认右下);点它(▸ 变 ▾)再选右上 / 右下 / 左上 / 左下,改完立刻生效;
|
|
133
133
|
- **不需要通知权限**:通知权限没给、或桌面端弹不出带按钮的通知时,浮层照常工作;
|
|
134
134
|
- **审批卡片带「同意 / 拒绝」**:与审批卡片的「允许一次 / 拒绝」等价,桌面端也能用(不依赖 Service Worker);点卡片正文则切回对应对话;
|
|
135
|
-
- **停留时间**:普通提醒 5 秒自动收起,带「同意 / 拒绝」的审批卡片 12
|
|
135
|
+
- **停留时间**:普通提醒 5 秒自动收起,带「同意 / 拒绝」的审批卡片 12 秒(系统通知用同一套数字);也可以点卡片或右上角叉提前关掉。最多同时叠 4 张;
|
|
136
136
|
- **与系统通知的关系**:二选一。以前两个开关可以同开,结果同一条提醒弹两遍、还互相挡住;1.10.0 起改成单选,1.10.2 起做成一行分段选择器。老配置里开着浮层的,升级后自动落到浮层。
|
|
137
137
|
|
|
138
138
|
浮层只知道窗口在哪块屏,不知道你人在看哪块屏。窗口留在主屏、人却盯着副屏时,它同样看不见。
|
|
@@ -194,12 +194,11 @@ Windows 的系统通知横幅固定画在主屏上,系统没有设置项、浏
|
|
|
194
194
|
|
|
195
195
|
> 需要浏览器通知权限:页面上点一下 → 允许;或地址栏锁 → 站点设置 → 通知 → 允许 → 刷新。macOS 还要在 系统设置 → 通知 里允许该浏览器。
|
|
196
196
|
|
|
197
|
-
##
|
|
197
|
+
## 提醒渠道
|
|
198
198
|
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
|
|
202
|
-
两种渠道在设置里二选一,不会同时出现。
|
|
199
|
+
- **提醒渠道(二选一,不同时出现)**:
|
|
200
|
+
- **系统通知**:经浏览器弹出的系统通知,进 Windows 通知中心或 macOS 通知中心(点击回到提醒所属的对话;支持快捷裁决的 Web 环境可点审批按钮直接裁决,桌面端无按钮)
|
|
201
|
+
- **页面浮层**:画在 DSH 页面角落的提醒卡片,落在窗口所在的那块屏,可带「同意 / 拒绝」按钮;见[副屏与浮层提醒](#副屏与浮层提醒)
|
|
203
202
|
- **提示音**:默认是 WebAudio 合成音(「需要你」与「完成」使用不同音型);可在设置里为两类提醒分别换成自定义音频文件,或改成让操作系统播放它自己的通知音
|
|
204
203
|
- **标签页标题标记**:有待处理事项时,标题前出现 `🔔 需要你 · …` / `🔔 Action needed · …`;后台会话**完成但还没看**时出现 `✅ 回复完成 · …` / `✅ Reply finished · …`,打开对应会话(或它再次开跑)即消失。两种标记可同时出现,「需要你」在前;宿主改写标题后标记基于新标题重建
|
|
205
204
|
- **外部通知**(可选,默认关):按设置里配的推送目标,把同一条提醒转发到 Discord Webhook / Bark / Gotify / 自定义 Webhook——临时离开电脑时,手机上的推送渠道照样收到
|
|
@@ -212,7 +211,7 @@ Windows 的系统通知横幅固定画在主屏上,系统没有设置项、浏
|
|
|
212
211
|
|
|
213
212
|
实测**真正激活**(各自独立 profile 启动:插件条目进启动页 `__DSH_BOOT__` 且注入依赖解析通过、`/plugins/??dsh-notify-me/client.js&rev=…` 返回含新代码的构建,设置里出现「通知提醒」分区,即插件的 `apply` 确实执行)于 `0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2` 与 `0.2.0-rc.2`;更早的 `0.1.1-rc.2` 亦验证过。
|
|
214
213
|
|
|
215
|
-
`0.2.1-rc.2`(当前 latest)另跑了一轮隔离验证:隔离 `DSH_HOME` 起 `dsh web`(70 个启动条目),插件条目排在第 59、`application` 批,三个注入目标都在且都排在它前面;`/plugins/??dsh-notify-me/client.js&rev=…`
|
|
214
|
+
`0.2.1-rc.2`(当前 latest)另跑了一轮隔离验证:隔离 `DSH_HOME` 起 `dsh web`(70 个启动条目),插件条目排在第 59、`application` 批,三个注入目标都在且都排在它前面;`/plugins/??dsh-notify-me/client.js&rev=…` 返回当时装的 1.7.0 源码构建(140,153 B);无头 Chromium 载入页面后 `apply` 正常执行,`window.__dshNotifyMe.debug()` 报 `uiSession: bound`、`uiSessionSource: sessionStatus`、`bridge: active`。宿主侧的形状与 `0.2.0-rc.2` 一致,没有需要改代码的地方。
|
|
216
215
|
|
|
217
216
|
<details>
|
|
218
217
|
<summary>宿主代际与适配排查细节</summary>
|
|
@@ -249,7 +248,7 @@ window.__dshNotifyMe.setConfig({
|
|
|
249
248
|
currentHiddenOnly: true, // true = 当前对话的等待只留标题标记(转后台补发)
|
|
250
249
|
doneHiddenOnly: true, // false = 页面可见时「完成」也提醒
|
|
251
250
|
ignoreSubagent: true, // true = 后台子代理(subagent)会话不提醒(当前打开的照常)
|
|
252
|
-
channel: "toast", //
|
|
251
|
+
channel: "toast", // 通知类型:'toast' 系统通知 | 'overlay' 页面浮层,二选一
|
|
253
252
|
sound: true, // 提示音开关(含「系统通知音」模式)
|
|
254
253
|
soundDone: "synth", // 「完成」音效来源:'synth' 内置 | 'custom' 自定义文件 | 'system' 系统通知音
|
|
255
254
|
soundAttention: "synth", // 「需要你」音效来源,取值同上
|
|
@@ -296,7 +295,7 @@ window.__dshNotifyMe.testExternal() // 显式外发测试:向有
|
|
|
296
295
|
|
|
297
296
|
通知按钮(`actions`)只属于 Service Worker 弹的持久通知,往 `new Notification()` 里传 `actions` 会直接抛 `TypeError`——这是绕不开的浏览器限制。所以 bundle 一份文件干两件事:页面里照常注册提醒工厂,同一份字节再注册成一个只干转信的 Service Worker,把「点了哪个按钮」(同意 / 拒绝 / 点正文)带回页面。真正的裁决发生在页面里,调的是审批卡片自己用的 `PendingApproval.answer('allowed-once' | 'rejected')`,所以「同意」就是「允许一次」,不多放行任何东西。点正文的「调窗口 + 切对话」同样归 worker 这半侧调度:它用 `client.focus()` 只调起一个窗口(优先当前可见的),并只让那个窗口切对话——多个 DSH 标签页不会互相抢焦点或一起乱切。
|
|
298
297
|
|
|
299
|
-
每条按钮通知按交互 key
|
|
298
|
+
每条按钮通知按交互 key 记账,一次只认领一条等待;请求被页面里答掉、或被新请求顶替之后,残留通知上的按钮再点也不会误裁,只是安静地关掉。带按钮的通知停留 12 秒(普通通知 5 秒),到点自动撤;没来得及点就回页面里裁决,卡片一直等着你。
|
|
300
299
|
|
|
301
300
|
### 桌面端怎么抬窗的
|
|
302
301
|
|
package/lib/client.js
CHANGED
|
@@ -321,13 +321,18 @@
|
|
|
321
321
|
// Persist a patch, swap the live module config and re-apply any active
|
|
322
322
|
// title marker (its prefix follows the notification language).
|
|
323
323
|
function setConfigLocal(patch) {
|
|
324
|
+
var wasOverlay = config.channel === "overlay";
|
|
324
325
|
config = writeConfig(patch);
|
|
325
326
|
applyTitle();
|
|
326
|
-
// Overlay re-apply:
|
|
327
|
-
// new corner moves the layer without waiting for the next
|
|
327
|
+
// Overlay re-apply: leaving the overlay channel takes its cards down at
|
|
328
|
+
// once, and a new corner moves the layer without waiting for the next
|
|
329
|
+
// alert. Cards can also exist on the toast channel (the desktop fallback),
|
|
330
|
+
// so an unrelated patch must not sweep them away.
|
|
328
331
|
try {
|
|
329
|
-
if (config.channel !== "overlay")
|
|
330
|
-
|
|
332
|
+
if (config.channel !== "overlay") {
|
|
333
|
+
if (wasOverlay) clearOverlays();
|
|
334
|
+
else if (overlayLayer) overlayLayer.className = "dnm-ov-layer dnm-ov-" + overlayCorner();
|
|
335
|
+
} else if (overlayLayer) overlayLayer.className = "dnm-ov-layer dnm-ov-" + overlayCorner();
|
|
331
336
|
} catch (e) {}
|
|
332
337
|
return config;
|
|
333
338
|
}
|
|
@@ -384,6 +389,8 @@
|
|
|
384
389
|
approve: "同意",
|
|
385
390
|
reject: "拒绝",
|
|
386
391
|
dismiss: "关闭这条提醒",
|
|
392
|
+
details: "详情",
|
|
393
|
+
collapse: "收起",
|
|
387
394
|
testAttention: "这是一条测试提醒:DSH 需要你的操作",
|
|
388
395
|
testDone: "测试提醒 · 回复完成示例",
|
|
389
396
|
testApproval: "这是一条测试审批:点「同意 / 拒绝」试试快捷裁决",
|
|
@@ -411,6 +418,8 @@
|
|
|
411
418
|
approve: "Approve",
|
|
412
419
|
reject: "Reject",
|
|
413
420
|
dismiss: "Dismiss this alert",
|
|
421
|
+
details: "Details",
|
|
422
|
+
collapse: "Collapse",
|
|
414
423
|
testAttention: "This is a test alert: DSH is waiting for your input",
|
|
415
424
|
testDone: "Test alert · reply-finished sample",
|
|
416
425
|
testApproval: "This is a test approval: try the Approve / Reject buttons to settle it",
|
|
@@ -733,10 +742,26 @@
|
|
|
733
742
|
return q;
|
|
734
743
|
}
|
|
735
744
|
|
|
745
|
+
// A plain toast needs a tag unique to that one notification. It used to be
|
|
746
|
+
// "dsh-notify-me-" + kind, which leans on renotify:true to replace the
|
|
747
|
+
// previous banner of the same kind; Electron ignores that flag, so the
|
|
748
|
+
// second toast of a kind silently overwrote the first and never re-alerted
|
|
749
|
+
// (issue #15). A unique tag makes every toast a fresh alert everywhere,
|
|
750
|
+
// while renotify stays meaningful on the web. Date.now() alone collides
|
|
751
|
+
// when two alerts land in the same millisecond, hence the counter; the
|
|
752
|
+
// >>> 0 wrap keeps it from ever going negative. Approval toasts keep their
|
|
753
|
+
// stable "dsh-notify-me-attention-<key>" tag: closeNotificationTag() looks
|
|
754
|
+
// them up by it when the request is settled.
|
|
755
|
+
var toastSeq = 0;
|
|
756
|
+
function uniqueToastTag(kind) {
|
|
757
|
+
toastSeq = (toastSeq + 1) >>> 0;
|
|
758
|
+
return "dsh-notify-me-" + kind + "-" + toastSeq + "-" + Date.now();
|
|
759
|
+
}
|
|
760
|
+
|
|
736
761
|
function showToast(kind, title, body, sessionId, quick) {
|
|
737
762
|
if (!canToast()) return;
|
|
738
763
|
try {
|
|
739
|
-
var tag = quick ? quick.tag :
|
|
764
|
+
var tag = quick ? quick.tag : uniqueToastTag(kind);
|
|
740
765
|
if (quick && bridgeActive()) {
|
|
741
766
|
var d = texts();
|
|
742
767
|
try {
|
|
@@ -817,9 +842,11 @@
|
|
|
817
842
|
".dnm-ov-attention .dnm-ov-dot{color:var(--dsw-alias-state-warning-primary,#f59e0b);opacity:1}" +
|
|
818
843
|
".dnm-ov-done .dnm-ov-dot{color:var(--dsw-alias-state-success-primary,#22c55e);opacity:1}" +
|
|
819
844
|
".dnm-ov-title{flex:1;min-width:0;font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}" +
|
|
820
|
-
".dnm-ov-x{flex:none;border:0;background:transparent;color:inherit;opacity:.6;font-size:15px;line-height:15px;padding:0 2px;cursor:pointer;font-family:inherit}" +
|
|
821
|
-
".dnm-ov-x:hover{opacity:1}" +
|
|
845
|
+
".dnm-ov-x,.dnm-ov-more{flex:none;border:0;background:transparent;color:inherit;opacity:.6;font-size:15px;line-height:15px;padding:0 2px;cursor:pointer;font-family:inherit}" +
|
|
846
|
+
".dnm-ov-x:hover,.dnm-ov-more:hover{opacity:1}" +
|
|
847
|
+
".dnm-ov-more{font-size:11px;opacity:.8;white-space:nowrap}" +
|
|
822
848
|
".dnm-ov-body{color:var(--dsw-alias-label-secondary,rgba(220,222,226,.86));font-size:12px;line-height:18px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}" +
|
|
849
|
+
".dnm-ov.dnm-ov-open .dnm-ov-body{display:block;-webkit-line-clamp:unset;max-height:40vh;overflow:auto}" +
|
|
823
850
|
".dnm-ov-actions{display:flex;gap:8px;margin-top:2px}" +
|
|
824
851
|
".dnm-ov-btn{flex:1;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.4));background:var(--dsw-alias-bg-layer-1,rgba(255,255,255,.06));color:inherit;border-radius:8px;padding:5px 10px;font-size:12px;font-family:inherit;cursor:pointer}" +
|
|
825
852
|
".dnm-ov-btn:hover{background:var(--dsw-alias-bg-layer-2,rgba(255,255,255,.12))}" +
|
|
@@ -895,17 +922,30 @@
|
|
|
895
922
|
}
|
|
896
923
|
}
|
|
897
924
|
function overlayCount() { return Object.keys(overlayCards).length; }
|
|
898
|
-
//
|
|
899
|
-
//
|
|
900
|
-
|
|
901
|
-
|
|
925
|
+
// One card builder for both channels: the overlay channel draws with it,
|
|
926
|
+
// and so does the desktop fallback below. `opts` keeps the two behaviours
|
|
927
|
+
// apart: the overlay card is a shortcut (a click opens the conversation and
|
|
928
|
+
// takes the card down), while the fallback card carries a decision the OS
|
|
929
|
+
// notification cannot — so a click must not dismiss it unanswered, and a
|
|
930
|
+
// "详情 / Details" toggle exposes the body that the CSS clamps to 3 lines.
|
|
931
|
+
function drawOverlayCard(kind, title, body, sessionId, quick, opts) {
|
|
932
|
+
opts = opts || {};
|
|
902
933
|
var layer = ensureOverlayLayer();
|
|
903
934
|
if (!layer) return false;
|
|
935
|
+
// One card per approval key: a re-delivery (the quieted copy that fires
|
|
936
|
+
// when the page is backgrounded) must not stack a second card.
|
|
937
|
+
if (quick && typeof quick.key === "string") {
|
|
938
|
+
var known = Object.keys(overlayCards);
|
|
939
|
+
for (var k = 0; k < known.length; k++) {
|
|
940
|
+
if (overlayCards[known[k]].key === quick.key) return false;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
904
943
|
var d = texts();
|
|
905
944
|
try {
|
|
906
945
|
var id = "ov" + (++overlaySeq);
|
|
946
|
+
var baseClass = "dnm-ov dnm-ov-" + (kind === "attention" ? "attention" : "done");
|
|
907
947
|
var card = document.createElement("div");
|
|
908
|
-
card.className =
|
|
948
|
+
card.className = baseClass;
|
|
909
949
|
card.setAttribute("role", kind === "attention" ? "alert" : "status");
|
|
910
950
|
var head = document.createElement("div");
|
|
911
951
|
head.className = "dnm-ov-head";
|
|
@@ -914,6 +954,22 @@
|
|
|
914
954
|
var label = document.createElement("span");
|
|
915
955
|
label.className = "dnm-ov-title";
|
|
916
956
|
label.textContent = String(title == null ? "" : title);
|
|
957
|
+
var more = null;
|
|
958
|
+
if (opts.expand && body) {
|
|
959
|
+
more = document.createElement("button");
|
|
960
|
+
more.type = "button";
|
|
961
|
+
more.className = "dnm-ov-more";
|
|
962
|
+
more.setAttribute("aria-label", d.details);
|
|
963
|
+
more.setAttribute("aria-expanded", "false");
|
|
964
|
+
more.textContent = d.details;
|
|
965
|
+
more.onclick = function (ev) {
|
|
966
|
+
if (ev && ev.stopPropagation) ev.stopPropagation();
|
|
967
|
+
var open = card.className.indexOf("dnm-ov-open") !== -1;
|
|
968
|
+
card.className = baseClass + (open ? "" : " dnm-ov-open");
|
|
969
|
+
more.textContent = open ? d.details : d.collapse;
|
|
970
|
+
more.setAttribute("aria-expanded", open ? "false" : "true");
|
|
971
|
+
};
|
|
972
|
+
}
|
|
917
973
|
var close = document.createElement("button");
|
|
918
974
|
close.type = "button";
|
|
919
975
|
close.className = "dnm-ov-x";
|
|
@@ -925,6 +981,7 @@
|
|
|
925
981
|
};
|
|
926
982
|
head.appendChild(dot);
|
|
927
983
|
head.appendChild(label);
|
|
984
|
+
if (more) head.appendChild(more);
|
|
928
985
|
head.appendChild(close);
|
|
929
986
|
card.appendChild(head);
|
|
930
987
|
if (body) {
|
|
@@ -954,10 +1011,12 @@
|
|
|
954
1011
|
}
|
|
955
1012
|
// A click on the card body opens the conversation, exactly like a toast
|
|
956
1013
|
// body click — and here it is an ordinary page gesture, so it reaches the
|
|
957
|
-
// desktop's dsh:// raise path even though a worker click would not.
|
|
1014
|
+
// desktop's dsh:// raise path even though a worker click would not. The
|
|
1015
|
+
// overlay channel also takes the card down; the fallback card stays, so
|
|
1016
|
+
// the decision is still one click away after a look at the conversation.
|
|
958
1017
|
card.onclick = function () {
|
|
959
1018
|
if (config.autoFocus) focusSession(sessionId || null);
|
|
960
|
-
dismissOverlay(id);
|
|
1019
|
+
if (opts.dismissOnClick !== false) dismissOverlay(id);
|
|
961
1020
|
};
|
|
962
1021
|
layer.appendChild(card);
|
|
963
1022
|
var rec = { card: card, key: (quick && quick.key) ? quick.key : null, kind: kind, timer: null };
|
|
@@ -971,6 +1030,29 @@
|
|
|
971
1030
|
return true;
|
|
972
1031
|
} catch (e) { return false; }
|
|
973
1032
|
}
|
|
1033
|
+
// Same inputs as showToast: `quick` is the approval record built by
|
|
1034
|
+
// quickFor(), and it is what lets an overlay settle the request in place.
|
|
1035
|
+
function showOverlay(kind, title, body, sessionId, quick) {
|
|
1036
|
+
if (config.channel !== "overlay") return false;
|
|
1037
|
+
return drawOverlayCard(kind, title, body, sessionId, quick, { dismissOnClick: true });
|
|
1038
|
+
}
|
|
1039
|
+
// The desktop shell cannot register the Service Worker that OS action
|
|
1040
|
+
// buttons require, so an approval toast on a dsh-app:// page has no button
|
|
1041
|
+
// to click. While the alert channel is system notifications, an approval
|
|
1042
|
+
// therefore also drops a card into the same in-page layer, in the same
|
|
1043
|
+
// corner and with the same styling: its buttons call decidePending(), the
|
|
1044
|
+
// exact path a Web toast button takes. Only states that prove the bridge is
|
|
1045
|
+
// unusable qualify — 'idle'/'registering' are transitional, 'disabled' means
|
|
1046
|
+
// the quick-decision switch is off (quickFor() then returns null, so no card
|
|
1047
|
+
// is drawn at all), and the Web path stays untouched once the worker is up.
|
|
1048
|
+
function showFallbackApprovalCard(kind, title, body, sessionId, quick) {
|
|
1049
|
+
if (kind !== "attention") return false;
|
|
1050
|
+
if (!quick || typeof quick.key !== "string") return false;
|
|
1051
|
+
if (config.channel !== "toast") return false;
|
|
1052
|
+
if (bridgeActive()) return false;
|
|
1053
|
+
if (swState.indexOf("unsupported:") !== 0 && swState.indexOf("failed:") !== 0) return false;
|
|
1054
|
+
return drawOverlayCard(kind, title, body, sessionId, quick, { dismissOnClick: false, expand: true });
|
|
1055
|
+
}
|
|
974
1056
|
// Sound: WebAudio beeps (no asset needed). The context only runs after a
|
|
975
1057
|
// user gesture; we unlock it on the first pointer/key event.
|
|
976
1058
|
var audioCtx = null;
|
|
@@ -1325,6 +1407,7 @@
|
|
|
1325
1407
|
if (!config.enabled) return;
|
|
1326
1408
|
showToast(kind, title, body, sessionId, quick);
|
|
1327
1409
|
showOverlay(kind, title, body, sessionId, quick);
|
|
1410
|
+
showFallbackApprovalCard(kind, title, body, sessionId, quick);
|
|
1328
1411
|
if (kind === "attention") {
|
|
1329
1412
|
playAttentionSound();
|
|
1330
1413
|
} else {
|
|
@@ -1964,7 +2047,7 @@
|
|
|
1964
2047
|
});
|
|
1965
2048
|
} catch (e) {}
|
|
1966
2049
|
// keep in sync with package.json "version" on every release
|
|
1967
|
-
api.version = "1.10.
|
|
2050
|
+
api.version = "1.10.4";
|
|
1968
2051
|
api.setConfig = function (patch) { return setConfigLocal(patch); };
|
|
1969
2052
|
api.resetConfig = function () {
|
|
1970
2053
|
try {
|
|
@@ -2177,16 +2260,16 @@
|
|
|
2177
2260
|
autoFocus: "点击通知回到对应对话",
|
|
2178
2261
|
autoFocusHint: "点通知会切到这条提醒所属的对话;关掉后点击不做任何事。",
|
|
2179
2262
|
quickActions: "审批通知上直接裁决",
|
|
2180
|
-
quickActionsHint: "审批通知上带「同意 / 拒绝」,点一下即完成裁决,不用切回页面。需要 Service Worker(http://127.0.0.1 或 https
|
|
2263
|
+
quickActionsHint: "审批通知上带「同意 / 拒绝」,点一下即完成裁决,不用切回页面。需要 Service Worker(http://127.0.0.1 或 https);用不了时按钮改画在窗口角落的卡片上(桌面端就是这条路)。",
|
|
2181
2264
|
quickApprovalNote: "「同意」等价于审批卡片上的「允许一次」,只放行这一次。",
|
|
2182
2265
|
bridgeOff: "快捷裁决按钮暂不可用(",
|
|
2183
|
-
bridgeOffTail: "
|
|
2184
|
-
bridgeOffDesktop: "
|
|
2266
|
+
bridgeOffTail: "):系统通知没有按钮,按钮改画在窗口角落的卡片上。",
|
|
2267
|
+
bridgeOffDesktop: "系统通知本身没有「同意 / 拒绝」按钮:桌面端页面(dsh-app://)注册不了 Service Worker(宿主少给 allowServiceWorkers 特权)。审批类提醒会同时在窗口角落弹一张卡片,按钮就在卡片上;想只留卡片、不弹系统通知,把「提醒方式」切到「页面浮层」。",
|
|
2185
2268
|
overlay: "页面浮层提醒",
|
|
2186
2269
|
overlayHint: "在窗口角落画提醒卡片:窗口在哪块屏,它就在哪块屏;系统通知只会出现在主屏,主屏不看时用它。不需要通知权限,卡片上能直接「同意 / 拒绝」。与系统通知二选一。",
|
|
2187
2270
|
channelLabel: "通知类型",
|
|
2188
2271
|
overlaySeg: "浮层提醒",
|
|
2189
|
-
channelHint: "
|
|
2272
|
+
channelHint: "系统通知只会出现在主屏,进通知中心要权限,桌面端的通知本身没有「同意 / 拒绝」按钮(审批会额外在窗口角落弹一张可点击的卡片);页面浮层画在 DSH 窗口所在的那块屏,不需要权限,卡片上能直接裁决。两个只能选一个。",
|
|
2190
2273
|
overlayCorner: "浮层位置",
|
|
2191
2274
|
overlayCornerHint: "贴在 DSH 窗口的哪个角;窗口在哪块屏,浮层就出现在哪块屏。",
|
|
2192
2275
|
overlayPosTR: "右上",
|
|
@@ -2194,7 +2277,7 @@
|
|
|
2194
2277
|
overlayPosTL: "左上",
|
|
2195
2278
|
overlayPosBL: "左下",
|
|
2196
2279
|
overlayQuickNote: "浮层上的「同意」同样等价于审批卡片上的「允许一次」,与通知按钮一致。",
|
|
2197
|
-
testApprovalNoBridge: "
|
|
2280
|
+
testApprovalNoBridge: "已发测试提醒:系统通知没有按钮,快捷裁决按钮画在窗口角落的卡片上。",
|
|
2198
2281
|
testNeedsQuick: "先打开上面的「审批通知上直接裁决」才能测按钮。",
|
|
2199
2282
|
volume: "音量",
|
|
2200
2283
|
language: "通知语言",
|
|
@@ -2307,16 +2390,16 @@
|
|
|
2307
2390
|
autoFocus: "Click a toast to open that conversation",
|
|
2308
2391
|
autoFocusHint: "A click switches to the conversation the alert came from; off means a click does nothing.",
|
|
2309
2392
|
quickActions: "Decide approvals from the toast",
|
|
2310
|
-
quickActionsHint: "Approval notifications carry Approve / Reject; one click settles the request without switching back. Needs a Service Worker browser (http://127.0.0.1 or https)
|
|
2393
|
+
quickActionsHint: "Approval notifications carry Approve / Reject; one click settles the request without switching back. Needs a Service Worker browser (http://127.0.0.1 or https); when it is unavailable the buttons land on a card in the window corner (the Desktop shell's route).",
|
|
2311
2394
|
quickApprovalNote: "\"Approve\" equals \"Allow once\" on the approval card — it allows that one call only.",
|
|
2312
2395
|
bridgeOff: "Quick-decision buttons are unavailable right now (",
|
|
2313
|
-
bridgeOffTail: ");
|
|
2314
|
-
bridgeOffDesktop: "System notifications carry no Approve / Reject buttons: dsh-app:// pages cannot register a Service Worker (the shell does not grant the allowServiceWorkers privilege)
|
|
2396
|
+
bridgeOffTail: "); system notifications carry no buttons, so they are drawn on a card in the window corner instead.",
|
|
2397
|
+
bridgeOffDesktop: "System notifications carry no Approve / Reject buttons: dsh-app:// pages cannot register a Service Worker (the shell does not grant the allowServiceWorkers privilege). An approval therefore also drops a clickable card in the window corner, buttons and all; switch the alert channel to the in-page overlay to keep only the card and skip the system notification.",
|
|
2315
2398
|
overlay: "In-page overlay",
|
|
2316
2399
|
overlayHint: "Draw a card in the window corner, on whatever display the window sits on. System notifications only ever show on the primary display. No permission needed, and the card carries Approve / Reject directly. It replaces system notifications rather than adding to them.",
|
|
2317
2400
|
channelLabel: "Alert type",
|
|
2318
2401
|
overlaySeg: "Overlay",
|
|
2319
|
-
channelHint: "System notifications land in the Windows notification center: permission needed, primary display only, and no Approve / Reject buttons
|
|
2402
|
+
channelHint: "System notifications land in the Windows notification center: permission needed, primary display only, and the Desktop shell's notifications carry no Approve / Reject buttons (an approval also drops a clickable card in the window corner). The in-page overlay draws on whichever display the DSH window sits on, needs no permission, and lets the Desktop shell decide right on the card. Pick one.",
|
|
2320
2403
|
overlayCorner: "Overlay position",
|
|
2321
2404
|
overlayCornerHint: "Which corner of the DSH window the cards stack in; they follow the window to whatever display it is on.",
|
|
2322
2405
|
overlayPosTR: "Top right",
|
|
@@ -2324,7 +2407,7 @@
|
|
|
2324
2407
|
overlayPosTL: "Top left",
|
|
2325
2408
|
overlayPosBL: "Bottom left",
|
|
2326
2409
|
overlayQuickNote: "\"Approve\" here equals \"Allow once\" on the approval card — the same decision the toast buttons send.",
|
|
2327
|
-
testApprovalNoBridge: "
|
|
2410
|
+
testApprovalNoBridge: "Test alert sent: system notifications carry no buttons, so the quick-decision buttons are drawn on a card in the window corner.",
|
|
2328
2411
|
testNeedsQuick: "Turn on \"Decide approvals from the toast\" above to test the buttons.",
|
|
2329
2412
|
volume: "Volume",
|
|
2330
2413
|
language: "Notification language",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-notify-me",
|
|
3
|
-
"version": "1.10.
|
|
4
|
-
"description": "离开 DSH 页面也能收到提醒:需要你操作 /
|
|
3
|
+
"version": "1.10.4",
|
|
4
|
+
"description": "离开 DSH 页面也能收到提醒:需要你操作 / 后台回复完成时发系统通知、标题标记与可选页面浮层(副屏也能看见),支持审批快捷裁决与外部推送,Web 版与桌面版均可用。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|