@blocklet/ui-react 2.11.28 → 2.11.30

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.
@@ -20,7 +20,7 @@ function Disconnect() {
20
20
  }
21
21
  }
22
22
  ),
23
- /* @__PURE__ */ jsx(DIDSpaceConnect, { session, onSuccess })
23
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(DIDSpaceConnect, { session, onSuccess }) })
24
24
  ] });
25
25
  }
26
26
  export default Disconnect;
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import Center from "@arcblock/ux/lib/Center";
3
- import { LocaleProvider } from "@arcblock/ux/lib/Locale/context";
3
+ import { LocaleProvider, useLocaleContext } from "@arcblock/ux/lib/Locale/context";
4
4
  import styled from "@emotion/styled";
5
5
  import { Box, CircularProgress } from "@mui/material";
6
6
  import { useConfigUserSpaceContext } from "../../../contexts/config-user-space.js";
@@ -9,10 +9,11 @@ import Disconnect from "./disconnect.js";
9
9
  import { translations } from "../../libs/locales.js";
10
10
  function DidSpace() {
11
11
  const { spaceGateway, hasStorageEndpoint, loading } = useConfigUserSpaceContext();
12
+ const { locale } = useLocaleContext();
12
13
  if (loading) {
13
14
  return /* @__PURE__ */ jsx(Center, { relative: "parent", children: /* @__PURE__ */ jsx(CircularProgress, {}) });
14
15
  }
15
- return /* @__PURE__ */ jsx(LocaleProvider, { translations, children: /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Box, { maxWidth: "720px", children: hasStorageEndpoint ? /* @__PURE__ */ jsx(Connected, { spaceGateway }) : /* @__PURE__ */ jsx(Disconnect, {}) }) }) });
16
+ return /* @__PURE__ */ jsx(LocaleProvider, { translations, locale, children: /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Box, { maxWidth: "720px", children: hasStorageEndpoint ? /* @__PURE__ */ jsx(Connected, { spaceGateway }) : /* @__PURE__ */ jsx(Disconnect, {}) }) }) });
16
17
  }
17
18
  const Container = styled(Box)`
18
19
  height: 100%;
@@ -1,17 +1,46 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import Badge from "@mui/material/Badge";
3
3
  import PropTypes from "prop-types";
4
+ import { useCallback, useEffect } from "react";
4
5
  import { temp as colors } from "@arcblock/ux/lib/Colors";
5
6
  import { IconButton } from "@mui/material";
6
7
  import NotificationsOutlinedIcon from "@arcblock/icons/lib/Notification";
7
8
  import { useCreation } from "ahooks";
9
+ import { EVENTS } from "@abtnode/constant";
10
+ import { useListenWsClient } from "./ws.js";
8
11
  export default function NotificationAddon({ session = {} }) {
9
- const { unReadCount } = session;
12
+ const { unReadCount, user, setUnReadCount } = session;
13
+ const userDid = useCreation(() => user?.did, [user]);
10
14
  const viewAllUrl = useCreation(() => {
11
15
  const { navigation } = window.blocklet ?? {};
12
16
  const notification = navigation?.find((x) => x.id === "/userCenter/notification");
13
17
  return notification?.link;
14
18
  });
19
+ const wsClient = useListenWsClient("user");
20
+ const listenEvent = useCreation(
21
+ () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_CREATE}`,
22
+ [userDid]
23
+ );
24
+ const listenCallback = useCallback(
25
+ (notification) => {
26
+ const { receivers } = notification ?? {};
27
+ const { receiver: notificationReceiver } = receivers[0] ?? {};
28
+ if (notificationReceiver === userDid) {
29
+ setUnReadCount((x) => x + 1);
30
+ }
31
+ },
32
+ [userDid, setUnReadCount]
33
+ );
34
+ useEffect(() => {
35
+ if (wsClient) {
36
+ wsClient.on(listenEvent, listenCallback);
37
+ }
38
+ return () => {
39
+ if (wsClient) {
40
+ wsClient.off(listenEvent, listenCallback);
41
+ }
42
+ };
43
+ }, [wsClient, setUnReadCount, listenCallback, listenEvent]);
15
44
  if (!session.user || !viewAllUrl) {
16
45
  return null;
17
46
  }
@@ -28,7 +57,7 @@ export default function NotificationAddon({ session = {} }) {
28
57
  borderRadius: "50%"
29
58
  }
30
59
  },
31
- children: /* @__PURE__ */ jsx(Badge, { variant: "dot", color: "error", invisible: unReadCount === 0, children: /* @__PURE__ */ jsx(NotificationsOutlinedIcon, { style: { width: "auto", height: 24 } }) })
60
+ children: /* @__PURE__ */ jsx(Badge, { badgeContent: unReadCount, color: "error", invisible: unReadCount === 0, children: /* @__PURE__ */ jsx(NotificationsOutlinedIcon, { style: { width: "auto", height: 24 } }) })
32
61
  }
