@blocklet/ui-react 2.11.46 → 2.11.48

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.
@@ -2,7 +2,7 @@ export default Dashboard;
2
2
  /**
3
3
  * 专门用于 (composable) blocklet 的 Dashboard 组件, 解析 blocklet meta 中 section 为 dashboard 的 navigation 数据, 渲染一个 UX Dashboard
4
4
  */
5
- declare function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessionManagerProps, links, ...rest }: {
5
+ declare function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessionManagerProps, links, showDomainWarningDialog, ...rest }: {
6
6
  [x: string]: any;
7
7
  meta: any;
8
8
  fallbackUrl: any;
@@ -10,6 +10,7 @@ declare function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddon
10
10
  headerAddons: any;
11
11
  sessionManagerProps: any;
12
12
  links: any;
13
+ showDomainWarningDialog: any;
13
14
  }): import("react").JSX.Element | null;
14
15
  declare namespace Dashboard {
15
16
  namespace propTypes {
@@ -19,6 +20,7 @@ declare namespace Dashboard {
19
20
  export let headerAddons: any;
20
21
  export { SessionManagerProps as sessionManagerProps };
21
22
  export let links: any;
23
+ export let showDomainWarningDialog: any;
22
24
  }
23
25
  namespace defaultProps {
24
26
  export let meta: {};
@@ -33,6 +35,8 @@ declare namespace Dashboard {
33
35
  }
34
36
  let links_1: never[];
35
37
  export { links_1 as links };
38
+ let showDomainWarningDialog_1: boolean;
39
+ export { showDomainWarningDialog_1 as showDomainWarningDialog };
36
40
  }
37
41
  }
38
42
  import { BlockletMetaProps } from '../types';
@@ -12,7 +12,16 @@ import { publicPath, formatBlockletInfo, getLocalizedNavigation, filterNavByRole
12
12
  import HeaderAddons from "../common/header-addons.js";
13
13
  import { useWalletHiddenTopbar } from "../common/wallet-hidden-topbar.js";
14
14
  import useMobile from "../hooks/use-mobile.js";
15
- function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessionManagerProps, links, ...rest }) {
15
+ function Dashboard({
16
+ meta,
17
+ fallbackUrl,
18
+ invalidPathFallback,
19
+ headerAddons,
20
+ sessionManagerProps,
21
+ links,
22
+ showDomainWarningDialog,
23
+ ...rest
24
+ }) {
16
25
  useWalletHiddenTopbar();
17
26
  const sessionCtx = useContext(SessionContext);
18
27
  const user = sessionCtx?.session?.user;
@@ -83,7 +92,8 @@ function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessi
83
92
  {
84
93
  formattedBlocklet,
85
94
  addons: headerAddons,
86
- sessionManagerProps
95
+ sessionManagerProps,
96
+ showDomainWarningDialog
87
97
  }
88
98
  );
89
99
  return /* @__PURE__ */ jsx(
@@ -112,7 +122,8 @@ Dashboard.propTypes = {
112
122
  invalidPathFallback: PropTypes.func,
113
123
  headerAddons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
114
124
  sessionManagerProps: SessionManagerProps,
115
- links: PropTypes.oneOfType([PropTypes.array, PropTypes.func])
125
+ links: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
126
+ showDomainWarningDialog: PropTypes.bool
116
127
  };
117
128
  Dashboard.defaultProps = {
118
129
  meta: {},
@@ -126,6 +137,7 @@ Dashboard.defaultProps = {
126
137
  window.location.href = publicPath;
127
138
  }
128
139
  },
129
- links: []
140
+ links: [],
141
+ showDomainWarningDialog: true
130
142
  };
131
143
  export default Dashboard;
@@ -16,6 +16,7 @@ type HeaderProps = {
16
16
  prepend?: React.ReactNode;
17
17
  align?: 'left' | 'right';
18
18
  maxWidth?: false | Breakpoint;
19
+ showDomainWarningDialog?: boolean;
19
20
  };
20
21
  declare const _default: import("react").ComponentType<HeaderProps & Omit<BoxProps, keyof HeaderProps>>;
21
22
  export default _default;
@@ -60,6 +60,7 @@ function Header({
60
60
  homeLink = publicPath,
61
61
  theme: themeOverrides,
62
62
  hideNavMenu = false,
63
+ showDomainWarningDialog = true,
63
64
  ...rest
64
65
  }) {
65
66
  useWalletHiddenTopbar();
@@ -84,7 +85,15 @@ function Header({
84
85
  const _addons = typeof addons === "function" ? (builtInAddons) => addons(builtInAddons, { navigation: parsedNavigation }) : addons;
85
86
  const headerAddons = (
86
87
  // @ts-ignore
87
- /* @__PURE__ */ jsx(HeaderAddons, { formattedBlocklet, addons: _addons, sessionManagerProps })
88
+ /* @__PURE__ */ jsx(
89
+ HeaderAddons,
90
+ {
91
+ formattedBlocklet,
92
+ addons: _addons,
93
+ sessionManagerProps,
94
+ showDomainWarningDialog
95
+ }
96
+ )
88
97
  );
89
98
  return /* @__PURE__ */ jsx(OverridableThemeProvider, { theme: themeOverrides, children: /* @__PURE__ */ jsx(
90
99
  StyledUxHeader,
@@ -22,36 +22,36 @@ const translations = {
22
22
  en: {
23
23
  guest: {
24
24
  title: "Notice: You are using a temporary domain",
25
- description: "You are accessing this site through a temporary domain. For a better experience, please contact the site administrator to bind a custom domain. Using a custom domain not only makes access more convenient but also ensures your access is more secure."
25
+ description: "You are accessing this site through a temporary domain. For a better experience, please contact the site administrator to configure a custom domain. Using a custom domain not only makes access more convenient but also ensures your access is more secure."
26
26
  },
27
27
  owner: {
28
- title: "Enhance Website Security",
29
- description: "Dear administrator, we recommend binding your custom domain soon, which will:",
28
+ title: "Enhance Your Website Security",
29
+ description: "Dear administrator, we recommend configuring your custom domain immediately, which will:",
30
30
  benefits1: "Automatically obtain HTTPS certificates to ensure secure data transmission",
31
31
  benefits2: "Create an exclusive brand image and increase website credibility",
32
32
  benefits3: "Get a shorter, more memorable access address",
33
33
  benefits4: "Provide visitors with a more professional experience",
34
- benefits5: "Domain binding takes just minutes to complete, taking your website to the next level!"
34
+ benefits5: "Domain configuration takes just minutes to complete, taking your website to the next level!"
35
35
  },
36
36
  skip: "Remind Me Later",
37
- bindDomain: "Bind Domain"
37
+ bindDomain: "Configure Domain"
38
38
  },
39
39
  zh: {
40
40
  guest: {
41
41
  title: "\u6E29\u99A8\u63D0\u793A\uFF1A\u5F53\u524D\u4F7F\u7528\u7684\u662F\u4E34\u65F6\u57DF\u540D",
42
- description: "\u60A8\u6B63\u5728\u901A\u8FC7\u4E34\u65F6\u57DF\u540D\u8BBF\u95EE\u672C\u7AD9\u70B9\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684\u8BBF\u95EE\u4F53\u9A8C\uFF0C\u8BF7\u8054\u7CFB\u7AD9\u70B9\u7BA1\u7406\u5458\u7ED1\u5B9A\u81EA\u5B9A\u4E49\u57DF\u540D\u3002\u4F7F\u7528\u81EA\u5B9A\u4E49\u57DF\u540D\u4E0D\u4EC5\u8BBF\u95EE\u66F4\u4FBF\u6377\uFF0C\u8FD8\u80FD\u786E\u4FDD\u60A8\u7684\u8BBF\u95EE\u66F4\u52A0\u5B89\u5168\u3002"
42
+ description: "\u60A8\u6B63\u5728\u901A\u8FC7\u4E34\u65F6\u57DF\u540D\u8BBF\u95EE\u672C\u7AD9\u70B9\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684\u8BBF\u95EE\u4F53\u9A8C\uFF0C\u8BF7\u8054\u7CFB\u7AD9\u70B9\u7BA1\u7406\u5458\u914D\u7F6E\u81EA\u5B9A\u4E49\u57DF\u540D\u3002\u4F7F\u7528\u81EA\u5B9A\u4E49\u57DF\u540D\u4E0D\u4EC5\u8BBF\u95EE\u66F4\u4FBF\u6377\uFF0C\u8FD8\u80FD\u786E\u4FDD\u60A8\u7684\u8BBF\u95EE\u66F4\u52A0\u5B89\u5168\u3002"
43
43
  },
44
44
  owner: {
45
45
  title: "\u63D0\u5347\u7F51\u7AD9\u5B89\u5168\u6027\u4E0E\u4E13\u4E1A\u5EA6",
46
- description: "\u5C0A\u656C\u7684\u7BA1\u7406\u5458\uFF0C\u6211\u4EEC\u5EFA\u8BAE\u60A8\u5C3D\u5FEB\u7ED1\u5B9A\u81EA\u5B9A\u4E49\u57DF\u540D\uFF0C\u8FD9\u6837\u53EF\u4EE5\uFF1A",
46
+ description: "\u5C0A\u656C\u7684\u7BA1\u7406\u5458\uFF0C\u6211\u4EEC\u5EFA\u8BAE\u60A8\u5C3D\u5FEB\u914D\u7F6E\u81EA\u5B9A\u4E49\u57DF\u540D\uFF0C\u8FD9\u6837\u53EF\u4EE5\uFF1A",
47
47
  benefits1: "\u81EA\u52A8\u83B7\u53D6 HTTPS \u8BC1\u4E66\uFF0C\u786E\u4FDD\u6570\u636E\u4F20\u8F93\u5B89\u5168",
48
48
  benefits2: "\u6253\u9020\u4E13\u5C5E\u54C1\u724C\u5F62\u8C61\uFF0C\u63D0\u5347\u7F51\u7AD9\u53EF\u4FE1\u5EA6",
49
49
  benefits3: "\u83B7\u5F97\u66F4\u7B80\u77ED\u3001\u6613\u8BB0\u7684\u8BBF\u95EE\u5730\u5740",
50
50
  benefits4: "\u4E3A\u8BBF\u5BA2\u63D0\u4F9B\u66F4\u4E13\u4E1A\u7684\u8BBF\u95EE\u4F53\u9A8C",
51
- benefits5: "\u53EA\u9700\u51E0\u5206\u949F\u5373\u53EF\u5B8C\u6210\u57DF\u540D\u7ED1\u5B9A\uFF0C\u8BA9\u60A8\u7684\u7F51\u7AD9\u66F4\u4E0A\u4E00\u5C42\u697C\uFF01"
51
+ benefits5: "\u53EA\u9700\u51E0\u5206\u949F\u5373\u53EF\u5B8C\u6210\u57DF\u540D\u914D\u7F6E\uFF0C\u5168\u9762\u63D0\u5347\u60A8\u7684\u7F51\u7AD9\u54C1\u8D28\uFF01"
52
52
  },
53
53
  skip: "\u7A0D\u540E\u63D0\u9192",
54
- bindDomain: "\u7ED1\u5B9A\u57DF\u540D"
54
+ bindDomain: "\u914D\u7F6E\u57DF\u540D"
55
55
  }
56
56
  };
57
57
  const ONE_MONTH = 1e3 * 60 * 60 * 24 * 30;
@@ -1,7 +1,7 @@
1
- declare function HeaderAddons({ formattedBlocklet, addons, showDomainWarning, sessionManagerProps }: {
1
+ declare function HeaderAddons({ formattedBlocklet, addons, showDomainWarningDialog, sessionManagerProps }: {
2
2
  formattedBlocklet: any;
3
3
  addons: any;
4
- showDomainWarning: any;
4
+ showDomainWarningDialog: any;
5
5
  sessionManagerProps: any;
6
6
  }): import("react").FunctionComponentElement<{
7
7
  children?: import("react").ReactNode | undefined;
@@ -11,7 +11,7 @@ declare namespace HeaderAddons {
11
11
  export let formattedBlocklet: any;
12
12
  export let addons: any;
13
13
  export { SessionManagerProps as sessionManagerProps };
14
- export let showDomainWarning: any;
14
+ export let showDomainWarningDialog: any;
15
15
  }
16
16
  namespace defaultProps {
17
17
  let addons_1: null;
@@ -19,8 +19,8 @@ declare namespace HeaderAddons {
19
19
  export namespace sessionManagerProps {
20
20
  let showRole: boolean;
21
21
  }
22
- let showDomainWarning_1: boolean;
23
- export { showDomainWarning_1 as showDomainWarning };
22
+ let showDomainWarningDialog_1: boolean;
23
+ export { showDomainWarningDialog_1 as showDomainWarningDialog };
24
24
  }
25
25
  }
26
26
  export default HeaderAddons;
@@ -16,7 +16,7 @@ const hasNotification = () => {
16
16
  const navigations = window?.blocklet?.navigation ?? [];
17
17
  return !!navigations.find((n) => n.id === "/userCenter/notification");
18
18
  };
19
- export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarning, sessionManagerProps }) {
19
+ export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarningDialog, sessionManagerProps }) {
20
20
  const sessionCtx = useContext(SessionContext);
21
21
  const { locale, languages } = useLocaleContext() || {};
22
22
  const { enableConnect = true, enableLocale = true } = formattedBlocklet;
@@ -71,7 +71,7 @@ export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarn
71
71
  const renderedAddons = renderAddons();
72
72
  const nodes = Array.isArray(renderedAddons) ? renderedAddons : [renderedAddons];
73
73
  const mergedNodes = [
74
- showDomainWarning ? /* @__PURE__ */ jsx(DomainWarning, { session: sessionCtx?.session, locale }) : null,
74
+ showDomainWarningDialog ? /* @__PURE__ */ jsx(DomainWarning, { session: sessionCtx?.session, locale }) : null,
75
75
  ...nodes
76
76
  ].filter(Boolean);
77
77
  return createElement(Fragment, null, ...mergedNodes);
@@ -83,12 +83,12 @@ HeaderAddons.propTypes = {
83
83
  // - PropTypes.node: 将 addons 原样传给 UX Header 组件
84
84
  addons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
85
85
  sessionManagerProps: SessionManagerProps,
86
- showDomainWarning: PropTypes.bool
86
+ showDomainWarningDialog: PropTypes.bool
87
87
  };
88
88
  HeaderAddons.defaultProps = {
89
89
  addons: null,
90
90
  sessionManagerProps: {
91
91
  showRole: true
92
92
  },
93
- showDomainWarning: true
93
+ showDomainWarningDialog: true
94
94
  };
@@ -21,6 +21,10 @@ export default function NotificationAddon({ session = {} }) {
21
21
  () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_CREATE}`,
22
22
  [userDid]
23
23
  );
24
+ const readListenEvent = useCreation(
25
+ () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_READ}`,
26
+ [userDid]
27
+ );
24
28
  const listenCallback = useCallback(
25
29
  (notification) => {
26
30
  const { receivers } = notification ?? {};
@@ -31,16 +35,27 @@ export default function NotificationAddon({ session = {} }) {
31
35
  },
32
36
  [userDid, setUnReadCount]
33
37
  );
38
+ const readListenCallback = useCallback(
39
+ (data) => {
40
+ const { receiver, readCount } = data ?? {};
41
+ if (receiver === userDid) {
42
+ setUnReadCount((x) => x - readCount);
43
+ }
44
+ },
45
+ [userDid, setUnReadCount]
46
+ );
34
47
  useEffect(() => {
35
48
  if (wsClient) {
36
49
  wsClient.on(listenEvent, listenCallback);
50
+ wsClient.on(readListenEvent, readListenCallback);
37
51
  }
38
52
  return () => {
39
53
  if (wsClient) {
40
54
  wsClient.off(listenEvent, listenCallback);
55
+ wsClient.off(readListenEvent, readListenCallback);
41
56
  }
42
57
  };
43
- }, [wsClient, setUnReadCount, listenCallback, listenEvent]);
58
+ }, [wsClient, setUnReadCount, listenCallback, listenEvent, readListenCallback, readListenEvent]);
44
59
  if (!session.user || !viewAllUrl) {
45
60
  return null;
46
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/ui-react",
3
- "version": "2.11.46",
3
+ "version": "2.11.48",
4
4
  "description": "Some useful front-end web components that can be used in Blocklets.",
5
5
  "keywords": [
6
6
  "react",
@@ -33,8 +33,8 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@abtnode/constant": "^1.16.38",
36
- "@arcblock/bridge": "^2.11.46",
37
- "@arcblock/react-hooks": "^2.11.46",
36
+ "@arcblock/bridge": "^2.11.48",
37
+ "@arcblock/react-hooks": "^2.11.48",
38
38
  "@arcblock/ws": "^1.19.9",
39
39
  "@blocklet/did-space-react": "^1.0.16",
40
40
  "@iconify-icons/logos": "^1.2.36",
@@ -84,5 +84,5 @@
84
84
  "jest": "^29.7.0",
85
85
  "unbuild": "^2.0.0"
86
86
  },
87
- "gitHead": "289036b9e8092ce23314bece14c61c6ae8a7c757"
87
+ "gitHead": "817e70f58232384efd588a37ee343d67b5007a8d"
88
88
  }
@@ -18,7 +18,16 @@ import useMobile from '../hooks/use-mobile';
18
18
  * 专门用于 (composable) blocklet 的 Dashboard 组件, 解析 blocklet meta 中 section 为 dashboard 的 navigation 数据, 渲染一个 UX Dashboard
19
19
  */
20
20
  // eslint-disable-next-line no-shadow
21
- function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessionManagerProps, links, ...rest }) {
21
+ function Dashboard({
22
+ meta,
23
+ fallbackUrl,
24
+ invalidPathFallback,
25
+ headerAddons,
26
+ sessionManagerProps,
27
+ links,
28
+ showDomainWarningDialog,
29
+ ...rest
30
+ }) {
22
31
  useWalletHiddenTopbar();
23
32
  const sessionCtx = useContext(SessionContext);
24
33
  const user = sessionCtx?.session?.user;
@@ -110,6 +119,7 @@ function Dashboard({ meta, fallbackUrl, invalidPathFallback, headerAddons, sessi
110
119
  formattedBlocklet={formattedBlocklet}
111
120
  addons={headerAddons}
112
121
  sessionManagerProps={sessionManagerProps}
122
+ showDomainWarningDialog={showDomainWarningDialog}
113
123
  />
114
124
  );
115
125
 
@@ -140,6 +150,7 @@ Dashboard.propTypes = {
140
150
  headerAddons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
141
151
  sessionManagerProps: SessionManagerProps,
142
152
  links: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
153
+ showDomainWarningDialog: PropTypes.bool,
143
154
  };
144
155
 
145
156
  Dashboard.defaultProps = {
@@ -156,6 +167,7 @@ Dashboard.defaultProps = {
156
167
  },
157
168
  },
158
169
  links: [],
170
+ showDomainWarningDialog: true,
159
171
  };
160
172
 
161
173
  export default Dashboard;
@@ -76,6 +76,7 @@ type HeaderProps = {
76
76
  prepend?: React.ReactNode;
77
77
  align?: 'left' | 'right';
78
78
  maxWidth?: false | Breakpoint;
79
+ showDomainWarningDialog?: boolean;
79
80
  };
80
81
 
81
82
  /**
@@ -92,6 +93,7 @@ function Header({
92
93
  homeLink = publicPath,
93
94
  theme: themeOverrides,
94
95
  hideNavMenu = false,
96
+ showDomainWarningDialog = true,
95
97
  ...rest
96
98
  }: HeaderProps & Omit<BoxProps, keyof HeaderProps>) {
97
99
  useWalletHiddenTopbar();
@@ -122,7 +124,12 @@ function Header({
122
124
  : addons;
123
125
  const headerAddons = (
124
126
  // @ts-ignore
125
- <HeaderAddons formattedBlocklet={formattedBlocklet} addons={_addons} sessionManagerProps={sessionManagerProps} />
127
+ <HeaderAddons
128
+ formattedBlocklet={formattedBlocklet}
129
+ addons={_addons}
130
+ sessionManagerProps={sessionManagerProps}
131
+ showDomainWarningDialog={showDomainWarningDialog}
132
+ />
126
133
  );
127
134
 
128
135
  return (
@@ -29,37 +29,37 @@ const translations = {
29
29
  guest: {
30
30
  title: 'Notice: You are using a temporary domain',
31
31
  description:
32
- 'You are accessing this site through a temporary domain. For a better experience, please contact the site administrator to bind a custom domain. Using a custom domain not only makes access more convenient but also ensures your access is more secure.',
32
+ 'You are accessing this site through a temporary domain. For a better experience, please contact the site administrator to configure a custom domain. Using a custom domain not only makes access more convenient but also ensures your access is more secure.',
33
33
  },
34
34
  owner: {
35
- title: 'Enhance Website Security',
36
- description: 'Dear administrator, we recommend binding your custom domain soon, which will:',
35
+ title: 'Enhance Your Website Security',
36
+ description: 'Dear administrator, we recommend configuring your custom domain immediately, which will:',
37
37
  benefits1: 'Automatically obtain HTTPS certificates to ensure secure data transmission',
38
38
  benefits2: 'Create an exclusive brand image and increase website credibility',
39
39
  benefits3: 'Get a shorter, more memorable access address',
40
40
  benefits4: 'Provide visitors with a more professional experience',
41
- benefits5: 'Domain binding takes just minutes to complete, taking your website to the next level!',
41
+ benefits5: 'Domain configuration takes just minutes to complete, taking your website to the next level!',
42
42
  },
43
43
  skip: 'Remind Me Later',
44
- bindDomain: 'Bind Domain',
44
+ bindDomain: 'Configure Domain',
45
45
  },
46
46
  zh: {
47
47
  guest: {
48
48
  title: '温馨提示:当前使用的是临时域名',
49
49
  description:
50
- '您正在通过临时域名访问本站点。为了获得更好的访问体验,请联系站点管理员绑定自定义域名。使用自定义域名不仅访问更便捷,还能确保您的访问更加安全。',
50
+ '您正在通过临时域名访问本站点。为了获得更好的访问体验,请联系站点管理员配置自定义域名。使用自定义域名不仅访问更便捷,还能确保您的访问更加安全。',
51
51
  },
52
52
  owner: {
53
53
  title: '提升网站安全性与专业度',
54
- description: '尊敬的管理员,我们建议您尽快绑定自定义域名,这样可以:',
54
+ description: '尊敬的管理员,我们建议您尽快配置自定义域名,这样可以:',
55
55
  benefits1: '自动获取 HTTPS 证书,确保数据传输安全',
56
56
  benefits2: '打造专属品牌形象,提升网站可信度',
57
57
  benefits3: '获得更简短、易记的访问地址',
58
58
  benefits4: '为访客提供更专业的访问体验',
59
- benefits5: '只需几分钟即可完成域名绑定,让您的网站更上一层楼!',
59
+ benefits5: '只需几分钟即可完成域名配置,全面提升您的网站品质!',
60
60
  },
61
61
  skip: '稍后提醒',
62
- bindDomain: '绑定域名',
62
+ bindDomain: '配置域名',
63
63
  },
64
64
  };
65
65
 
@@ -20,7 +20,7 @@ const hasNotification = () => {
20
20
  };
21
21
 
22
22
  // eslint-disable-next-line no-shadow
23
- export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarning, sessionManagerProps }) {
23
+ export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarningDialog, sessionManagerProps }) {
24
24
  const sessionCtx = useContext(SessionContext);
25
25
  const { locale, languages } = useLocaleContext() || {};
26
26
  const { enableConnect = true, enableLocale = true } = formattedBlocklet;
@@ -85,7 +85,7 @@ export default function HeaderAddons({ formattedBlocklet, addons, showDomainWarn
85
85
  const renderedAddons = renderAddons();
86
86
  const nodes = Array.isArray(renderedAddons) ? renderedAddons : [renderedAddons];
87
87
  const mergedNodes = [
88
- showDomainWarning ? <DomainWarning session={sessionCtx?.session} locale={locale} /> : null,
88
+ showDomainWarningDialog ? <DomainWarning session={sessionCtx?.session} locale={locale} /> : null,
89
89
  ...nodes,
90
90
  ].filter(Boolean);
91
91
 
@@ -99,7 +99,7 @@ HeaderAddons.propTypes = {
99
99
  // - PropTypes.node: 将 addons 原样传给 UX Header 组件
100
100
  addons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
101
101
  sessionManagerProps: SessionManagerProps,
102
- showDomainWarning: PropTypes.bool,
102
+ showDomainWarningDialog: PropTypes.bool,
103
103
  };
104
104
 
105
105
  HeaderAddons.defaultProps = {
@@ -107,5 +107,5 @@ HeaderAddons.defaultProps = {
107
107
  sessionManagerProps: {
108
108
  showRole: true,
109
109
  },
110
- showDomainWarning: true,
110
+ showDomainWarningDialog: true,
111
111
  };
@@ -26,13 +26,17 @@ export default function NotificationAddon({ session = {} }) {
26
26
  () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_CREATE}`,
27
27
  [userDid]
28
28
  );
29
+ const readListenEvent = useCreation(
30
+ () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_READ}`,
31
+ [userDid]
32
+ );
29
33
 
30
34
  const listenCallback = useCallback(
31
35
  (notification) => {
32
36
  const { receivers } = notification ?? {};
33
37
 
34
38
  const { receiver: notificationReceiver } = receivers[0] ?? {};
35
- // 更新列表
39
+
36
40
  if (notificationReceiver === userDid) {
37
41
  setUnReadCount((x) => x + 1);
38
42
  }
@@ -40,16 +44,29 @@ export default function NotificationAddon({ session = {} }) {
40
44
  [userDid, setUnReadCount]
41
45
  );
42
46
 
47
+ const readListenCallback = useCallback(
48
+ (data) => {
49
+ const { receiver, readCount } = data ?? {};
50
+
51
+ if (receiver === userDid) {
52
+ setUnReadCount((x) => x - readCount);
53
+ }
54
+ },
55
+ [userDid, setUnReadCount]
56
+ );
57
+
43
58
  useEffect(() => {
44
59
  if (wsClient) {
45
60
  wsClient.on(listenEvent, listenCallback);
61
+ wsClient.on(readListenEvent, readListenCallback);
46
62
  }
47
63
  return () => {
48
64
  if (wsClient) {
49
65
  wsClient.off(listenEvent, listenCallback);
66
+ wsClient.off(readListenEvent, readListenCallback);
50
67
  }
51
68
  };
52
- }, [wsClient, setUnReadCount, listenCallback, listenEvent]);
69
+ }, [wsClient, setUnReadCount, listenCallback, listenEvent, readListenCallback, readListenEvent]);
53
70
 
54
71
  if (!session.user || !viewAllUrl) {
55
72
  return null;