@blocklet/ui-react 2.13.32 → 2.13.34

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.
@@ -57,7 +57,7 @@ const Root = styled("div")`
57
57
  .footer-brand-desc {
58
58
  white-space: pre-line;
59
59
  margin-top: 16px;
60
- color: #9397a1;
60
+ color: ${(props) => props.theme.palette.text.secondary};
61
61
  }
62
62
 
63
63
  ${(props) => props.theme.breakpoints.down("sm")} {
@@ -73,7 +73,7 @@ Footer.defaultProps = {
73
73
  };
74
74
  const StyledInternalFooter = styled(InternalFooter)`
75
75
  ${({ $bordered, theme }) => `border-top: 1px solid ${$bordered && theme.palette.divider};`}
76
- color: ${({ theme }) => theme.palette.grey[400]};
76
+ color: ${({ theme }) => theme.palette.text.secondary};
77
77
  ${({ $bgcolor }) => $bgcolor && `background-color: ${$bgcolor};`}
78
78
  `;
79
79
  export default withErrorBoundary(withHideWhenEmbed(Footer), {
@@ -2,7 +2,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import PropTypes from "prop-types";
3
3
  import clsx from "clsx";
4
4
  import { Box, Container } from "@mui/material";
5
- import { grey } from "@mui/material/colors";
6
5
  import { styled } from "@arcblock/ux/lib/Theme";
7
6
  import Row from "./row.js";
8
7
  function StandardLayout({ elements, data, className, ...rest }) {
@@ -28,7 +27,7 @@ function StandardLayout({ elements, data, className, ...rest }) {
28
27
  ]
29
28
  }
30
29
  ),
31
- /* @__PURE__ */ jsx(Box, { sx: { mb: 3, borderTop: { xs: `1px solid ${grey[200]}`, md: 0 } }, children: elements.navigation })
30
+ /* @__PURE__ */ jsx(Box, { sx: ({ palette }) => ({ mb: 3, borderTop: { xs: `1px solid ${palette.grey[200]}`, md: 0 } }), children: elements.navigation })
32
31
  ] });
33
32
  } else {
34
33
  topSection = /* @__PURE__ */ jsxs(
@@ -128,7 +128,7 @@ Links.defaultProps = {
128
128
  };
129
129
  const Root = styled("div")`
130
130
  overflow: hidden;
