@rei-standard/amsg-shared 0.4.0-next.7 → 0.4.0-next.8

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
@@ -78,7 +78,7 @@ omit all four.
78
78
  | `tag` | `string?` | Notification grouping tag. |
79
79
  | `renotify` | `boolean?` | Re-alert when a matching `tag` replaces an existing notification. |
80
80
  | `requireInteraction` | `boolean?` | Keep the notification visible until the user dismisses it. |
81
- | `silent` | `boolean?` | Suppress notification sound and vibration. |
81
+ | `silent` | `(boolean \| 'when-visible')?` | Suppress notification sound and vibration — see [选哪个 `silent`](#选哪个-silent). |
82
82
  | `data` | `Record<string, unknown>?` | Custom data passed to the notification. |
83
83
 
84
84
  Unknown fields are preserved for forward compatibility, but the known
@@ -101,6 +101,18 @@ fields above are validated by the builders when present.
101
101
 
102
102
  完整取舍见 [`@rei-standard/amsg-sw` README 的「不展示通知的代价」](https://github.com/Tosd0/ReiStandard/blob/main/packages/rei-standard-amsg/sw/README.md#不展示通知的代价)。
103
103
 
104
+ ### 选哪个 `silent`
105
+
106
+ `silent` 管的是「响不响铃、震不震」,跟弹不弹(`show`)是两件独立的事——通知照样进通知中心,只是安静地进。
107
+
108
+ | 值 | SW 那边 | 什么时候用 |
109
+ |---|---|---|
110
+ | 不配 / `false` | 正常响铃震动 | 默认 |
111
+ | `true` | 一律不响 | 一串连着来的通知配 `tag` 折叠,只想在通知中心留个痕迹 |
112
+ | `'when-visible'` | 有可见窗口就静音,没有就照常响 | 页面自己会把内容画出来的那类消息:用户正看着页面就别再响一声,人切后台了照样叫得动 |
113
+
114
+ `'when-visible'` 只能由 Service Worker 当场算:发送端发推那一刻并不知道用户此刻在不在前台,写死 `silent: true` 的话,用户切到后台收到的那条也不会响。判定用的是跟 `show: 'when-hidden'` 同一套窗口可见性口径,一条 payload 只算一次。
115
+
104
116
  ### `notificationIntent(payload)`
105
117
 
106
118
  把上面这套规则算成一个值,`'always'` / `'when-hidden'` / `'never'`:`notification.show` 说了算,没说才按 `messageKind` 走默认。两端读同一份——SW 拿它决定要不要 `showNotification`,发送端拿它决定这条值不值得占用推送通道(`'never'` 的 payload 推过去不会有任何可见反馈,`@rei-standard/amsg-server` 只把它落进收件箱,等客户端上线 `GET /outbox?since=` 补拉)。
package/dist/index.cjs CHANGED
@@ -964,11 +964,14 @@ function validateNotificationArg(kind, value) {
964
964
  throw new Error(`[amsg-shared] ${kind}: 'notification.${f}' must be a string when present`);
965
965
  }
966
966
  }
967
- for (const f of ["renotify", "requireInteraction", "silent"]) {
967
+ for (const f of ["renotify", "requireInteraction"]) {
968
968
  if (n[f] !== void 0 && typeof n[f] !== "boolean") {
969
969
  throw new Error(`[amsg-shared] ${kind}: 'notification.${f}' must be a boolean when present`);
970
970
  }
971
971
  }
972
+ if (n.silent !== void 0 && typeof n.silent !== "boolean" && n.silent !== "when-visible") {
973
+ throw new Error(`[amsg-shared] ${kind}: 'notification.silent' must be true, false, or "when-visible"`);
974
+ }
972
975
  if (n.data !== void 0 && (n.data === null || typeof n.data !== "object" || Array.isArray(n.data))) {
973
976
  throw new Error(`[amsg-shared] ${kind}: 'notification.data' must be a plain object when present`);
974
977
  }
package/dist/index.d.cts CHANGED
@@ -39,6 +39,10 @@
39
39
  * un-kinded payloads) will display a system notification. `reasoning` / `tool_request` /
40
40
  * `error` will dispatch silently.
41
41
  * - `show: "always"`, `"when-hidden"`, or `false` overrides this default.
42
+ * - `silent: "when-visible"` is resolved by the SW at render time from the
43
+ * same window-visibility check `show: "when-hidden"` uses: silent while a
44
+ * `visibilityState === "visible"` window client exists, audible otherwise.
45
+ * `true` / `false` stay literal.
42
46
  * - When rendering, `notification.*` is consulted first, with per-field
43
47
  * fallback to the matching top-level payload fields (`title`,
44
48
  * `body`/`message`, `icon`/`avatarUrl`, `badge`, `tag`/`messageId`,
@@ -55,6 +59,11 @@
55
59
  * 码不选。`show: false` 在两端也不是同一件事——有收件箱的发送端见到它根本不发
56
60
  * 这条 push,SW 压根收不到。
57
61
  *
62
+ * 想要「前台安静、切后台照常响」就配 `silent: "when-visible"`:`show` 照旧
63
+ * `"always"`(通知一定弹出来,那笔账不欠),响不响铃由 SW 收到时看有没有可见
64
+ * 窗口现算。发送端定不了这件事——它发推那一刻并不知道用户在不在前台,写死
65
+ * `silent: true` 的结果是切后台也不响。
66
+ *
58
67
  * 各档取舍见本包 README 的「选哪个 `show`」与 `@rei-standard/amsg-sw` README
59
68
  * 的「不展示通知的代价」。
60
69
  *
@@ -67,7 +76,7 @@
67
76
  * @property {string} [tag] - Notification grouping tag; matching tag replaces the prior notification (falls back to top-level `tag`, then `messageId`, then a generated unique tag).
68
77
  * @property {boolean} [renotify] - When tag matches, still vibrate/sound (falls back to top-level `renotify`, default false at SW).
69
78
  * @property {boolean} [requireInteraction] - Notification stays until user dismisses (falls back to top-level `requireInteraction`, default false at SW).
70
- * @property {boolean} [silent] - Suppress sound and vibration (falls back to top-level `silent`, default false at SW).
79
+ * @property {boolean | "when-visible"} [silent] - Suppress sound and vibration. `true` / `false` are literal; `"when-visible"` is decided by the SW at render time — silent while a window client is visible, audible otherwise (falls back to top-level `silent`, default false at SW).
71
80
  * @property {Record<string, unknown>} [data] - Custom payload data to attach to the notification (falls back to top-level `data`).
72
81
  */
73
82
  /**
@@ -674,6 +683,10 @@ export type AmsgPushCommon = {
674
683
  * un-kinded payloads) will display a system notification. `reasoning` / `tool_request` /
675
684
  * `error` will dispatch silently.
676
685
  * - `show: "always"`, `"when-hidden"`, or `false` overrides this default.
686
+ * - `silent: "when-visible"` is resolved by the SW at render time from the
687
+ * same window-visibility check `show: "when-hidden"` uses: silent while a
688
+ * `visibilityState === "visible"` window client exists, audible otherwise.
689
+ * `true` / `false` stay literal.
677
690
  * - When rendering, `notification.*` is consulted first, with per-field
678
691
  * fallback to the matching top-level payload fields (`title`,
679
692
  * `body`/`message`, `icon`/`avatarUrl`, `badge`, `tag`/`messageId`,
@@ -690,6 +703,11 @@ export type AmsgPushCommon = {
690
703
  * 码不选。`show: false` 在两端也不是同一件事——有收件箱的发送端见到它根本不发
691
704
  * 这条 push,SW 压根收不到。
692
705
  *
706
+ * 想要「前台安静、切后台照常响」就配 `silent: "when-visible"`:`show` 照旧
707
+ * `"always"`(通知一定弹出来,那笔账不欠),响不响铃由 SW 收到时看有没有可见
708
+ * 窗口现算。发送端定不了这件事——它发推那一刻并不知道用户在不在前台,写死
709
+ * `silent: true` 的结果是切后台也不响。
710
+ *
693
711
  * 各档取舍见本包 README 的「选哪个 `show`」与 `@rei-standard/amsg-sw` README
694
712
  * 的「不展示通知的代价」。
695
713
  */
@@ -727,9 +745,9 @@ export type NotificationDirective = {
727
745
  */
728
746
  requireInteraction?: boolean;
729
747
  /**
730
- * - Suppress sound and vibration (falls back to top-level `silent`, default false at SW).
748
+ * - Suppress sound and vibration. `true` / `false` are literal; `"when-visible"` is decided by the SW at render time — silent while a window client is visible, audible otherwise (falls back to top-level `silent`, default false at SW).
731
749
  */
732
- silent?: boolean;
750
+ silent?: boolean | "when-visible";
733
751
  /**
734
752
  * - Custom payload data to attach to the notification (falls back to top-level `data`).
735
753
  */
package/dist/index.d.ts CHANGED
@@ -39,6 +39,10 @@
39
39
  * un-kinded payloads) will display a system notification. `reasoning` / `tool_request` /
40
40
  * `error` will dispatch silently.
41
41
  * - `show: "always"`, `"when-hidden"`, or `false` overrides this default.
42
+ * - `silent: "when-visible"` is resolved by the SW at render time from the
43
+ * same window-visibility check `show: "when-hidden"` uses: silent while a
44
+ * `visibilityState === "visible"` window client exists, audible otherwise.
45
+ * `true` / `false` stay literal.
42
46
  * - When rendering, `notification.*` is consulted first, with per-field
43
47
  * fallback to the matching top-level payload fields (`title`,
44
48
  * `body`/`message`, `icon`/`avatarUrl`, `badge`, `tag`/`messageId`,
@@ -55,6 +59,11 @@
55
59
  * 码不选。`show: false` 在两端也不是同一件事——有收件箱的发送端见到它根本不发
56
60
  * 这条 push,SW 压根收不到。
57
61
  *
62
+ * 想要「前台安静、切后台照常响」就配 `silent: "when-visible"`:`show` 照旧
63
+ * `"always"`(通知一定弹出来,那笔账不欠),响不响铃由 SW 收到时看有没有可见
64
+ * 窗口现算。发送端定不了这件事——它发推那一刻并不知道用户在不在前台,写死
65
+ * `silent: true` 的结果是切后台也不响。
66
+ *
58
67
  * 各档取舍见本包 README 的「选哪个 `show`」与 `@rei-standard/amsg-sw` README
59
68
  * 的「不展示通知的代价」。
60
69
  *
@@ -67,7 +76,7 @@
67
76
  * @property {string} [tag] - Notification grouping tag; matching tag replaces the prior notification (falls back to top-level `tag`, then `messageId`, then a generated unique tag).
68
77
  * @property {boolean} [renotify] - When tag matches, still vibrate/sound (falls back to top-level `renotify`, default false at SW).
69
78
  * @property {boolean} [requireInteraction] - Notification stays until user dismisses (falls back to top-level `requireInteraction`, default false at SW).
70
- * @property {boolean} [silent] - Suppress sound and vibration (falls back to top-level `silent`, default false at SW).
79
+ * @property {boolean | "when-visible"} [silent] - Suppress sound and vibration. `true` / `false` are literal; `"when-visible"` is decided by the SW at render time — silent while a window client is visible, audible otherwise (falls back to top-level `silent`, default false at SW).
71
80
  * @property {Record<string, unknown>} [data] - Custom payload data to attach to the notification (falls back to top-level `data`).
72
81
  */
73
82
  /**
@@ -674,6 +683,10 @@ export type AmsgPushCommon = {
674
683
  * un-kinded payloads) will display a system notification. `reasoning` / `tool_request` /
675
684
  * `error` will dispatch silently.
676
685
  * - `show: "always"`, `"when-hidden"`, or `false` overrides this default.
686
+ * - `silent: "when-visible"` is resolved by the SW at render time from the
687
+ * same window-visibility check `show: "when-hidden"` uses: silent while a
688
+ * `visibilityState === "visible"` window client exists, audible otherwise.
689
+ * `true` / `false` stay literal.
677
690
  * - When rendering, `notification.*` is consulted first, with per-field
678
691
  * fallback to the matching top-level payload fields (`title`,
679
692
  * `body`/`message`, `icon`/`avatarUrl`, `badge`, `tag`/`messageId`,
@@ -690,6 +703,11 @@ export type AmsgPushCommon = {
690
703
  * 码不选。`show: false` 在两端也不是同一件事——有收件箱的发送端见到它根本不发
691
704
  * 这条 push,SW 压根收不到。
692
705
  *
706
+ * 想要「前台安静、切后台照常响」就配 `silent: "when-visible"`:`show` 照旧
707
+ * `"always"`(通知一定弹出来,那笔账不欠),响不响铃由 SW 收到时看有没有可见
708
+ * 窗口现算。发送端定不了这件事——它发推那一刻并不知道用户在不在前台,写死
709
+ * `silent: true` 的结果是切后台也不响。
710
+ *
693
711
  * 各档取舍见本包 README 的「选哪个 `show`」与 `@rei-standard/amsg-sw` README
694
712
  * 的「不展示通知的代价」。
695
713
  */
@@ -727,9 +745,9 @@ export type NotificationDirective = {
727
745
  */
728
746
  requireInteraction?: boolean;
729
747
  /**
730
- * - Suppress sound and vibration (falls back to top-level `silent`, default false at SW).
748
+ * - Suppress sound and vibration. `true` / `false` are literal; `"when-visible"` is decided by the SW at render time — silent while a window client is visible, audible otherwise (falls back to top-level `silent`, default false at SW).
731
749
  */
732
- silent?: boolean;
750
+ silent?: boolean | "when-visible";
733
751
  /**
734
752
  * - Custom payload data to attach to the notification (falls back to top-level `data`).
735
753
  */
package/dist/index.mjs CHANGED
@@ -879,11 +879,14 @@ function validateNotificationArg(kind, value) {
879
879
  throw new Error(`[amsg-shared] ${kind}: 'notification.${f}' must be a string when present`);
880
880
  }
881
881
  }
882
- for (const f of ["renotify", "requireInteraction", "silent"]) {
882
+ for (const f of ["renotify", "requireInteraction"]) {
883
883
  if (n[f] !== void 0 && typeof n[f] !== "boolean") {
884
884
  throw new Error(`[amsg-shared] ${kind}: 'notification.${f}' must be a boolean when present`);
885
885
  }
886
886
  }
887
+ if (n.silent !== void 0 && typeof n.silent !== "boolean" && n.silent !== "when-visible") {
888
+ throw new Error(`[amsg-shared] ${kind}: 'notification.silent' must be true, false, or "when-visible"`);
889
+ }
887
890
  if (n.data !== void 0 && (n.data === null || typeof n.data !== "object" || Array.isArray(n.data))) {
888
891
  throw new Error(`[amsg-shared] ${kind}: 'notification.data' must be a plain object when present`);
889
892
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rei-standard/amsg-shared",
3
- "version": "0.4.0-next.7",
3
+ "version": "0.4.0-next.8",
4
4
  "description": "ReiStandard Active Messaging shared types and push builders — the lowest layer (no deps on other amsg packages)",
5
5
  "repository": {
6
6
  "type": "git",