33
62
  );
34
63
  }
@@ -0,0 +1,3 @@
1
+ export function create(endpoint?: string): any;
2
+ export default function getWsClient(endpoint?: string): any;
3
+ export function useListenWsClient(endpoint?: string): any;
@@ -0,0 +1,37 @@
1
+ import { useContext } from 'react';
2
+ import Cookie from 'js-cookie';
3
+ import { WsClient } from '@arcblock/ws';
4
+ import { SessionContext } from '@arcblock/did-connect/lib/Session';
5
+
6
+ const client = {};
7
+
8
+ export function create(endpoint = 'admin') {
9
+ const pathPrefix = (window.env && window.env.apiPrefix ? window.env.apiPrefix : '/').replace(/\/$/, '');
10
+ const url = `//${window.location.host}${pathPrefix}/.well-known/service/${endpoint}`;
11
+ return new WsClient(url, {
12
+ heartbeatIntervalMs: 100 * 1000,
13
+ params: () => ({
14
+ token: Cookie.get('login_token'),
15
+ }),
16
+ });
17
+ }
18
+
19
+ export default function getWsClient(endpoint = 'admin') {
20
+ if (!client[endpoint]) {
21
+ client[endpoint] = create(endpoint);
22
+ }
23
+
24
+ return client[endpoint];
25
+ }
26
+
27
+ export const useListenWsClient = (endpoint = 'admin') => {
28
+ const sessionCtx = useContext(SessionContext);
29
+ const { session } = sessionCtx ?? {};
30
+
31
+ if (!client[endpoint] && session.user) {
32
+ client[endpoint] = getWsClient(endpoint);
33
+ client[endpoint].connect();
34
+ }
35
+
36
+ return client[endpoint];
37
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/ui-react",
3
- "version": "2.11.28",
3
+ "version": "2.11.30",
4
4
  "description": "Some useful front-end web components that can be used in Blocklets.",
5
5
  "keywords": [
6
6
  "react",
@@ -32,8 +32,10 @@
32
32
  "url": "https://github.com/ArcBlock/ux/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@arcblock/bridge": "^2.11.28",
36
- "@arcblock/react-hooks": "^2.11.28",
35
+ "@abtnode/constant": "1.16.37",
36
+ "@arcblock/bridge": "^2.11.30",
37
+ "@arcblock/react-hooks": "^2.11.30",
38
+ "@arcblock/ws": "^1.19.2",
37
39
  "@blocklet/did-space-react": "^1.0.2",
38
40
  "@iconify-icons/logos": "^1.2.36",
39
41
  "@iconify-icons/material-symbols": "^1.2.58",
@@ -45,6 +47,7 @@
45
47
  "iconify-icon": "^1.0.8",
46
48
  "iconify-icons-material-symbols-400": "^0.0.1",
47
49
  "is-url": "^1.2.4",
50
+ "js-cookie": "^2.2.1",
48
51
  "lodash": "^4.17.21",
49
52
  "p-all": "^5.0.0",
50
53
  "p-queue": "^6.6.2",
@@ -81,5 +84,5 @@
81
84
  "jest": "^29.7.0",
82
85
  "unbuild": "^2.0.0"
83
86
  },
84
- "gitHead": "d5c76bd7e9d1fb74e6253a3016f6b8ccf37b77f0"
87
+ "gitHead": "a4a88b339b04b907c7f76927806324c98d4b2904"
85
88
  }
@@ -22,7 +22,9 @@ function Disconnect() {
22
22
  margin: '16px 0',
23
23
  }}
24
24
  />
25
- <DIDSpaceConnect session={session} onSuccess={onSuccess} />
25
+ <Box>
26
+ <DIDSpaceConnect session={session} onSuccess={onSuccess} />
27
+ </Box>
26
28
  </Box>
27
29
  );
28
30
  }
@@ -1,5 +1,5 @@
1
1
  import Center from '@arcblock/ux/lib/Center';
