@blocklet/ui-react 2.13.33 → 2.13.35
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/lib/UserCenter/components/config-profile.js +1 -1
- package/lib/UserCenter/components/danger-zone.js +2 -1
- package/lib/UserCenter/components/editable-field.js +1 -0
- package/lib/UserCenter/components/notification.d.ts +2 -1
- package/lib/UserCenter/components/notification.js +23 -5
- package/lib/UserCenter/components/settings.d.ts +2 -1
- package/lib/UserCenter/components/settings.js +3 -2
- package/lib/UserCenter/components/user-center.js +3 -2
- package/lib/UserSessions/components/user-sessions.d.ts +3 -2
- package/lib/UserSessions/components/user-sessions.js +68 -27
- package/package.json +6 -6
- package/src/UserCenter/components/config-profile.tsx +1 -1
- package/src/UserCenter/components/danger-zone.tsx +1 -0
- package/src/UserCenter/components/editable-field.tsx +1 -0
- package/src/UserCenter/components/notification.tsx +19 -5
- package/src/UserCenter/components/settings.tsx +4 -2
- package/src/UserCenter/components/user-center.tsx +2 -1
- package/src/UserSessions/components/user-sessions.tsx +65 -22
|
@@ -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:
|
|
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
|
|
@@ -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(
|
|
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-
|
|
456
|
+
".MuiTabs-root": {
|
|
456
457
|
"&:after": {
|
|
457
458
|
content: '""',
|
|
458
459
|
display: "block",
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { UserSession } from '@blocklet/js-sdk';
|
|
2
2
|
import { User } from '../../@types';
|
|
3
|
-
export default function UserSessions({ user, showAction, showUser, getUserSessions, }: {
|
|
3
|
+
export default function UserSessions({ user, showAction, showUser, getUserSessions, showOffline, }: {
|
|
4
4
|
readonly user: User & {
|
|
5
5
|
userSessions?: any[];
|
|
6
6
|
};
|
|
7
7
|
readonly showAction?: boolean;
|
|
8
8
|
readonly showUser?: boolean;
|
|
9
|
+
readonly showOffline?: boolean;
|
|
9
10
|
readonly getUserSessions: (params: {
|
|
10
11
|
page: number;
|
|
11
12
|
pageSize: number;
|
|
12
|
-
status?: 'online' | 'expired';
|
|
13
|
+
status?: 'online' | 'expired' | 'offline';
|
|
13
14
|
}) => Promise<{
|
|
14
15
|
paging: {
|
|
15
16
|
total: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import Datatable from "@arcblock/ux/lib/Datatable";
|
|
3
|
-
import { useCreation, useMemoizedFn, useReactive, useRequest } from "ahooks";
|
|
3
|
+
import { useCreation, useMemoizedFn, useMount, useReactive, useRequest } from "ahooks";
|
|
4
4
|
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
5
5
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
6
6
|
import RelativeTime from "@arcblock/ux/lib/RelativeTime";
|
|
@@ -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,19 +55,32 @@ const UserSessionIp = memo(({ userSession, isMobile = false }) => {
|
|
|
49
55
|
}
|
|
50
56
|
});
|
|
51
57
|
}, [currentState, userSession.lastLoginIp]);
|
|
52
|
-
return /* @__PURE__ */ jsx(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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,
|
|
62
80
|
showAction = true,
|
|
63
81
|
showUser = true,
|
|
64
|
-
getUserSessions
|
|
82
|
+
getUserSessions,
|
|
83
|
+
showOffline = false
|
|
65
84
|
}) {
|
|
66
85
|
const filterParams = useReactive({
|
|
67
86
|
status: "online",
|
|
@@ -70,7 +89,8 @@ export default function UserSessions({
|
|
|
70
89
|
});
|
|
71
90
|
const userSessionsCountMap = useReactive({
|
|
72
91
|
online: 0,
|
|
73
|
-
expired: 0
|
|
92
|
+
expired: 0,
|
|
93
|
+
offline: 0
|
|
74
94
|
});
|
|
75
95
|
const currentVisitorId = getVisitorId();
|
|
76
96
|
const { locale } = useLocaleContext();
|
|
@@ -93,14 +113,19 @@ export default function UserSessions({
|
|
|
93
113
|
list: result?.list || []
|
|
94
114
|
};
|
|
95
115
|
});
|
|
96
|
-
|
|
97
|
-
const
|
|
116
|
+
useMount(async () => {
|
|
117
|
+
const expiredResult = await getUserSessions({
|
|
98
118
|
page: 1,
|
|
99
119
|
pageSize: 1,
|
|
100
120
|
status: "expired"
|
|
101
121
|
});
|
|
102
|
-
userSessionsCountMap.expired =
|
|
103
|
-
|
|
122
|
+
userSessionsCountMap.expired = expiredResult?.paging?.total || 0;
|
|
123
|
+
const offlineResult = await getUserSessions({
|
|
124
|
+
page: 1,
|
|
125
|
+
pageSize: 1,
|
|
126
|
+
status: "offline"
|
|
127
|
+
});
|
|
128
|
+
userSessionsCountMap.offline = offlineResult?.paging?.total || 0;
|
|
104
129
|
});
|
|
105
130
|
const pageState = useRequest(getData, {
|
|
106
131
|
refreshDeps: [filterParams.status, filterParams.page, filterParams.pageSize]
|
|
@@ -115,6 +140,9 @@ export default function UserSessions({
|
|
|
115
140
|
}
|
|
116
141
|
return userSessionsCountMap[status] === 0;
|
|
117
142
|
}, [safeData, currentVisitorId]);
|
|
143
|
+
const mergeStyle = useCreation(() => {
|
|
144
|
+
return mergeSx({}, isMobile ? textRightStyle : {});
|
|
145
|
+
}, [isMobile]);
|
|
118
146
|
const logout = useMemoizedFn(({ visitorId }) => {
|
|
119
147
|
confirmApi.open({
|
|
120
148
|
title: t("logoutThisSession"),
|
|
@@ -127,7 +155,6 @@ export default function UserSessions({
|
|
|
127
155
|
onConfirm: async () => {
|
|
128
156
|
await client.user.logout({
|
|
129
157
|
visitorId,
|
|
130
|
-
// @ts-expect-error js-sdk 1.16.43 中会包含这个参数
|
|
131
158
|
includeFederated: true
|
|
132
159
|
});
|
|
133
160
|
pageState.refresh();
|
|
@@ -152,7 +179,6 @@ export default function UserSessions({
|
|
|
152
179
|
await client.user.logout({
|
|
153
180
|
status: filterParams.status,
|
|
154
181
|
visitorId: currentVisitorId,
|
|
155
|
-
// @ts-expect-error js-sdk 1.16.43 中会包含这个参数
|
|
156
182
|
includeFederated: true
|
|
157
183
|
});
|
|
158
184
|
pageState.refresh();
|
|
@@ -210,8 +236,8 @@ export default function UserSessions({
|
|
|
210
236
|
options: {
|
|
211
237
|
customBodyRenderLite: (rawIndex) => {
|
|
212
238
|
const x = safeData[rawIndex];
|
|
213
|
-
const result = parseUa(x
|
|
214
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
239
|
+
const result = parseUa(x?.ua);
|
|
240
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: [result.os?.name, result.os?.version].filter(Boolean).join("/") || t("unknown") });
|
|
215
241
|
}
|
|
216
242
|
}
|
|
217
243
|
},
|
|
@@ -221,8 +247,8 @@ export default function UserSessions({
|
|
|
221
247
|
options: {
|
|
222
248
|
customBodyRenderLite: (rawIndex) => {
|
|
223
249
|
const x = safeData[rawIndex];
|
|
224
|
-
const result = parseUa(x
|
|
225
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
250
|
+
const result = parseUa(x?.ua);
|
|
251
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: [result.browser?.name, result.browser?.version].filter(Boolean).join("/") || t("unknown") });
|
|
226
252
|
}
|
|
227
253
|
}
|
|
228
254
|
},
|
|
@@ -232,7 +258,7 @@ export default function UserSessions({
|
|
|
232
258
|
options: {
|
|
233
259
|
customBodyRenderLite: (rawIndex) => {
|
|
234
260
|
const x = safeData[rawIndex];
|
|
235
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
261
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.extra?.walletOS || t("unknown") });
|
|
236
262
|
}
|
|
237
263
|
}
|
|
238
264
|
},
|
|
@@ -242,7 +268,7 @@ export default function UserSessions({
|
|
|
242
268
|
options: {
|
|
243
269
|
customBodyRenderLite: (rawIndex) => {
|
|
244
270
|
const x = safeData[rawIndex];
|
|
245
|
-
return /* @__PURE__ */ jsx(Box, { sx: { minWidth: 150, maxWidth: 250,
|
|
271
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeSx({ minWidth: 150, maxWidth: 250 }, isMobile ? textRightStyle : {}), children: /* @__PURE__ */ jsx(UserSessionInfo, { sessionUser: x.user, user }) });
|
|
246
272
|
}
|
|
247
273
|
}
|
|
248
274
|
},
|
|
@@ -252,17 +278,17 @@ export default function UserSessions({
|
|
|
252
278
|
options: {
|
|
253
279
|
customBodyRenderLite: (rawIndex) => {
|
|
254
280
|
const x = safeData[rawIndex];
|
|
255
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
281
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.createdAt ? /* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale }) : t("unknown") });
|
|
256
282
|
}
|
|
257
283
|
}
|
|
258
284
|
},
|
|
259
|
-
{
|
|
285
|
+
!showOffline && {
|
|
260
286
|
label: t("updatedAt"),
|
|
261
287
|
name: "updatedAt",
|
|
262
288
|
options: {
|
|
263
289
|
customBodyRenderLite: (rawIndex) => {
|
|
264
290
|
const x = safeData[rawIndex];
|
|
265
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
291
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: x.status === "expired" ? t("expired") : /* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale }) });
|
|
266
292
|
}
|
|
267
293
|
}
|
|
268
294
|
},
|
|
@@ -282,7 +308,7 @@ export default function UserSessions({
|
|
|
282
308
|
options: {
|
|
283
309
|
customBodyRenderLite: (rawIndex) => {
|
|
284
310
|
const x = safeData[rawIndex];
|
|
285
|
-
return /* @__PURE__ */ jsx(Box, { sx:
|
|
311
|
+
return /* @__PURE__ */ jsx(Box, { sx: mergeStyle, children: /* @__PURE__ */ jsx(
|
|
286
312
|
Button,
|
|
287
313
|
{
|
|
288
314
|
sx: {
|
|
@@ -400,7 +426,22 @@ export default function UserSessions({
|
|
|
400
426
|
] })
|
|
401
427
|
] })
|
|
402
428
|
}
|
|
403
|
-
)
|
|
429
|
+
),
|
|
430
|
+
showOffline ? /* @__PURE__ */ jsx(
|
|
431
|
+
FormControlLabel,
|
|
432
|
+
{
|
|
433
|
+
value: "offline",
|
|
434
|
+
control: /* @__PURE__ */ jsx(Radio, { size: "small", sx: { lineHeight: 1, fontSize: 0 }, checked: filterParams.status === "offline" }),
|
|
435
|
+
label: /* @__PURE__ */ jsxs(Typography, { sx: { display: "flex", alignItems: "center" }, children: [
|
|
436
|
+
t("offline"),
|
|
437
|
+
/* @__PURE__ */ jsxs(Typography, { component: "span", sx: { ml: 0.5, color: "text.secondary" }, children: [
|
|
438
|
+
"(",
|
|
439
|
+
userSessionsCountMap.offline,
|
|
440
|
+
")"
|
|
441
|
+
] })
|
|
442
|
+
] })
|
|
443
|
+
}
|
|
444
|
+
) : null
|
|
404
445
|
]
|
|
405
446
|
}
|
|
406
447
|
),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.35",
|
|
4
4
|
"description": "Some useful front-end web components that can be used in Blocklets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@abtnode/constant": "^1.16.43",
|
|
36
36
|
"@abtnode/util": "^1.16.43",
|
|
37
|
-
"@arcblock/bridge": "^2.13.
|
|
38
|
-
"@arcblock/react-hooks": "^2.13.
|
|
39
|
-
"@arcblock/ws": "^1.20.
|
|
37
|
+
"@arcblock/bridge": "^2.13.35",
|
|
38
|
+
"@arcblock/react-hooks": "^2.13.35",
|
|
39
|
+
"@arcblock/ws": "^1.20.10",
|
|
40
40
|
"@blocklet/constant": "^1.16.43",
|
|
41
|
-
"@blocklet/did-space-react": "^1.0.
|
|
41
|
+
"@blocklet/did-space-react": "^1.0.53",
|
|
42
42
|
"@iconify-icons/logos": "^1.2.36",
|
|
43
43
|
"@iconify-icons/material-symbols": "^1.2.58",
|
|
44
44
|
"@iconify-icons/tabler": "^1.2.95",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"jest": "^29.7.0",
|
|
95
95
|
"unbuild": "^2.0.0"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "0637c76e4c1036802b2fef273f785cc9bf00edd0"
|
|
98
98
|
}
|
|
@@ -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:
|
|
72
|
+
minWidth: 200,
|
|
73
73
|
'&:hover': {
|
|
74
74
|
'fieldset.MuiOutlinedInput-notchedOutline': {
|
|
75
75
|
borderColor: 'divider',
|
|
@@ -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
|
-
<
|
|
192
|
-
{getWalletDid(user)}
|
|
193
|
-
|
|
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-
|
|
537
|
+
'.MuiTabs-root': {
|
|
537
538
|
'&:after': {
|
|
538
539
|
content: '""',
|
|
539
540
|
display: 'block',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-nested-ternary */
|
|
2
2
|
/* eslint-disable react/no-unstable-nested-components */
|
|
3
3
|
import Datatable from '@arcblock/ux/lib/Datatable';
|
|
4
|
-
import { useCreation, useMemoizedFn, useReactive, useRequest } from 'ahooks';
|
|
4
|
+
import { useCreation, useMemoizedFn, useMount, useReactive, useRequest } from 'ahooks';
|
|
5
5
|
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
6
6
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
7
7
|
import RelativeTime from '@arcblock/ux/lib/RelativeTime';
|
|
@@ -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
|
|
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>
|
|
@@ -87,13 +101,19 @@ export default function UserSessions({
|
|
|
87
101
|
showAction = true,
|
|
88
102
|
showUser = true,
|
|
89
103
|
getUserSessions,
|
|
104
|
+
showOffline = false,
|
|
90
105
|
}: {
|
|
91
106
|
readonly user: User & {
|
|
92
107
|
userSessions?: any[];
|
|
93
108
|
};
|
|
94
109
|
readonly showAction?: boolean;
|
|
95
110
|
readonly showUser?: boolean;
|
|
96
|
-
readonly
|
|
111
|
+
readonly showOffline?: boolean;
|
|
112
|
+
readonly getUserSessions: (params: {
|
|
113
|
+
page: number;
|
|
114
|
+
pageSize: number;
|
|
115
|
+
status?: 'online' | 'expired' | 'offline';
|
|
116
|
+
}) => Promise<{
|
|
97
117
|
paging: {
|
|
98
118
|
total: number;
|
|
99
119
|
};
|
|
@@ -108,6 +128,7 @@ export default function UserSessions({
|
|
|
108
128
|
const userSessionsCountMap = useReactive({
|
|
109
129
|
online: 0,
|
|
110
130
|
expired: 0,
|
|
131
|
+
offline: 0,
|
|
111
132
|
});
|
|
112
133
|
const currentVisitorId = getVisitorId();
|
|
113
134
|
const { locale } = useLocaleContext();
|
|
@@ -121,7 +142,7 @@ export default function UserSessions({
|
|
|
121
142
|
const result = await getUserSessions({
|
|
122
143
|
page: filterParams.page,
|
|
123
144
|
pageSize: filterParams.pageSize,
|
|
124
|
-
status: filterParams.status as 'online' | 'expired',
|
|
145
|
+
status: filterParams.status as 'online' | 'expired' | 'offline',
|
|
125
146
|
});
|
|
126
147
|
|
|
127
148
|
const total = result?.paging?.total || 0;
|
|
@@ -133,14 +154,20 @@ export default function UserSessions({
|
|
|
133
154
|
};
|
|
134
155
|
});
|
|
135
156
|
|
|
136
|
-
|
|
137
|
-
const
|
|
157
|
+
useMount(async () => {
|
|
158
|
+
const expiredResult = await getUserSessions({
|
|
138
159
|
page: 1,
|
|
139
160
|
pageSize: 1,
|
|
140
161
|
status: 'expired',
|
|
141
162
|
});
|
|
142
|
-
userSessionsCountMap.expired =
|
|
143
|
-
|
|
163
|
+
userSessionsCountMap.expired = expiredResult?.paging?.total || 0;
|
|
164
|
+
|
|
165
|
+
const offlineResult = await getUserSessions({
|
|
166
|
+
page: 1,
|
|
167
|
+
pageSize: 1,
|
|
168
|
+
status: 'offline',
|
|
169
|
+
});
|
|
170
|
+
userSessionsCountMap.offline = offlineResult?.paging?.total || 0;
|
|
144
171
|
});
|
|
145
172
|
|
|
146
173
|
const pageState = useRequest(getData, {
|
|
@@ -160,6 +187,10 @@ export default function UserSessions({
|
|
|
160
187
|
return userSessionsCountMap[status] === 0;
|
|
161
188
|
}, [safeData, currentVisitorId]);
|
|
162
189
|
|
|
190
|
+
const mergeStyle = useCreation(() => {
|
|
191
|
+
return mergeSx({}, isMobile ? textRightStyle : {});
|
|
192
|
+
}, [isMobile]);
|
|
193
|
+
|
|
163
194
|
const logout = useMemoizedFn(({ visitorId }) => {
|
|
164
195
|
confirmApi.open({
|
|
165
196
|
title: t('logoutThisSession'),
|
|
@@ -172,7 +203,6 @@ export default function UserSessions({
|
|
|
172
203
|
onConfirm: async () => {
|
|
173
204
|
await client.user.logout({
|
|
174
205
|
visitorId,
|
|
175
|
-
// @ts-expect-error js-sdk 1.16.43 中会包含这个参数
|
|
176
206
|
includeFederated: true,
|
|
177
207
|
});
|
|
178
208
|
pageState.refresh();
|
|
@@ -197,7 +227,6 @@ export default function UserSessions({
|
|
|
197
227
|
await client.user.logout({
|
|
198
228
|
status: filterParams.status,
|
|
199
229
|
visitorId: currentVisitorId as string,
|
|
200
|
-
// @ts-expect-error js-sdk 1.16.43 中会包含这个参数
|
|
201
230
|
includeFederated: true,
|
|
202
231
|
});
|
|
203
232
|
pageState.refresh();
|
|
@@ -249,11 +278,9 @@ export default function UserSessions({
|
|
|
249
278
|
options: {
|
|
250
279
|
customBodyRenderLite: (rawIndex: number) => {
|
|
251
280
|
const x = safeData[rawIndex];
|
|
252
|
-
const result = parseUa(x
|
|
281
|
+
const result = parseUa(x?.ua);
|
|
253
282
|
return (
|
|
254
|
-
<Box sx={
|
|
255
|
-
{[result.os?.name, result.os?.version].filter(Boolean).join('/') || t('unknown')}
|
|
256
|
-
</Box>
|
|
283
|
+
<Box sx={mergeStyle}>{[result.os?.name, result.os?.version].filter(Boolean).join('/') || t('unknown')}</Box>
|
|
257
284
|
);
|
|
258
285
|
},
|
|
259
286
|
},
|
|
@@ -264,9 +291,9 @@ export default function UserSessions({
|
|
|
264
291
|
options: {
|
|
265
292
|
customBodyRenderLite: (rawIndex: number) => {
|
|
266
293
|
const x = safeData[rawIndex];
|
|
267
|
-
const result = parseUa(x
|
|
294
|
+
const result = parseUa(x?.ua);
|
|
268
295
|
return (
|
|
269
|
-
<Box sx={
|
|
296
|
+
<Box sx={mergeStyle}>
|
|
270
297
|
{[result.browser?.name, result.browser?.version].filter(Boolean).join('/') || t('unknown')}
|
|
271
298
|
</Box>
|
|
272
299
|
);
|
|
@@ -279,7 +306,7 @@ export default function UserSessions({
|
|
|
279
306
|
options: {
|
|
280
307
|
customBodyRenderLite: (rawIndex: number) => {
|
|
281
308
|
const x = safeData[rawIndex];
|
|
282
|
-
return <Box sx={
|
|
309
|
+
return <Box sx={mergeStyle}>{x.extra?.walletOS || t('unknown')}</Box>;
|
|
283
310
|
},
|
|
284
311
|
},
|
|
285
312
|
},
|
|
@@ -290,7 +317,7 @@ export default function UserSessions({
|
|
|
290
317
|
customBodyRenderLite: (rawIndex: number) => {
|
|
291
318
|
const x = safeData[rawIndex];
|
|
292
319
|
return (
|
|
293
|
-
<Box sx={{ minWidth: 150, maxWidth: 250,
|
|
320
|
+
<Box sx={mergeSx({ minWidth: 150, maxWidth: 250 }, isMobile ? textRightStyle : {})}>
|
|
294
321
|
<UserSessionInfo sessionUser={x.user} user={user} />
|
|
295
322
|
</Box>
|
|
296
323
|
);
|
|
@@ -304,7 +331,7 @@ export default function UserSessions({
|
|
|
304
331
|
customBodyRenderLite: (rawIndex: number) => {
|
|
305
332
|
const x = safeData[rawIndex];
|
|
306
333
|
return (
|
|
307
|
-
<Box sx={
|
|
334
|
+
<Box sx={mergeStyle}>
|
|
308
335
|
{x.createdAt ? (
|
|
309
336
|
<RelativeTime value={x.createdAt} relativeRange={3 * 86400 * 1000} locale={locale} />
|
|
310
337
|
) : (
|
|
@@ -315,14 +342,14 @@ export default function UserSessions({
|
|
|
315
342
|
},
|
|
316
343
|
},
|
|
317
344
|
},
|
|
318
|
-
{
|
|
345
|
+
!showOffline && {
|
|
319
346
|
label: t('updatedAt'),
|
|
320
347
|
name: 'updatedAt',
|
|
321
348
|
options: {
|
|
322
349
|
customBodyRenderLite: (rawIndex: number) => {
|
|
323
350
|
const x = safeData[rawIndex];
|
|
324
351
|
return (
|
|
325
|
-
<Box sx={
|
|
352
|
+
<Box sx={mergeStyle}>
|
|
326
353
|
{x.status === 'expired' ? (
|
|
327
354
|
t('expired')
|
|
328
355
|
) : (
|
|
@@ -350,7 +377,7 @@ export default function UserSessions({
|
|
|
350
377
|
customBodyRenderLite: (rawIndex: number) => {
|
|
351
378
|
const x = safeData[rawIndex];
|
|
352
379
|
return (
|
|
353
|
-
<Box sx={
|
|
380
|
+
<Box sx={mergeStyle}>
|
|
354
381
|
<Button
|
|
355
382
|
sx={{
|
|
356
383
|
whiteSpace: 'nowrap',
|
|
@@ -468,6 +495,22 @@ export default function UserSessions({
|
|
|
468
495
|
</Typography>
|
|
469
496
|
}
|
|
470
497
|
/>
|
|
498
|
+
{showOffline ? (
|
|
499
|
+
<FormControlLabel
|
|
500
|
+
value="offline"
|
|
501
|
+
control={
|
|
502
|
+
<Radio size="small" sx={{ lineHeight: 1, fontSize: 0 }} checked={filterParams.status === 'offline'} />
|
|
503
|
+
}
|
|
504
|
+
label={
|
|
505
|
+
<Typography sx={{ display: 'flex', alignItems: 'center' }}>
|
|
506
|
+
{t('offline')}
|
|
507
|
+
<Typography component="span" sx={{ ml: 0.5, color: 'text.secondary' }}>
|
|
508
|
+
({userSessionsCountMap.offline})
|
|
509
|
+
</Typography>
|
|
510
|
+
</Typography>
|
|
511
|
+
}
|
|
512
|
+
/>
|
|
513
|
+
) : null}
|
|
471
514
|
</RadioGroup>
|
|
472
515
|
}
|
|
473
516
|
onChange={(state) => {
|