@blocklet/ui-react 2.10.5 → 2.10.7
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/@types/index.d.ts +2 -0
- package/lib/Header/index.d.ts +19 -8
- package/lib/UserCenter/components/user-info/user-basic-info.js +64 -30
- package/lib/UserCenter/libs/locales.d.ts +8 -0
- package/lib/UserCenter/libs/locales.js +8 -0
- package/lib/UserSessions/components/user-sessions.js +8 -2
- package/package.json +5 -4
- package/src/@types/index.ts +3 -0
- package/src/Header/index.tsx +21 -9
- package/src/UserCenter/components/user-info/user-basic-info.tsx +67 -27
- package/src/UserCenter/libs/locales.ts +8 -0
- package/src/UserSessions/components/user-session-info.tsx +1 -0
- package/src/UserSessions/components/user-sessions.tsx +2 -0
package/lib/@types/index.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type User = UserPublicInfo & {
|
|
|
51
51
|
didSpace?: Record<string, any>;
|
|
52
52
|
connectedAccounts?: any[];
|
|
53
53
|
locale?: string;
|
|
54
|
+
url: string;
|
|
54
55
|
};
|
|
55
56
|
export type UserCenterTab = {
|
|
56
57
|
value: string;
|
|
@@ -67,6 +68,7 @@ export type Session = {
|
|
|
67
68
|
logout: any;
|
|
68
69
|
switch: any;
|
|
69
70
|
switchDid: any;
|
|
71
|
+
refreshProfile: () => Promise<void>;
|
|
70
72
|
switchProfile: any;
|
|
71
73
|
switchPassport: any;
|
|
72
74
|
refresh: Function;
|
package/lib/Header/index.d.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
+
import { LiteralUnion } from 'type-fest';
|
|
2
|
+
import type { BoxProps } from '@mui/material';
|
|
1
3
|
import { BlockletMetaProps, SessionManagerProps } from '../@types';
|
|
2
|
-
|
|
3
|
-
meta
|
|
4
|
-
addons
|
|
5
|
-
sessionManagerProps
|
|
6
|
-
homeLink
|
|
7
|
-
theme
|
|
8
|
-
hideNavMenu
|
|
4
|
+
type HeaderProps = {
|
|
5
|
+
meta?: BlockletMetaProps;
|
|
6
|
+
addons?: Function | React.ReactNode;
|
|
7
|
+
sessionManagerProps?: SessionManagerProps;
|
|
8
|
+
homeLink?: string | Function;
|
|
9
|
+
theme?: object;
|
|
10
|
+
hideNavMenu?: boolean;
|
|
9
11
|
bordered?: boolean;
|
|
10
|
-
|
|
12
|
+
logo?: React.ReactNode;
|
|
13
|
+
brand?: React.ReactNode;
|
|
14
|
+
brandAddon?: React.ReactNode;
|
|
15
|
+
description?: React.ReactNode;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
prepend?: React.ReactNode;
|
|
18
|
+
align?: 'left' | 'right';
|
|
19
|
+
maxWidth?: false | LiteralUnion<'xs' | 'sm' | 'md' | 'lg' | 'xl', string>;
|
|
20
|
+
};
|
|
21
|
+
declare const _default: import("react").ComponentType<HeaderProps & Omit<BoxProps, keyof HeaderProps>>;
|
|
11
22
|
export default _default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Chip, IconButton, Typography } from "@mui/material";
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Chip, CircularProgress, IconButton, Tooltip, Typography } from "@mui/material";
|
|
3
3
|
import { Icon } from "@iconify/react";
|
|
4
4
|
import SwapHorizRoundedIcon from "@iconify-icons/material-symbols/swap-horiz-rounded";
|
|
5
5
|
import SettingsOutlineRoundedIcon from "@iconify-icons/material-symbols/settings-outline-rounded";
|
|
@@ -11,7 +11,13 @@ import { useCreation, useMemoizedFn } from "ahooks";
|
|
|
11
11
|
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
12
12
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
13
13
|
import noop from "lodash/noop";
|
|
14
|
+
import RefreshOutlinedIcon from "@mui/icons-material/RefreshOutlined";
|
|
15
|
+
import { SessionContext } from "@arcblock/did-connect/lib/Session";
|
|
16
|
+
import { useContext, useState } from "react";
|
|
17
|
+
import Toast from "@arcblock/ux/lib/Toast";
|
|
18
|
+
import isEmpty from "lodash/isEmpty";
|
|
14
19
|
import { translations } from "../../libs/locales.js";
|
|
20
|
+
import { formatAxiosError } from "../../libs/utils.js";
|
|
15
21
|
export default function UserBasicInfo({
|
|
16
22
|
user,
|
|
17
23
|
isMyself = true,
|
|
@@ -22,6 +28,8 @@ export default function UserBasicInfo({
|
|
|
22
28
|
...rest
|
|
23
29
|
}) {
|
|
24
30
|
const { locale } = useLocaleContext();
|
|
31
|
+
const { session } = useContext(SessionContext);
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
25
33
|
const t = useMemoizedFn((key, data = {}) => {
|
|
26
34
|
return translate(translations, key, locale, "en", data);
|
|
27
35
|
});
|
|
@@ -34,6 +42,19 @@ export default function UserBasicInfo({
|
|
|
34
42
|
if (!user) {
|
|
35
43
|
return null;
|
|
36
44
|
}
|
|
45
|
+
const refreshProfile = async () => {
|
|
46
|
+
try {
|
|
47
|
+
setLoading(true);
|
|
48
|
+
await session.refreshProfile();
|
|
49
|
+
session.refresh();
|
|
50
|
+
Toast.success(translate(translations, "refreshProfile.successfully", locale));
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error(err);
|
|
53
|
+
Toast.error(formatAxiosError(err));
|
|
54
|
+
} finally {
|
|
55
|
+
setLoading(false);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
37
58
|
return /* @__PURE__ */ jsxs(
|
|
38
59
|
Box,
|
|
39
60
|
{
|
|
@@ -95,35 +116,48 @@ export default function UserBasicInfo({
|
|
|
95
116
|
},
|
|
96
117
|
children: [
|
|
97
118
|
user?.fullName,
|
|
98
|
-
isMyself ? /* @__PURE__ */
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
isMyself ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
120
|
+
/* @__PURE__ */ jsx(
|
|
121
|
+
Chip,
|
|
122
|
+
{
|
|
123
|
+
label: currentRole?.title || user?.role || "Guest",
|
|
124
|
+
size: "small",
|
|
125
|
+
variant: "outlined",
|
|
126
|
+
sx: {
|
|
127
|
+
flexShrink: 0,
|
|
128
|
+
fontWeight: "bold",
|
|
129
|
+
fontSize: "12px",
|
|
130
|
+
color: colors.textBase,
|
|
131
|
+
borderColor: colors.strokeBorderStrong,
|
|
132
|
+
backgroundColor: "transparent",
|
|
133
|
+
textTransform: "capitalize",
|
|
134
|
+
pr: 1,
|
|
135
|
+
pl: 0.5,
|
|
136
|
+
"&:hover": {
|
|
137
|
+
backgroundColor: "rgba(0, 0, 0, 0.04)"
|
|
138
|
+
},
|
|
139
|
+
"&:active": {
|
|
140
|
+
boxShadow: "none"
|
|
141
|
+
}
|
|
116
142
|
},
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
clickable: true,
|
|
144
|
+
deleteIcon: /* @__PURE__ */ jsx(Icon, { icon: SwapHorizRoundedIcon, color: colors.textBase }),
|
|
145
|
+
onDelete: switchPassport,
|
|
146
|
+
onClick: switchPassport
|
|
147
|
+
}
|
|
148
|
+
),
|
|
149
|
+
!isEmpty(user.url) && /* @__PURE__ */ jsx(
|
|
150
|
+
Tooltip,
|
|
151
|
+
{
|
|
152
|
+
title: !loading && translate(translations, "refreshProfile.title", locale),
|
|
153
|
+
sx: { display: "flex", alignItems: "center" },
|
|
154
|
+
children: loading ? (
|
|
155
|
+
// @ts-expect-error
|
|
156
|
+
/* @__PURE__ */ jsx(CircularProgress, { size: "16px", sx: { color: theme?.colors?.primary, ml: 0.5 } })
|
|
157
|
+
) : /* @__PURE__ */ jsx(RefreshOutlinedIcon, { onClick: refreshProfile })
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
] }) : null
|
|
127
161
|
]
|
|
128
162
|
}
|
|
129
163
|
),
|
|
@@ -39,6 +39,10 @@ export declare const translations: {
|
|
|
39
39
|
};
|
|
40
40
|
toPublic: string;
|
|
41
41
|
currentPassport: string;
|
|
42
|
+
refreshProfile: {
|
|
43
|
+
title: string;
|
|
44
|
+
successfully: string;
|
|
45
|
+
};
|
|
42
46
|
switchProfile: string;
|
|
43
47
|
userInfo: string;
|
|
44
48
|
myInfo: string;
|
|
@@ -125,6 +129,10 @@ export declare const translations: {
|
|
|
125
129
|
};
|
|
126
130
|
toPublic: string;
|
|
127
131
|
currentPassport: string;
|
|
132
|
+
refreshProfile: {
|
|
133
|
+
title: string;
|
|
134
|
+
successfully: string;
|
|
135
|
+
};
|
|
128
136
|
switchProfile: string;
|
|
129
137
|
userInfo: string;
|
|
130
138
|
myInfo: string;
|
|
@@ -39,6 +39,10 @@ export const translations = {
|
|
|
39
39
|
},
|
|
40
40
|
toPublic: "\u516C\u5F00 \u201C{name}\u201D \u9875\u9762",
|
|
41
41
|
currentPassport: "\u5F53\u524D\u4F7F\u7528\u7684\u901A\u884C\u8BC1",
|
|
42
|
+
refreshProfile: {
|
|
43
|
+
title: "\u5237\u65B0\u4E2A\u4EBA\u4FE1\u606F",
|
|
44
|
+
successfully: "\u5237\u65B0\u4E2A\u4EBA\u4FE1\u606F\u6210\u529F"
|
|
45
|
+
},
|
|
42
46
|
switchProfile: "\u5207\u6362",
|
|
43
47
|
userInfo: "\u4E2A\u4EBA\u4FE1\u606F",
|
|
44
48
|
myInfo: "\u6211\u7684\u4FE1\u606F",
|
|
@@ -125,6 +129,10 @@ export const translations = {
|
|
|
125
129
|
},
|
|
126
130
|
toPublic: 'Public "{name}" page',
|
|
127
131
|
currentPassport: "Passport currently in use",
|
|
132
|
+
refreshProfile: {
|
|
133
|
+
title: "Refresh profile",
|
|
134
|
+
successfully: "Refresh profile successfully"
|
|
135
|
+
},
|
|
128
136
|
switchProfile: "Switch",
|
|
129
137
|
userInfo: "User Info",
|
|
130
138
|
myInfo: "My Info",
|
|
@@ -187,7 +187,10 @@ export default function UserSessions({
|
|
|
187
187
|
options: {
|
|
188
188
|
customBodyRenderLite: (rawIndex) => {
|
|
189
189
|
const x = safeData[rawIndex];
|
|
190
|
-
return x.createdAt ?
|
|
190
|
+
return x.createdAt ? (
|
|
191
|
+
// @ts-expect-error
|
|
192
|
+
/* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale })
|
|
193
|
+
) : t("unknown");
|
|
191
194
|
}
|
|
192
195
|
}
|
|
193
196
|
},
|
|
@@ -197,7 +200,10 @@ export default function UserSessions({
|
|
|
197
200
|
options: {
|
|
198
201
|
customBodyRenderLite: (rawIndex) => {
|
|
199
202
|
const x = safeData[rawIndex];
|
|
200
|
-
return x.status === "expired" ? t("expired") :
|
|
203
|
+
return x.status === "expired" ? t("expired") : (
|
|
204
|
+
// @ts-expect-error
|
|
205
|
+
/* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale })
|
|
206
|
+
);
|
|
201
207
|
}
|
|
202
208
|
}
|
|
203
209
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.7",
|
|
4
4
|
"description": "Some useful front-end web components that can be used in Blocklets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"url": "https://github.com/ArcBlock/ux/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@arcblock/bridge": "^2.10.
|
|
36
|
-
"@arcblock/react-hooks": "^2.10.
|
|
35
|
+
"@arcblock/bridge": "^2.10.7",
|
|
36
|
+
"@arcblock/react-hooks": "^2.10.7",
|
|
37
37
|
"@iconify-icons/logos": "^1.2.36",
|
|
38
38
|
"@iconify-icons/material-symbols": "^1.2.58",
|
|
39
39
|
"@iconify/react": "^4.1.1",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"prop-types": "^15.8.1",
|
|
51
51
|
"react-error-boundary": "^3.1.4",
|
|
52
52
|
"react-placeholder": "^4.1.0",
|
|
53
|
+
"type-fest": "^4.22.0",
|
|
53
54
|
"ua-parser-js": "^1.0.37",
|
|
54
55
|
"ufo": "^1.5.3"
|
|
55
56
|
},
|
|
@@ -78,5 +79,5 @@
|
|
|
78
79
|
"jest": "^28.1.3",
|
|
79
80
|
"unbuild": "^2.0.0"
|
|
80
81
|
},
|
|
81
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "865d3f490c7148b8ef706768add621409198a3c1"
|
|
82
83
|
}
|
package/src/@types/index.ts
CHANGED
|
@@ -57,6 +57,7 @@ export type User = UserPublicInfo & {
|
|
|
57
57
|
didSpace?: Record<string, any>;
|
|
58
58
|
connectedAccounts?: any[];
|
|
59
59
|
locale?: string;
|
|
60
|
+
url: string;
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
export type UserCenterTab = {
|
|
@@ -75,6 +76,8 @@ export type Session = {
|
|
|
75
76
|
logout: any;
|
|
76
77
|
switch: any;
|
|
77
78
|
switchDid: any;
|
|
79
|
+
|
|
80
|
+
refreshProfile: () => Promise<void>;
|
|
78
81
|
switchProfile: any;
|
|
79
82
|
switchPassport: any;
|
|
80
83
|
|
package/src/Header/index.tsx
CHANGED
|
@@ -7,6 +7,8 @@ import NavMenu from '@arcblock/ux/lib/NavMenu';
|
|
|
7
7
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
8
8
|
import { temp as colors } from '@arcblock/ux/lib/Colors';
|
|
9
9
|
import omit from 'lodash/omit';
|
|
10
|
+
import { LiteralUnion } from 'type-fest';
|
|
11
|
+
import type { BoxProps } from '@mui/material';
|
|
10
12
|
|
|
11
13
|
import Icon from '../Icon';
|
|
12
14
|
import OverridableThemeProvider from '../common/overridable-theme-provider';
|
|
@@ -56,6 +58,24 @@ const parseNavigation = (navigation: any) => {
|
|
|
56
58
|
return { navItems, activeId: matchedIndex >= 0 ? flattened[matchedIndex].id : null };
|
|
57
59
|
};
|
|
58
60
|
|
|
61
|
+
type HeaderProps = {
|
|
62
|
+
meta?: BlockletMetaProps;
|
|
63
|
+
addons?: Function | React.ReactNode;
|
|
64
|
+
sessionManagerProps?: SessionManagerProps;
|
|
65
|
+
homeLink?: string | Function;
|
|
66
|
+
theme?: object;
|
|
67
|
+
hideNavMenu?: boolean;
|
|
68
|
+
bordered?: boolean;
|
|
69
|
+
logo?: React.ReactNode;
|
|
70
|
+
brand?: React.ReactNode;
|
|
71
|
+
brandAddon?: React.ReactNode;
|
|
72
|
+
description?: React.ReactNode;
|
|
73
|
+
children?: React.ReactNode;
|
|
74
|
+
prepend?: React.ReactNode;
|
|
75
|
+
align?: 'left' | 'right';
|
|
76
|
+
maxWidth?: false | LiteralUnion<'xs' | 'sm' | 'md' | 'lg' | 'xl', string>;
|
|
77
|
+
};
|
|
78
|
+
|
|
59
79
|
/**
|
|
60
80
|
* 专门用于 (composable) blocklet 的 Header 组件, 解析 blocklet meta 中的数据, 通过组合 UX 中的 Header & NavMenu 组件来渲染
|
|
61
81
|
*/
|
|
@@ -71,15 +91,7 @@ function Header({
|
|
|
71
91
|
theme: themeOverrides,
|
|
72
92
|
hideNavMenu = false,
|
|
73
93
|
...rest
|
|
74
|
-
}: {
|
|
75
|
-
meta: BlockletMetaProps;
|
|
76
|
-
addons: Function | JSX.Element;
|
|
77
|
-
sessionManagerProps: SessionManagerProps;
|
|
78
|
-
homeLink: string;
|
|
79
|
-
theme: object;
|
|
80
|
-
hideNavMenu: boolean;
|
|
81
|
-
bordered?: boolean;
|
|
82
|
-
}) {
|
|
94
|
+
}: HeaderProps & Omit<BoxProps, keyof HeaderProps>) {
|
|
83
95
|
useWalletHiddenTopbar();
|
|
84
96
|
const { locale } = useLocaleContext() || {};
|
|
85
97
|
const formattedBlocklet = useMemo(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box, Chip, IconButton, Typography } from '@mui/material';
|
|
1
|
+
import { Box, Chip, CircularProgress, IconButton, Tooltip, Typography } from '@mui/material';
|
|
2
2
|
import type { BoxProps } from '@mui/material';
|
|
3
3
|
import { Icon } from '@iconify/react';
|
|
4
4
|
import SwapHorizRoundedIcon from '@iconify-icons/material-symbols/swap-horiz-rounded';
|
|
@@ -11,9 +11,17 @@ import { useCreation, useMemoizedFn } from 'ahooks';
|
|
|
11
11
|
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
12
12
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
13
13
|
import noop from 'lodash/noop';
|
|
14
|
+
import RefreshOutlinedIcon from '@mui/icons-material/RefreshOutlined';
|
|
15
|
+
import { SessionContext } from '@arcblock/did-connect/lib/Session';
|
|
16
|
+
import { useContext, useState } from 'react';
|
|
17
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
18
|
+
import type { AxiosError } from 'axios';
|
|
19
|
+
import isEmpty from 'lodash/isEmpty';
|
|
20
|
+
import { SessionContext as TSessionContext } from '../../../@types';
|
|
14
21
|
|
|
15
22
|
import { translations } from '../../libs/locales';
|
|
16
23
|
import type { User } from '../../../@types';
|
|
24
|
+
import { formatAxiosError } from '../../libs/utils';
|
|
17
25
|
|
|
18
26
|
export default function UserBasicInfo({
|
|
19
27
|
user,
|
|
@@ -32,6 +40,9 @@ export default function UserBasicInfo({
|
|
|
32
40
|
openSettings: () => void;
|
|
33
41
|
} & BoxProps) {
|
|
34
42
|
const { locale } = useLocaleContext();
|
|
43
|
+
const { session } = useContext<TSessionContext>(SessionContext);
|
|
44
|
+
const [loading, setLoading] = useState(false);
|
|
45
|
+
|
|
35
46
|
const t = useMemoizedFn((key, data = {}) => {
|
|
36
47
|
return translate(translations, key, locale, 'en', data);
|
|
37
48
|
});
|
|
@@ -47,6 +58,20 @@ export default function UserBasicInfo({
|
|
|
47
58
|
return null;
|
|
48
59
|
}
|
|
49
60
|
|
|
61
|
+
const refreshProfile = async () => {
|
|
62
|
+
try {
|
|
63
|
+
setLoading(true);
|
|
64
|
+
await session.refreshProfile();
|
|
65
|
+
session.refresh();
|
|
66
|
+
Toast.success(translate(translations, 'refreshProfile.successfully', locale));
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error(err);
|
|
69
|
+
Toast.error(formatAxiosError(err as AxiosError));
|
|
70
|
+
} finally {
|
|
71
|
+
setLoading(false);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
50
75
|
return (
|
|
51
76
|
<Box
|
|
52
77
|
{...rest}
|
|
@@ -55,6 +80,7 @@ export default function UserBasicInfo({
|
|
|
55
80
|
...rest.sx,
|
|
56
81
|
}}>
|
|
57
82
|
<Avatar
|
|
83
|
+
// @ts-ignore
|
|
58
84
|
src={user?.avatar}
|
|
59
85
|
did={user?.did}
|
|
60
86
|
size={isSmallView ? 64 : 80}
|
|
@@ -103,32 +129,46 @@ export default function UserBasicInfo({
|
|
|
103
129
|
}}>
|
|
104
130
|
{user?.fullName}
|
|
105
131
|
{isMyself ? (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
<>
|
|
133
|
+
<Chip
|
|
134
|
+
label={currentRole?.title || user?.role || 'Guest'}
|
|
135
|
+
size="small"
|
|
136
|
+
variant="outlined"
|
|
137
|
+
sx={{
|
|
138
|
+
flexShrink: 0,
|
|
139
|
+
fontWeight: 'bold',
|
|
140
|
+
fontSize: '12px',
|
|
141
|
+
color: colors.textBase,
|
|
142
|
+
borderColor: colors.strokeBorderStrong,
|
|
143
|
+
backgroundColor: 'transparent',
|
|
144
|
+
textTransform: 'capitalize',
|
|
145
|
+
pr: 1,
|
|
146
|
+
pl: 0.5,
|
|
147
|
+
'&:hover': {
|
|
148
|
+
backgroundColor: 'rgba(0, 0, 0, 0.04)',
|
|
149
|
+
},
|
|
150
|
+
'&:active': {
|
|
151
|
+
boxShadow: 'none',
|
|
152
|
+
},
|
|
153
|
+
}}
|
|
154
|
+
clickable
|
|
155
|
+
deleteIcon={<Icon icon={SwapHorizRoundedIcon} color={colors.textBase} />}
|
|
156
|
+
onDelete={switchPassport}
|
|
157
|
+
onClick={switchPassport}
|
|
158
|
+
/>
|
|
159
|
+
{!isEmpty(user.url) && (
|
|
160
|
+
<Tooltip
|
|
161
|
+
title={!loading && translate(translations, 'refreshProfile.title', locale)}
|
|
162
|
+
sx={{ display: 'flex', alignItems: 'center' }}>
|
|
163
|
+
{loading ? (
|
|
164
|
+
// @ts-expect-error
|
|
165
|
+
<CircularProgress size="16px" sx={{ color: theme?.colors?.primary, ml: 0.5 }} />
|
|
166
|
+
) : (
|
|
167
|
+
<RefreshOutlinedIcon onClick={refreshProfile} />
|
|
168
|
+
)}
|
|
169
|
+
</Tooltip>
|
|
170
|
+
)}
|
|
171
|
+
</>
|
|
132
172
|
) : null}
|
|
133
173
|
</Typography>
|
|
134
174
|
<DID did={user.did} showQrcode copyable compact={!showFullDid} responsive={!showFullDid} locale={locale} />
|
|
@@ -39,6 +39,10 @@ export const translations = {
|
|
|
39
39
|
},
|
|
40
40
|
toPublic: '公开 “{name}” 页面',
|
|
41
41
|
currentPassport: '当前使用的通行证',
|
|
42
|
+
refreshProfile: {
|
|
43
|
+
title: '刷新个人信息',
|
|
44
|
+
successfully: '刷新个人信息成功',
|
|
45
|
+
},
|
|
42
46
|
switchProfile: '切换',
|
|
43
47
|
userInfo: '个人信息',
|
|
44
48
|
myInfo: '我的信息',
|
|
@@ -126,6 +130,10 @@ export const translations = {
|
|
|
126
130
|
},
|
|
127
131
|
toPublic: 'Public "{name}" page',
|
|
128
132
|
currentPassport: 'Passport currently in use',
|
|
133
|
+
refreshProfile: {
|
|
134
|
+
title: 'Refresh profile',
|
|
135
|
+
successfully: 'Refresh profile successfully',
|
|
136
|
+
},
|
|
129
137
|
switchProfile: 'Switch',
|
|
130
138
|
userInfo: 'User Info',
|
|
131
139
|
myInfo: 'My Info',
|
|
@@ -209,6 +209,7 @@ export default function UserSessions({
|
|
|
209
209
|
customBodyRenderLite: (rawIndex: number) => {
|
|
210
210
|
const x = safeData[rawIndex];
|
|
211
211
|
return x.createdAt ? (
|
|
212
|
+
// @ts-expect-error
|
|
212
213
|
<RelativeTime value={x.createdAt} relativeRange={3 * 86400 * 1000} locale={locale} />
|
|
213
214
|
) : (
|
|
214
215
|
t('unknown')
|
|
@@ -225,6 +226,7 @@ export default function UserSessions({
|
|
|
225
226
|
return x.status === 'expired' ? (
|
|
226
227
|
t('expired')
|
|
227
228
|
) : (
|
|
229
|
+
// @ts-expect-error
|
|
228
230
|
<RelativeTime value={x.updatedAt} relativeRange={3 * 86400 * 1000} locale={locale} />
|
|
229
231
|
);
|
|
230
232
|
},
|