2
- import { LocaleProvider } from '@arcblock/ux/lib/Locale/context';
2
+ import { LocaleProvider, useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
3
  import styled from '@emotion/styled';
4
4
  import { Box, CircularProgress } from '@mui/material';
5
5
  import { useConfigUserSpaceContext } from '../../../contexts/config-user-space';
@@ -9,6 +9,7 @@ import { translations } from '../../libs/locales';
9
9
 
10
10
  function DidSpace() {
11
11
  const { spaceGateway, hasStorageEndpoint, loading } = useConfigUserSpaceContext();
12
+ const { locale } = useLocaleContext();
12
13
 
13
14
  if (loading) {
14
15
  return (
@@ -19,7 +20,7 @@ function DidSpace() {
19
20
  }
20
21
 
21
22
  return (
22
- <LocaleProvider translations={translations}>
23
+ <LocaleProvider translations={translations} locale={locale}>
23
24
  <Container>
24
25
  <Box maxWidth="720px">{hasStorageEndpoint ? <Connected spaceGateway={spaceGateway} /> : <Disconnect />}</Box>
25
26
  </Container>
@@ -1,14 +1,18 @@
1
1
  import Badge from '@mui/material/Badge';
2
2
  import PropTypes from 'prop-types';
3
+ import { useCallback, useEffect } from 'react';
3
4
  import { temp as colors } from '@arcblock/ux/lib/Colors';
4
5
  import { IconButton } from '@mui/material';
5
6
 
6
7
  // eslint-disable-next-line import/no-extraneous-dependencies
7
8
  import NotificationsOutlinedIcon from '@arcblock/icons/lib/Notification';
8
9
  import { useCreation } from 'ahooks';
10
+ import { EVENTS } from '@abtnode/constant';
11
+ import { useListenWsClient } from './ws';
9
12
 
10
13
  export default function NotificationAddon({ session = {} }) {
11
- const { unReadCount } = session;
14
+ const { unReadCount, user, setUnReadCount } = session;
15
+ const userDid = useCreation(() => user?.did, [user]);
12
16
 
13
17
  const viewAllUrl = useCreation(() => {
14
18
  const { navigation } = window.blocklet ?? {};
@@ -16,6 +20,37 @@ export default function NotificationAddon({ session = {} }) {
16
20
  return notification?.link;
17
21
  });
18
22
 
23
+ const wsClient = useListenWsClient('user');
24
+
25
+ const listenEvent = useCreation(
26
+ () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_CREATE}`,
27
+ [userDid]
28
+ );
29
+
30
+ const listenCallback = useCallback(
31
+ (notification) => {
32
+ const { receivers } = notification ?? {};
33
+
34
+ const { receiver: notificationReceiver } = receivers[0] ?? {};
35
+ // 更新列表
36
+ if (notificationReceiver === userDid) {
37
+ setUnReadCount((x) => x + 1);
38
+ }
39
+ },
40
+ [userDid, setUnReadCount]
41
+ );
42
+
43
+ useEffect(() => {
44
+ if (wsClient) {
45
+ wsClient.on(listenEvent, listenCallback);
46
+ }
47
+ return () => {
48
+ if (wsClient) {
49
+ wsClient.off(listenEvent, listenCallback);
50
+ }
51
+ };
52
+ }, [wsClient, setUnReadCount, listenCallback, listenEvent]);
53
+
19
54
  if (!session.user || !viewAllUrl) {
20
55
  return null;
21
56
  }
@@ -32,7 +67,7 @@ export default function NotificationAddon({ session = {} }) {
32
67
  borderRadius: '50%',
33
68
  },
34
69
  }}>
35
- <Badge variant="dot" color="error" invisible={unReadCount === 0}>
70
+ <Badge badgeContent={unReadCount} color="error" invisible={unReadCount === 0}>
36
71
  <NotificationsOutlinedIcon style={{ width: 'auto', height: 24 }} />
37
72
  </Badge>
38
73
  </IconButton>
@@ -0,0 +1,37 @@
1
+ import { useContext } from 'react';
2
+ import Cookie from 'js-cookie';
3
+ import { WsClient } from '@arcblock/ws';
4
+ import { SessionContext } from '@arcblock/did-connect/lib/Session';
5
+
6
+ const client = {};
7
+
8
+ export function create(endpoint = 'admin') {
9
+ const pathPrefix = (window.env && window.env.apiPrefix ? window.env.apiPrefix : '/').replace(/\/$/, '');
10
+ const url = `//${window.location.host}${pathPrefix}/.well-known/service/${endpoint}`;
11
+ return new WsClient(url, {
12
+ heartbeatIntervalMs: 100 * 1000,
13
+ params: () => ({
14
+ token: Cookie.get('login_token'),
15
+ }),
16
+ });
17
+ }
18
+
19
+ export default function getWsClient(endpoint = 'admin') {
20
+ if (!client[endpoint]) {
21
+ client[endpoint] = create(endpoint);
22
+ }
23
+
24
+ return client[endpoint];
25
+ }
26
+
27
+ export const useListenWsClient = (endpoint = 'admin') => {
28
+ const sessionCtx = useContext(SessionContext);
29
+ const { session } = sessionCtx ?? {};
30
+
31
+ if (!client[endpoint] && session.user) {
32
+ client[endpoint] = getWsClient(endpoint);
33
+ client[endpoint].connect();
34
+ }
35
+
36
+ return client[endpoint];
37
+ };