131
- color: ${({ theme }) => theme.palette.grey[400]};
131
+ color: ${({ theme }) => theme.palette.text.secondary};
132
132
  .footer-links-inner {
133
133
  display: flex;
134
134
  justify-content: space-between;
@@ -221,7 +221,7 @@ const Root = styled("div")`
221
221
  top: 50%;
222
222
  transform: translate(0, -50%);
223
223
  height: 1em;
224
- border-left: 1px solid ${(props) => props.theme.palette.grey[400]};
224
+ border-left: 1px solid ${(props) => props.theme.palette.text.secondary};
225
225
  }
226
226
  }
227
227
  }
@@ -39,7 +39,7 @@ const Root = styled("div")`
39
39
  justify-content: center;
40
40
  gap: 20px;
41
41
  a {
42
- color: ${(props) => props.theme.palette.grey[400]};
42
+ color: ${(props) => props.theme.palette.text.secondary};
43
43
  text-decoration: none;
44
44
  transition: color 0.2s ease-in-out;
45
45
  &:hover {
@@ -70,7 +70,7 @@ export default function ConfigProfile({ user, onSave }) {
70
70
  size: "small",
71
71
  IconComponent: (props) => /* @__PURE__ */ jsx(ArrowDownwardIcon, { ...props, width: 20, height: 20 }),
72
72
  sx: {
73
- minWidth: 300,
73
+ minWidth: 200,
74
74
  "&:hover": {
75
75
  "fieldset.MuiOutlinedInput-notchedOutline": {
76
76
  borderColor: "divider"
@@ -100,7 +100,8 @@ export default function DangerZone() {
100
100
  display: "flex",
101
101
  alignItems: "center",
102
102
  gap: 1,
103
- justifyContent: "space-between"
103
+ justifyContent: "space-between",
104
+ flexWrap: "wrap"
104
105
  },
105
106
  children: [
106
107
  /* @__PURE__ */ jsxs(Box, { children: [
@@ -203,6 +203,7 @@ function EditableField({
203
203
  whiteSpace: "pre-wrap",
204
204
  ...inline ? { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" } : {}
205
205
  },
206
+ component: "div",
206
207
  onMouseEnter: handleMouseEnter,
207
208
  onMouseLeave: handleMouseLeave,
208
209
  children: renderValue ? renderValue(value) : value
@@ -1,4 +1,5 @@
1
1
  import { User } from '../../@types';
2
- export default function Notification({ user }: {
2
+ export default function Notification({ user, isMobile }: {
3
3
  user: User;
4
+ isMobile: boolean;
4
5
  }): import("react").JSX.Element;
@@ -9,6 +9,7 @@ import Toast from "@arcblock/ux/lib/Toast";
9
9
  import { getWalletDid } from "@arcblock/ux/lib/SessionUser/libs/utils";
10
10
  import { translate } from "@arcblock/ux/lib/Locale/util";
11
11
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
12
+ import DID from "@arcblock/ux/lib/DID";
12
13
  import { translations } from "../libs/locales.js";
13
14
  import WebhookItem from "./webhook-item.js";
14
15
  import { formatAxiosError } from "../libs/utils.js";
@@ -17,7 +18,8 @@ function NotificationItem({
17
18
  title,
18
19
  description,
19
20
  value,
20
- onChange
21
+ onChange,
22
+ isMobile
21
23
  }) {
22
24
  return /* @__PURE__ */ jsx(
23
25
  Switch,
@@ -31,9 +33,10 @@ function NotificationItem({
31
33
  sx: {
32
34
  fontSize: 14,
33
35
  display: "flex",
34
- flexFlow: "wrap",
36
+ flexFlow: isMobile ? "wrap" : "nowrap",
35
37
  columnGap: 1,
36
- flex: 1
38
+ flex: 1,
39
+ whiteSpace: "nowrap"
37
40
  },
38
41
  children: [
39
42
  title,
@@ -47,7 +50,7 @@ function NotificationItem({
47
50
  }
48
51
  );
49
52
  }
50
- export default function Notification({ user }) {
53
+ export default function Notification({ user, isMobile }) {
51
54
  const { locale } = useLocaleContext();
52
55
  const t = useMemoizedFn((key, data = {}) => {
53
56
  return translate(translations, key, locale, "en", data);
@@ -175,15 +178,29 @@ export default function Notification({ user }) {
175
178
  NotificationItem,
176
179
  {
177
180
  value: notifications.wallet,
181
+ isMobile,
178
182
  title: t("walletNotification"),
179
183
  onChange: (event) => handleChangeSwitch("wallet", event.target.checked),
180
- description: getWalletDid(user) && /* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", fontSize: 13, children: getWalletDid(user) })
184
+ description: getWalletDid(user) && /* @__PURE__ */ jsx(
185
+ DID,
186
+ {
187
+ did: getWalletDid(user),
188
+ showQrcode: false,
189
+ showAvatar: !isMobile,
190
+ copyable: true,
191
+ compact: true,
192
+ responsive: true,
193
+ locale,
194
+ startChars: isMobile ? 2 : 6
195
+ }
196
+ )
181
197
  }
182
198
  ),
183
199
  /* @__PURE__ */ jsx(
184
200
  NotificationItem,
185
201
  {
186
202
  value: notifications.email,
203
+ isMobile,
187
204
  onChange: (event) => handleChangeSwitch("email", event.target.checked),
188
205
  title: t("emailNotification"),
189
206
  description: user?.email && /* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", fontSize: 13, children: user?.email })
@@ -192,6 +209,7 @@ export default function Notification({ user }) {
192
209
  /* @__PURE__ */ jsx(
193
210
  NotificationItem,
194
211
  {
212
+ isMobile,
195
213
  value: notifications.push,
196
214
  title: t("pushNotification"),
197
215
  onChange: (event) => handleChangeSwitch("push", event.target.checked)
@@ -1,9 +1,10 @@
1
1
  import type { BoxProps } from '@mui/material';
2
2
  import { User, UserCenterTab } from '../../@types';
3
- export default function Settings({ user, settings, onSave, ...rest }: {
3
+ export default function Settings({ user, settings, onSave, isMobile, ...rest }: {
4
4
  user: User;
5
5
  onSave: (type: 'privacy' | 'profile') => void;
6
6
  settings: {
7
7
  userCenterTabs: UserCenterTab[];
8
8
  };
9
+ isMobile: boolean;
9
10
  } & BoxProps): import("react").JSX.Element;
@@ -18,6 +18,7 @@ export default function Settings({
18
18
  user,
19
19
  settings,
20
20
  onSave,
21
+ isMobile,
21
22
  ...rest
22
23
  }) {
23
24
  const { locale } = useLocaleContext();
@@ -47,7 +48,7 @@ export default function Settings({
47
48
  {
48
49
  label: t("notificationManagement"),
49
50
  value: "notification",
50
- content: /* @__PURE__ */ jsx(Notification, { user })
51
+ content: /* @__PURE__ */ jsx(Notification, { user, isMobile })
51
52
  },
52
53
  {
53
54
  label: t("thirdPartyLogin.title"),
@@ -82,7 +83,7 @@ export default function Settings({
82
83
  }
83
84
  }
84
85
  ].filter(Boolean);
85
- }, [user, privacyConfigList]);
86
+ }, [user, privacyConfigList, isMobile]);
86
87
  useEffect(() => {
87
88
  const id = window.location.hash.slice(1);
88
89
  if (id) {
@@ -238,7 +238,8 @@ export default function UserCenter({
238
238
  await session.refresh();
239
239
  }
240
240
  return null;
241
- }
241
+ },
242
+ isMobile
242
243
  }
243
244
  );
244
245
  }, [userState.data, userCenterTabs, privacyState.data, privacyState.runAsync]);
@@ -452,7 +453,7 @@ export default function UserCenter({
452
453
  fontWeight: 400
453
454
  }
454
455
  },
455
- ".MuiTabs-scroller": {
456
+ ".MuiTabs-root": {
456
457
  "&:after": {
457
458
  content: '""',
458
459
  display: "block",
@@ -20,6 +20,7 @@ import {
20
20
  useMediaQuery
21
21
  } from "@mui/material";
22
22
  import { memo, useEffect } from "react";
23
+ import { mergeSx } from "@arcblock/ux/lib/Util/style";
23
24
  import useMobile from "../../hooks/use-mobile.js";
24
25
  import UserSessionInfo from "./user-session-info.js";
25
26
  import { client } from "../../libs/client.js";
@@ -33,6 +34,11 @@ const parseUa = (ua) => {
33
34
  const result = parser.getResult();
34
35
  return result;
35
36
  };
37
+ const textRightStyle = {
38
+ display: "flex",
39
+ justifyContent: "flex-end",
40
+ textAlign: "right"
41
+ };
36
42
  const queue = new PQueue({ concurrency: 1 });
37
43
  const UserSessionIp = memo(({ userSession, isMobile = false }) => {
38
44
  const currentState = useReactive({
@@ -49,13 +55,25 @@ const UserSessionIp = memo(({ userSession, isMobile = false }) => {
49
55
  }
50
56
  });
51
57
  }, [currentState, userSession.lastLoginIp]);
52
- return /* @__PURE__ */ jsx(Box, { ...isMobile && { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 1 }, children: currentState.ipRegion ? /* @__PURE__ */ jsxs(Fragment, { children: [
53
- /* @__PURE__ */ jsx(Typography, { variant: "body2", children: currentState.ipRegion }),
54
- /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "grey", children: userSession.lastLoginIp || t("unknown") })
55
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
56
- /* @__PURE__ */ jsx(Typography, { children: userSession.lastLoginIp || t("unknown") }),
57
- currentState.loading ? /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "grey", sx: { textAlign: "center" }, children: /* @__PURE__ */ jsx(CircularProgress, { size: 12, color: "inherit" }) }) : null
58
- ] }) });
58
+ return /* @__PURE__ */ jsx(
59
+ Box,
60
+ {
61
+ ...isMobile && {
62
+ display: "flex",
63
+ alignItems: "center",
64
+ justifyContent: "flex-end",
65
+ gap: 1,
66
+ flexWrap: "wrap"
67
+ },
68
+ children: currentState.ipRegion ? /* @__PURE__ */ jsxs(Fragment, { children: [
69
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: currentState.ipRegion }),
70
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "grey", children: userSession.lastLoginIp || t("unknown") })
71
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
72
+ /* @__PURE__ */ jsx(Typography, { children: userSession.lastLoginIp || t("unknown") }),
73
+ currentState.loading ? /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "grey", sx: { textAlign: "center" }, children: /* @__PURE__ */ jsx(CircularProgress, { size: 12, color: "inherit" }) }) : null
74
+ ] })
75
+ }
76
+ );
59
77
  });
60
78
  export default function UserSessions({
61
79
  user,
@@ -115,6 +133,9 @@ export default function UserSessions({
115
133
  }
116
134
  return userSessionsCountMap[status] === 0;
117
135
  }, [safeData, currentVisitorId]);
136
+ const mergeStyle = useCreation(() => {
137
+ return mergeSx({}, isMobile ? textRightStyle : {});
138
+ }, [isMobile]);
118
139
  const logout = useMemoizedFn(({ visitorId }) => {
119
140
  confirmApi.open({
120
141
  title: t("logoutThisSession"),
@@ -210,8 +231,8 @@ export default function UserSessions({
210
231
  options: {
211
232
  customBodyRenderLite: (rawIndex) => {
212
233
  const x = safeData[rawIndex];
213
- const result = parseUa(x.ua);
214
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: [result.os?.name, result.os?.version].filter(Boolean).join("/") || t("unknown") });
234
+ const result = parseUa(x?.ua);
235
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: [result.os?.name, result.os?.version].filter(Boolean).join("/") || t("unknown") });
215
236
  }
216
237
  }
217
238
  },
@@ -221,8 +242,8 @@ export default function UserSessions({
221
242
  options: {
222
243
  customBodyRenderLite: (rawIndex) => {
223
244
  const x = safeData[rawIndex];
224
- const result = parseUa(x.ua);
225
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: [result.browser?.name, result.browser?.version].filter(Boolean).join("/") || t("unknown") });
245
+ const result = parseUa(x?.ua);
246
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: [result.browser?.name, result.browser?.version].filter(Boolean).join("/") || t("unknown") });
226
247
  }
227
248
  }
228
249
  },
@@ -232,7 +253,7 @@ export default function UserSessions({
232
253
  options: {
233
254
  customBodyRenderLite: (rawIndex) => {
234
255
  const x = safeData[rawIndex];
235
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.extra?.walletOS || t("unknown") });
256
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.extra?.walletOS || t("unknown") });
236
257
  }
237
258
  }
238
259
  },
@@ -242,7 +263,7 @@ export default function UserSessions({
242
263
  options: {
243
264
  customBodyRenderLite: (rawIndex) => {
244
265
  const x = safeData[rawIndex];
245
- return /* @__PURE__ */ jsx(Box, { sx: { minWidth: 150, maxWidth: 250, ...isMobile && { textAlign: "right" } }, children: /* @__PURE__ */ jsx(UserSessionInfo, { sessionUser: x.user, user }) });
266
+ return /* @__PURE__ */ jsx(Box, { sx: mergeSx({ minWidth: 150, maxWidth: 250 }, isMobile ? textRightStyle : {}), children: /* @__PURE__ */ jsx(UserSessionInfo, { sessionUser: x.user, user }) });
246
267
  }
247
268
  }
248
269
  },
@@ -252,7 +273,7 @@ export default function UserSessions({
252
273
  options: {
253
274
  customBodyRenderLite: (rawIndex) => {
254
275
  const x = safeData[rawIndex];
255
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.createdAt ? /* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale }) : t("unknown") });
276
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.createdAt ? /* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale }) : t("unknown") });
256
277
  }
257
278
  }
258
279
  },
@@ -262,7 +283,7 @@ export default function UserSessions({
262
283
  options: {
263
284
  customBodyRenderLite: (rawIndex) => {
264
285
  const x = safeData[rawIndex];
265
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.status === "expired" ? t("expired") : /* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale }) });
286
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.status === "expired" ? t("expired") : /* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale }) });
266
287
  }
267
288
  }
268
289
  },
@@ -282,7 +303,7 @@ export default function UserSessions({
282
303
  options: {
283
304
  customBodyRenderLite: (rawIndex) => {
284
305
  const x = safeData[rawIndex];
285
- return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: /* @__PURE__ */ jsx(
306
+ return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: /* @__PURE__ */ jsx(
286
307
  Button,
287
308
  {
288
309
  sx: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/ui-react",
3
- "version": "2.13.32",
3
+ "version": "2.13.34",
4
4
  "description": "Some useful front-end web components that can be used in Blocklets.",
5
5
  "keywords": [
6
6
  "react",
@@ -34,8 +34,8 @@
34
34
  "dependencies": {
35
35
  "@abtnode/constant": "^1.16.43",
36
36
  "@abtnode/util": "^1.16.43",
37
- "@arcblock/bridge": "^2.13.32",
38
- "@arcblock/react-hooks": "^2.13.32",
37
+ "@arcblock/bridge": "^2.13.34",
38
+ "@arcblock/react-hooks": "^2.13.34",
39
39
  "@arcblock/ws": "^1.20.8",
40
40
  "@blocklet/constant": "^1.16.43",
41
41
  "@blocklet/did-space-react": "^1.0.51",
@@ -94,5 +94,5 @@
94
94
  "jest": "^29.7.0",
95
95
  "unbuild": "^2.0.0"
96
96
  },
97
- "gitHead": "87fa6cebba886885a5c2ac78c786c71599fb5f7a"
97
+ "gitHead": "2dd874ee643777fe089a0d02183543497d0c8f39"
98
98
  }
@@ -68,7 +68,7 @@ const Root = styled('div')`
68
68
  .footer-brand-desc {
69
69
  white-space: pre-line;
70
70
  margin-top: 16px;
71
- color: #9397a1;
71
+ color: ${(props) => props.theme.palette.text.secondary};
72
72
  }
73
73
 
74
74
  ${(props) => props.theme.breakpoints.down('sm')} {
@@ -89,7 +89,7 @@ Footer.defaultProps = {
89
89
 
90
90
  const StyledInternalFooter = styled(InternalFooter)`
91
91
  ${({ $bordered, theme }) => `border-top: 1px solid ${$bordered && theme.palette.divider};`}
92
- color: ${({ theme }) => theme.palette.grey[400]};
92
+ color: ${({ theme }) => theme.palette.text.secondary};
93
93
  ${({ $bgcolor }) => $bgcolor && `background-color: ${$bgcolor};`}
94
94
  `;
95
95
 
@@ -1,7 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import clsx from 'clsx';
3
3
  import { Box, Container } from '@mui/material';
4
- import { grey } from '@mui/material/colors';
5
4
  import { styled } from '@arcblock/ux/lib/Theme';
6
5
 
7
6
  import Row from './row';
@@ -31,7 +30,9 @@ function StandardLayout({ elements, data, className, ...rest }) {
31
30
  <Box>{elements.brand}</Box>
32
31
  <Box lineHeight={1}>{elements.socialMedia}</Box>
33
32
  </Box>
34
- <Box sx={{ mb: 3, borderTop: { xs: `1px solid ${grey[200]}`, md: 0 } }}>{elements.navigation}</Box>
33
+ <Box sx={({ palette }) => ({ mb: 3, borderTop: { xs: `1px solid ${palette.grey[200]}`, md: 0 } })}>
34
+ {elements.navigation}
35
+ </Box>
35
36
  </Container>
36
37
  );
37
38
  } else {
@@ -167,7 +167,7 @@ Links.defaultProps = {
167
167
 
168
168
  const Root = styled('div')`
169
169
  overflow: hidden;
170
- color: ${({ theme }) => theme.palette.grey[400]};
170
+ color: ${({ theme }) => theme.palette.text.secondary};
171
171
  .footer-links-inner {
172
172
  display: flex;
173
173
  justify-content: space-between;
@@ -260,7 +260,7 @@ const Root = styled('div')`
260
260
  top: 50%;
261
261
  transform: translate(0, -50%);
262
262
  height: 1em;
263
- border-left: 1px solid ${(props) => props.theme.palette.grey[400]};
263
+ border-left: 1px solid ${(props) => props.theme.palette.text.secondary};
264
264
  }
265
265
  }
266
266
  }
@@ -46,7 +46,7 @@ const Root = styled('div')`
46
46
  justify-content: center;
47
47
  gap: 20px;
48
48
  a {
49
- color: ${(props) => props.theme.palette.grey[400]};
49
+ color: ${(props) => props.theme.palette.text.secondary};
50
50
  text-decoration: none;
51
51
  transition: color 0.2s ease-in-out;
52
52
  &:hover {
@@ -69,7 +69,7 @@ export default function ConfigProfile({ user, onSave }: { user: User; onSave: (t
69
69
  // eslint-disable-next-line react/no-unstable-nested-components
70
70
  IconComponent={(props) => <ArrowDownwardIcon {...props} width={20} height={20} />}
71
71
  sx={{
72
- minWidth: 300,
72
+ minWidth: 200,
73
73
  '&:hover': {
74
74
  'fieldset.MuiOutlinedInput-notchedOutline': {
75
75
  borderColor: 'divider',
@@ -110,6 +110,7 @@ export default function DangerZone() {
110
110
  alignItems: 'center',
111
111
  gap: 1,
112
112
  justifyContent: 'space-between',
113
+ flexWrap: 'wrap',
113
114
  }}>
114
115
  <Box>
115
116
  <Typography
@@ -230,6 +230,7 @@ function EditableField({
230
230
  whiteSpace: 'pre-wrap',
231
231
  ...(inline ? { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } : {}),
232
232
  }}
233
+ component="div"
233
234
  onMouseEnter={handleMouseEnter}
234
235
  onMouseLeave={handleMouseLeave}>
235
236
  {renderValue ? renderValue(value) : value}
@@ -10,6 +10,7 @@ import { getWalletDid } from '@arcblock/ux/lib/SessionUser/libs/utils';
10
10
  import { translate } from '@arcblock/ux/lib/Locale/util';
11
11
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
12
12
  import { AxiosError } from 'axios';
13
+ import DID from '@arcblock/ux/lib/DID';
13
14
 
14
15
  import { translations } from '../libs/locales';
15
16
  import WebhookItem from './webhook-item';
@@ -22,11 +23,13 @@ function NotificationItem({
22
23
  description,
23
24
  value,
24
25
  onChange,
26
+ isMobile,
25
27
  }: {
26
28
  title?: string;
27
29
  description?: React.ReactNode;
28
30
  value: boolean;
29
31
  onChange: (event: ChangeEvent<HTMLInputElement>) => void;
32
+ isMobile: boolean;
30
33
  }) {
31
34
  return (
32
35
  <Switch
@@ -38,9 +41,10 @@ function NotificationItem({
38
41
  sx={{
39
42
  fontSize: 14,
40
43
  display: 'flex',
41
- flexFlow: 'wrap',
44
+ flexFlow: isMobile ? 'wrap' : 'nowrap',
42
45
  columnGap: 1,
43
46
  flex: 1,
47
+ whiteSpace: 'nowrap',
44
48
  }}>
45
49
  {title}
46
50
  {description}
@@ -53,7 +57,7 @@ function NotificationItem({
53
57
  );
54
58
  }
55
59
 
56
- export default function Notification({ user }: { user: User }) {
60
+ export default function Notification({ user, isMobile }: { user: User; isMobile: boolean }) {
57
61
  const { locale } = useLocaleContext();
58
62
  const t = useMemoizedFn((key, data = {}) => {
59
63
  return translate(translations, key, locale, 'en', data);
@@ -184,18 +188,27 @@ export default function Notification({ user }: { user: User }) {
184
188
  }}>
185
189
  <NotificationItem
186
190
  value={notifications.wallet}
191
+ isMobile={isMobile}
187
192
  title={t('walletNotification')}
188
193
  onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('wallet', event.target.checked)}
189
194
  description={
190
195
  getWalletDid(user) && (
191
- <Typography component="span" color="text.secondary" fontSize={13}>
192
- {getWalletDid(user)}
193
- </Typography>
196
+ <DID
197
+ did={getWalletDid(user)}
198
+ showQrcode={false}
199
+ showAvatar={!isMobile}
200
+ copyable
201
+ compact
202
+ responsive
203
+ locale={locale}
204
+ startChars={isMobile ? 2 : 6}
205
+ />
194
206
  )
195
207
  }
196
208
  />
197
209
  <NotificationItem
198
210
  value={notifications.email}
211
+ isMobile={isMobile}
199
212
  onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('email', event.target.checked)}
200
213
  title={t('emailNotification')}
201
214
  description={
@@ -207,6 +220,7 @@ export default function Notification({ user }: { user: User }) {
207
220
  }
208
221
  />
209
222
  <NotificationItem
223
+ isMobile={isMobile}
210
224
  value={notifications.push}
211
225
  title={t('pushNotification')}
212
226
  onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('push', event.target.checked)}
@@ -20,6 +20,7 @@ export default function Settings({
20
20
  user,
21
21
  settings,
22
22
  onSave,
23
+ isMobile,
23
24
  ...rest
24
25
  }: {
25
26
  user: User;
@@ -27,6 +28,7 @@ export default function Settings({
27
28
  settings: {
28
29
  userCenterTabs: UserCenterTab[];
29
30
  };
31
+ isMobile: boolean;
30
32
  } & BoxProps) {
31
33
  const { locale } = useLocaleContext();
32
34
  const browser = useBrowser();
@@ -57,7 +59,7 @@ export default function Settings({
57
59
  {
58
60
  label: t('notificationManagement'),
59
61
  value: 'notification',
60
- content: <Notification user={user} />,
62
+ content: <Notification user={user} isMobile={isMobile} />,
61
63
  },
62
64
  {
63
65
  label: t('thirdPartyLogin.title'),
@@ -91,7 +93,7 @@ export default function Settings({
91
93
  },
92
94
  },
93
95
  ].filter(Boolean);
94
- }, [user, privacyConfigList]);
96
+ }, [user, privacyConfigList, isMobile]);
95
97
 
96
98
  // 支持 hash 锚点定位
97
99
  useEffect(() => {
@@ -286,6 +286,7 @@ export default function UserCenter({
286
286
  }
287
287
  return null;
288
288
  }}
289
+ isMobile={isMobile}
289
290
  />
290
291
  );
291
292
  }, [userState.data, userCenterTabs, privacyState.data, privacyState.runAsync]);
@@ -533,7 +534,7 @@ export default function UserCenter({
533
534
  fontWeight: 400,
534
535
  },
535
536
  },
536
- '.MuiTabs-scroller': {
537
+ '.MuiTabs-root': {
537
538
  '&:after': {
538
539
  content: '""',
539
540
  display: 'block',
@@ -22,6 +22,7 @@ import {
22
22
  } from '@mui/material';
23
23
  import { memo, ReactElement, useEffect } from 'react';
24
24
  import { UserSession } from '@blocklet/js-sdk';
25
+ import { mergeSx } from '@arcblock/ux/lib/Util/style';
25
26
 
26
27
  import useMobile from '../../hooks/use-mobile';
27
28
  import UserSessionInfo from './user-session-info';
@@ -39,6 +40,12 @@ const parseUa = (ua: string) => {
39
40
  return result;
40
41
  };
41
42
 
43
+ const textRightStyle = {
44
+ display: 'flex',
45
+ justifyContent: 'flex-end',
46
+ textAlign: 'right',
47
+ };
48
+
42
49
  const queue = new PQueue({ concurrency: 1 });
43
50
 
44
51
  const UserSessionIp = memo(({ userSession, isMobile = false }: { userSession: any; isMobile: boolean }) => {
@@ -60,7 +67,14 @@ const UserSessionIp = memo(({ userSession, isMobile = false }: { userSession: an
60
67
  }, [currentState, userSession.lastLoginIp]);
61
68
 
62
69
  return (
63
- <Box {...(isMobile && { display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 1 })}>
70
+ <Box
71
+ {...(isMobile && {
72
+ display: 'flex',
73
+ alignItems: 'center',
74
+ justifyContent: 'flex-end',
75
+ gap: 1,
76
+ flexWrap: 'wrap',
77
+ })}>
64
78
  {currentState.ipRegion ? (
65
79
  <>
66
80
  <Typography variant="body2">{currentState.ipRegion}</Typography>
@@ -160,6 +174,10 @@ export default function UserSessions({
160
174
  return userSessionsCountMap[status] === 0;
161
175
  }, [safeData, currentVisitorId]);
162
176
 
177
+ const mergeStyle = useCreation(() => {
178
+ return mergeSx({}, isMobile ? textRightStyle : {});
179
+ }, [isMobile]);
180
+
163
181
  const logout = useMemoizedFn(({ visitorId }) => {
164
182
  confirmApi.open({
165
183
  title: t('logoutThisSession'),
@@ -249,11 +267,9 @@ export default function UserSessions({
249
267
  options: {
250
268
  customBodyRenderLite: (rawIndex: number) => {
251
269
  const x = safeData[rawIndex];
252
- const result = parseUa(x.ua);
270
+ const result = parseUa(x?.ua);
253
271
  return (
254
- <Box sx={isMobile ? { textAlign: 'right' } : {}}>
255
- {[result.os?.name, result.os?.version].filter(Boolean).join('/') || t('unknown')}
256
- </Box>
272
+ <Box sx={mergeStyle}>{[result.os?.name, result.os?.version].filter(Boolean).join('/') || t('unknown')}</Box>
257
273
  );
258
274
  },
259
275
  },
@@ -264,9 +280,9 @@ export default function UserSessions({
264
280
  options: {
265
281
  customBodyRenderLite: (rawIndex: number) => {
266
282
  const x = safeData[rawIndex];
267
- const result = parseUa(x.ua);
283
+ const result = parseUa(x?.ua);
268
284
  return (
269
- <Box sx={isMobile ? { textAlign: 'right' } : {}}>
285
+ <Box sx={mergeStyle}>
270
286
  {[result.browser?.name, result.browser?.version].filter(Boolean).join('/') || t('unknown')}
271
287
  </Box>
272
288
  );
@@ -279,7 +295,7 @@ export default function UserSessions({
279
295
  options: {
280
296
  customBodyRenderLite: (rawIndex: number) => {
281
297
  const x = safeData[rawIndex];
282
- return <Box sx={isMobile ? { textAlign: 'right' } : {}}>{x.extra?.walletOS || t('unknown')}</Box>;
298
+ return <Box sx={mergeStyle}>{x.extra?.walletOS || t('unknown')}</Box>;
283
299
  },
284
300
  },
285
301
  },
@@ -290,7 +306,7 @@ export default function UserSessions({
290
306
  customBodyRenderLite: (rawIndex: number) => {
291
307
  const x = safeData[rawIndex];
292
308
  return (
293
- <Box sx={{ minWidth: 150, maxWidth: 250, ...(isMobile && { textAlign: 'right' }) }}>
309
+ <Box sx={mergeSx({ minWidth: 150, maxWidth: 250 }, isMobile ? textRightStyle : {})}>
294
310
  <UserSessionInfo sessionUser={x.user} user={user} />
295
311
  </Box>
296
312
  );
@@ -304,7 +320,7 @@ export default function UserSessions({
304
320
  customBodyRenderLite: (rawIndex: number) => {
305
321
  const x = safeData[rawIndex];
306
322
  return (
307
- <Box sx={isMobile ? { textAlign: 'right' } : {}}>
323
+ <Box sx={mergeStyle}>
308
324
  {x.createdAt ? (
309
325
  <RelativeTime value={x.createdAt} relativeRange={3 * 86400 * 1000} locale={locale} />
310
326
  ) : (
@@ -322,7 +338,7 @@ export default function UserSessions({
322
338
  customBodyRenderLite: (rawIndex: number) => {
323
339
  const x = safeData[rawIndex];
324
340
  return (
325
- <Box sx={isMobile ? { textAlign: 'right' } : {}}>
341
+ <Box sx={mergeStyle}>
326
342
  {x.status === 'expired' ? (
327
343
  t('expired')
328
344
  ) : (
@@ -350,7 +366,7 @@ export default function UserSessions({
350
366
  customBodyRenderLite: (rawIndex: number) => {
351
367
  const x = safeData[rawIndex];
352
368
  return (
353
- <Box sx={isMobile ? { textAlign: 'right' } : {}}>
369
+ <Box sx={mergeStyle}>
354
370
  <Button
355
371
  sx={{
356
372
  whiteSpace: 'nowrap',