@blocklet/ui-react 3.0.16 → 3.0.19
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 +1 -0
- package/lib/UserCenter/components/danger-zone.d.ts +3 -1
- package/lib/UserCenter/components/danger-zone.js +40 -83
- package/lib/UserCenter/components/settings.d.ts +1 -0
- package/lib/UserCenter/components/settings.js +54 -53
- package/lib/UserCenter/components/user-center.d.ts +3 -1
- package/lib/UserCenter/components/user-center.js +53 -50
- package/lib/common/notification-addon.js +30 -30
- package/package.json +5 -5
- package/src/@types/index.ts +1 -0
- package/src/UserCenter/components/danger-zone.tsx +23 -81
- package/src/UserCenter/components/settings.tsx +17 -8
- package/src/UserCenter/components/user-center.tsx +5 -1
- package/src/common/notification-addon.jsx +1 -1
package/lib/@types/index.d.ts
CHANGED
|
@@ -1,80 +1,37 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { use as
|
|
3
|
-
import { Box as
|
|
4
|
-
import { useLocaleContext as
|
|
5
|
-
import { translate as
|
|
6
|
-
import { useMemoizedFn as
|
|
7
|
-
import { useConfirm as
|
|
8
|
-
import { SessionContext as
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return !1;
|
|
17
|
-
const r = n?.user?.connectedAccounts || [], o = [_.WALLET];
|
|
18
|
-
return !!r.some((t) => o.includes(t.provider));
|
|
19
|
-
}, [n?.user]), A = d(() => new Promise((r, o) => {
|
|
20
|
-
const t = n?.user?.did;
|
|
21
|
-
u.open({
|
|
22
|
-
locale: f,
|
|
23
|
-
action: "destroy-myself",
|
|
24
|
-
forceConnected: !0,
|
|
25
|
-
saveConnect: !1,
|
|
26
|
-
autoConnect: !1,
|
|
27
|
-
// 暂不允许使用 passkey 进行验证
|
|
28
|
-
passkeyBehavior: "none",
|
|
1
|
+
import { jsxs as a, Fragment as f, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { use as u } from "react";
|
|
3
|
+
import { Box as s, Typography as c, Button as h } from "@mui/material";
|
|
4
|
+
import { useLocaleContext as x } from "@arcblock/ux/lib/Locale/context";
|
|
5
|
+
import { translate as g } from "@arcblock/ux/lib/Locale/util";
|
|
6
|
+
import { useMemoizedFn as l } from "ahooks";
|
|
7
|
+
import { useConfirm as y } from "@arcblock/ux/lib/Dialog";
|
|
8
|
+
import { SessionContext as v } from "@arcblock/did-connect/lib/Session";
|
|
9
|
+
import w from "@arcblock/ux/lib/Toast";
|
|
10
|
+
import { translations as C } from "../libs/locales.js";
|
|
11
|
+
function S({ onDestroySelf: t = void 0 }) {
|
|
12
|
+
const { confirmHolder: m } = y(), { locale: d } = x(), { session: e } = u(v), r = l((n, i = {}) => g(C, n, d, "en", i)), p = l(async () => {
|
|
13
|
+
if (!t || typeof t != "function")
|
|
14
|
+
return;
|
|
15
|
+
const n = e.withSecondaryAuth(t, {
|
|
29
16
|
extraParams: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
confirm: e("destroyMyself.confirm"),
|
|
36
|
-
success: e("destroyMyself.success")
|
|
37
|
-
},
|
|
38
|
-
// @ts-expect-error 该 did-connect 后端api 将结果塞在了 result 中,并做了加密,所以已经变成一个字符串了
|
|
39
|
-
onSuccess: ({ result: c }, C = (i) => i) => {
|
|
40
|
-
const i = C(c);
|
|
41
|
-
r(i);
|
|
42
|
-
},
|
|
43
|
-
onClose: () => {
|
|
44
|
-
u.close(), o(new Error(e("destroyMyself.abort")));
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
})), M = d(() => {
|
|
48
|
-
g.open({
|
|
49
|
-
title: e("dangerZone.deleteAccount"),
|
|
50
|
-
content: e("dangerZone.deleteAccountDescription"),
|
|
51
|
-
confirmButtonText: e("common.confirm"),
|
|
52
|
-
confirmButtonProps: {
|
|
53
|
-
color: "error"
|
|
54
|
-
},
|
|
55
|
-
cancelButtonText: e("common.cancel"),
|
|
56
|
-
async onConfirm(r) {
|
|
57
|
-
let o;
|
|
58
|
-
try {
|
|
59
|
-
if (h)
|
|
60
|
-
o = await A();
|
|
61
|
-
else if (y?.user?.destroyMyself instanceof Function)
|
|
62
|
-
o = await y.user.destroyMyself();
|
|
63
|
-
else {
|
|
64
|
-
m.error(e("notImplemented"));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
o?.did === n?.user?.did ? n.logout(r) : m.error(e("destroyMyself.error"));
|
|
68
|
-
} catch (t) {
|
|
69
|
-
const c = t?.response?.data.error || t?.message || e("destroyMyself.error");
|
|
70
|
-
m.error(c);
|
|
17
|
+
locale: d,
|
|
18
|
+
removeUserDid: e?.user?.did,
|
|
19
|
+
input: {
|
|
20
|
+
user: { did: e?.user?.did },
|
|
21
|
+
teamDid: window?.blocklet?.did
|
|
71
22
|
}
|
|
72
|
-
}
|
|
23
|
+
},
|
|
24
|
+
operation: "destroySelf"
|
|
73
25
|
});
|
|
26
|
+
try {
|
|
27
|
+
await n(), e.logout();
|
|
28
|
+
} catch (i) {
|
|
29
|
+
w.error(i?.message || r("destroyMyself.error"));
|
|
30
|
+
}
|
|
74
31
|
});
|
|
75
|
-
return /* @__PURE__ */
|
|
76
|
-
/* @__PURE__ */ s
|
|
77
|
-
|
|
32
|
+
return /* @__PURE__ */ a(f, { children: [
|
|
33
|
+
/* @__PURE__ */ o(s, { children: /* @__PURE__ */ a(
|
|
34
|
+
s,
|
|
78
35
|
{
|
|
79
36
|
sx: {
|
|
80
37
|
display: "flex",
|
|
@@ -84,36 +41,36 @@ function N() {
|
|
|
84
41
|
flexWrap: "wrap"
|
|
85
42
|
},
|
|
86
43
|
children: [
|
|
87
|
-
/* @__PURE__ */
|
|
88
|
-
/* @__PURE__ */
|
|
89
|
-
|
|
44
|
+
/* @__PURE__ */ a(s, { children: [
|
|
45
|
+
/* @__PURE__ */ o(
|
|
46
|
+
c,
|
|
90
47
|
{
|
|
91
48
|
variant: "h6",
|
|
92
49
|
sx: {
|
|
93
50
|
fontSize: "0.875rem !important",
|
|
94
51
|
fontWeight: "bold"
|
|
95
52
|
},
|
|
96
|
-
children:
|
|
53
|
+
children: r("dangerZone.deleteAccount")
|
|
97
54
|
}
|
|
98
55
|
),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
-
|
|
56
|
+
/* @__PURE__ */ o(
|
|
57
|
+
c,
|
|
101
58
|
{
|
|
102
59
|
variant: "caption",
|
|
103
60
|
sx: {
|
|
104
61
|
color: "text.secondary"
|
|
105
62
|
},
|
|
106
|
-
children:
|
|
63
|
+
children: r("dangerZone.deleteAccountDescription")
|
|
107
64
|
}
|
|
108
65
|
)
|
|
109
66
|
] }),
|
|
110
|
-
/* @__PURE__ */
|
|
67
|
+
/* @__PURE__ */ o(h, { variant: "contained", color: "error", size: "small", onClick: p, children: r("dangerZone.delete") })
|
|
111
68
|
]
|
|
112
69
|
}
|
|
113
70
|
) }),
|
|
114
|
-
|
|
71
|
+
m
|
|
115
72
|
] });
|
|
116
73
|
}
|
|
117
74
|
export {
|
|
118
|
-
|
|
75
|
+
S as default
|
|
119
76
|
};
|
|
@@ -1,82 +1,83 @@
|
|
|
1
|
-
import { jsx as o, jsxs as
|
|
2
|
-
import { useEffect as
|
|
3
|
-
import { Box as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import T from "
|
|
13
|
-
import B from "
|
|
1
|
+
import { jsx as o, jsxs as h } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect as y } from "react";
|
|
3
|
+
import { Box as s, Typography as v } from "@mui/material";
|
|
4
|
+
import { ROLES as x } from "@abtnode/constant";
|
|
5
|
+
import { useMemoizedFn as b, useCreation as l } from "ahooks";
|
|
6
|
+
import { translate as S } from "@arcblock/ux/lib/Locale/util";
|
|
7
|
+
import { useLocaleContext as C } from "@arcblock/ux/lib/Locale/context";
|
|
8
|
+
import { mergeSx as w } from "@arcblock/ux/lib/Util/style";
|
|
9
|
+
import L from "@arcblock/react-hooks/lib/useBrowser";
|
|
10
|
+
import { translations as P } from "../libs/locales.js";
|
|
11
|
+
import D from "./notification.js";
|
|
12
|
+
import T from "./privacy.js";
|
|
13
|
+
import B from "../../UserSessions/components/user-sessions.js";
|
|
14
|
+
import E from "./third-party-login/index.js";
|
|
14
15
|
import M from "./config-profile.js";
|
|
15
|
-
import
|
|
16
|
-
import { client as
|
|
17
|
-
function
|
|
18
|
-
user:
|
|
19
|
-
settings:
|
|
20
|
-
onSave:
|
|
21
|
-
isMobile:
|
|
22
|
-
...
|
|
16
|
+
import W from "./danger-zone.js";
|
|
17
|
+
import { client as O } from "../../libs/client.js";
|
|
18
|
+
function Y({
|
|
19
|
+
user: r,
|
|
20
|
+
settings: a,
|
|
21
|
+
onSave: m,
|
|
22
|
+
isMobile: c,
|
|
23
|
+
...i
|
|
23
24
|
}) {
|
|
24
|
-
const { locale: p } =
|
|
25
|
-
key:
|
|
26
|
-
name:
|
|
27
|
-
value:
|
|
28
|
-
isPrivate:
|
|
29
|
-
})), [
|
|
25
|
+
const { locale: p } = C(), d = L().arcSphere, n = b((e, t = {}) => S(P, e, p, "en", t)), u = l(() => r.passports?.some((e) => e.role === x.OWNER), [r]), f = l(() => (a?.userCenterTabs || []).map((t) => ({
|
|
26
|
+
key: t.value,
|
|
27
|
+
name: t.label,
|
|
28
|
+
value: t.protected,
|
|
29
|
+
isPrivate: t.isPrivate
|
|
30
|
+
})), [a?.userCenterTabs]), g = l(() => [
|
|
30
31
|
d ? void 0 : {
|
|
31
|
-
label:
|
|
32
|
+
label: n("commonSetting.title"),
|
|
32
33
|
value: "common",
|
|
33
|
-
content: /* @__PURE__ */ o(M, { user:
|
|
34
|
+
content: /* @__PURE__ */ o(M, { user: r, onSave: m })
|
|
34
35
|
},
|
|
35
36
|
{
|
|
36
|
-
label:
|
|
37
|
+
label: n("notificationManagement"),
|
|
37
38
|
value: "notification",
|
|
38
|
-
content: /* @__PURE__ */ o(
|
|
39
|
+
content: /* @__PURE__ */ o(D, { user: r, isMobile: c })
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
|
-
label:
|
|
42
|
+
label: n("thirdPartyLogin.title"),
|
|
42
43
|
value: "thirdPartyLogin",
|
|
43
|
-
content: /* @__PURE__ */ o(
|
|
44
|
+
content: /* @__PURE__ */ o(E, { user: r })
|
|
44
45
|
},
|
|
45
46
|
{
|
|
46
|
-
label:
|
|
47
|
+
label: n("privacyManagement"),
|
|
47
48
|
value: "privacy",
|
|
48
|
-
content: /* @__PURE__ */ o(
|
|
49
|
+
content: /* @__PURE__ */ o(T, { configList: f, onSave: m })
|
|
49
50
|
},
|
|
50
51
|
{
|
|
51
|
-
label:
|
|
52
|
+
label: n("sessionManagement"),
|
|
52
53
|
value: "session",
|
|
53
54
|
content: /* @__PURE__ */ o(
|
|
54
|
-
|
|
55
|
+
B,
|
|
55
56
|
{
|
|
56
|
-
user:
|
|
57
|
+
user: r,
|
|
57
58
|
showUser: !1,
|
|
58
|
-
getUserSessions: (e) =>
|
|
59
|
+
getUserSessions: (e) => O.userSession.getMyLoginSessions({}, e)
|
|
59
60
|
}
|
|
60
61
|
)
|
|
61
62
|
},
|
|
62
|
-
{
|
|
63
|
-
label:
|
|
63
|
+
!u && i.onDestroySelf && typeof i.onDestroySelf == "function" ? {
|
|
64
|
+
label: n("dangerZone.title"),
|
|
64
65
|
value: "dangerZone",
|
|
65
|
-
content: /* @__PURE__ */ o(
|
|
66
|
+
content: /* @__PURE__ */ o(W, { onDestroySelf: i.onDestroySelf }),
|
|
66
67
|
sx: {
|
|
67
68
|
borderColor: "error.main"
|
|
68
69
|
}
|
|
69
|
-
}
|
|
70
|
-
].filter(Boolean), [
|
|
71
|
-
return
|
|
70
|
+
} : null
|
|
71
|
+
].filter(Boolean), [r, f, c]);
|
|
72
|
+
return y(() => {
|
|
72
73
|
const e = window.location.hash.slice(1);
|
|
73
74
|
e && document.getElementById(e)?.scrollIntoView({ behavior: "smooth" });
|
|
74
75
|
}, []), /* @__PURE__ */ o(
|
|
75
|
-
|
|
76
|
+
s,
|
|
76
77
|
{
|
|
77
|
-
...
|
|
78
|
+
...i,
|
|
78
79
|
sx: {
|
|
79
|
-
...
|
|
80
|
+
...i?.sx,
|
|
80
81
|
display: "flex",
|
|
81
82
|
flexDirection: "column",
|
|
82
83
|
gap: 2.5,
|
|
@@ -85,11 +86,11 @@ function O({
|
|
|
85
86
|
},
|
|
86
87
|
maxWidth: "100%"
|
|
87
88
|
},
|
|
88
|
-
children:
|
|
89
|
-
|
|
89
|
+
children: g.map((e) => e ? /* @__PURE__ */ h(
|
|
90
|
+
s,
|
|
90
91
|
{
|
|
91
92
|
id: e.value,
|
|
92
|
-
sx:
|
|
93
|
+
sx: w(
|
|
93
94
|
{
|
|
94
95
|
border: "1px solid",
|
|
95
96
|
borderColor: "divider",
|
|
@@ -113,7 +114,7 @@ function O({
|
|
|
113
114
|
}
|
|
114
115
|
),
|
|
115
116
|
/* @__PURE__ */ o(
|
|
116
|
-
|
|
117
|
+
s,
|
|
117
118
|
{
|
|
118
119
|
sx: {
|
|
119
120
|
mt: 2.5
|
|
@@ -129,5 +130,5 @@ function O({
|
|
|
129
130
|
);
|
|
130
131
|
}
|
|
131
132
|
export {
|
|
132
|
-
|
|
133
|
+
Y as default
|
|
133
134
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BoxProps } from '@mui/material';
|
|
2
|
-
export default function UserCenter({ children, notLoginContent, currentTab, contentProps, disableAutoRedirect, hideFooter, headerProps, footerProps, userDid, stickySidebar, embed, onlyProfile,
|
|
2
|
+
export default function UserCenter({ children, notLoginContent, currentTab, contentProps, disableAutoRedirect, hideFooter, headerProps, footerProps, userDid, stickySidebar, embed, onlyProfile, // 只显示 profile 页面,用于 ArcSphere 只需要显示 Profile 的内容
|
|
3
|
+
onDestroySelf, }: {
|
|
3
4
|
readonly children: any;
|
|
4
5
|
readonly notLoginContent?: any;
|
|
5
6
|
readonly currentTab: string;
|
|
@@ -13,4 +14,5 @@ export default function UserCenter({ children, notLoginContent, currentTab, cont
|
|
|
13
14
|
readonly stickySidebar?: boolean;
|
|
14
15
|
readonly embed?: boolean;
|
|
15
16
|
readonly onlyProfile?: boolean;
|
|
17
|
+
readonly onDestroySelf?: () => void;
|
|
16
18
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { jsx as e, jsxs as f, Fragment as D } from "react/jsx-runtime";
|
|
2
|
-
import { use as
|
|
3
|
-
import { Box as a, Typography as
|
|
2
|
+
import { use as pe } from "react";
|
|
3
|
+
import { Box as a, Typography as me, CircularProgress as he, Divider as xe } from "@mui/material";
|
|
4
4
|
import { useMemoizedFn as y, useCreation as d, useRequest as Y } from "ahooks";
|
|
5
|
-
import
|
|
6
|
-
import { SessionContext as
|
|
7
|
-
import
|
|
5
|
+
import ge from "p-wait-for";
|
|
6
|
+
import { SessionContext as ve } from "@arcblock/did-connect/lib/Session";
|
|
7
|
+
import be from "@arcblock/ux/lib/Tabs";
|
|
8
8
|
import M from "@arcblock/ux/lib/Empty";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import { useConfirm as
|
|
12
|
-
import { translate as
|
|
13
|
-
import { useLocaleContext as
|
|
14
|
-
import { ErrorFallback as
|
|
9
|
+
import we from "@arcblock/ux/lib/Button";
|
|
10
|
+
import ye from "@arcblock/ux/lib/Result";
|
|
11
|
+
import { useConfirm as Ce } from "@arcblock/ux/lib/Dialog";
|
|
12
|
+
import { translate as ke } from "@arcblock/ux/lib/Locale/util";
|
|
13
|
+
import { useLocaleContext as Pe } from "@arcblock/ux/lib/Locale/context";
|
|
14
|
+
import { ErrorFallback as Se } from "@arcblock/ux/lib/ErrorBoundary";
|
|
15
15
|
import { styled as oe } from "@arcblock/ux/lib/Theme";
|
|
16
|
-
import
|
|
17
|
-
import { joinURL as C, getQuery as
|
|
16
|
+
import De from "lodash/cloneDeep";
|
|
17
|
+
import { joinURL as C, getQuery as Me, withoutTrailingSlash as Z, withQuery as $ } from "ufo";
|
|
18
18
|
import { PROFILE_URL as k } from "@arcblock/ux/lib/Util/constant";
|
|
19
|
-
import
|
|
19
|
+
import Te from "../../Footer/index.js";
|
|
20
20
|
import ee from "../../Header/index.js";
|
|
21
|
-
import { translations as
|
|
21
|
+
import { translations as We } from "../libs/locales.js";
|
|
22
22
|
import re from "./user-info/user-basic-info.js";
|
|
23
23
|
import "@mui/icons-material";
|
|
24
24
|
import "@iconify/react";
|
|
@@ -30,14 +30,14 @@ import "@iconify-icons/material-symbols/settings-input-antenna-rounded";
|
|
|
30
30
|
import "@arcblock/ux/lib/RelativeTime";
|
|
31
31
|
import "@arcblock/ux/lib/UserCard/Content/shorten-label";
|
|
32
32
|
import "./user-info/switch-role.js";
|
|
33
|
-
import { formatBlockletInfo as
|
|
34
|
-
import
|
|
35
|
-
import
|
|
33
|
+
import { formatBlockletInfo as ze, getLink as T, getLocalizedNavigation as Ae } from "../../blocklets.js";
|
|
34
|
+
import Ue from "./passport.js";
|
|
35
|
+
import Le from "./settings.js";
|
|
36
36
|
import { client as te } from "../../libs/client.js";
|
|
37
|
-
import
|
|
38
|
-
import { ConfigUserSpaceProvider as
|
|
39
|
-
import
|
|
40
|
-
import
|
|
37
|
+
import Be from "../../hooks/use-mobile.js";
|
|
38
|
+
import { ConfigUserSpaceProvider as Fe } from "../../contexts/config-user-space.js";
|
|
39
|
+
import Re from "./storage/index.js";
|
|
40
|
+
import Ie from "./nft.js";
|
|
41
41
|
const W = C(k, "/nfts"), z = C(k, "/settings"), A = C(k, "/did-spaces"), ie = oe(a)(({ theme: v }) => ({
|
|
42
42
|
flex: 1,
|
|
43
43
|
boxSizing: "border-box",
|
|
@@ -64,7 +64,7 @@ const W = C(k, "/nfts"), z = C(k, "/settings"), A = C(k, "/did-spaces"), ie = oe
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
}));
|
|
67
|
-
function
|
|
67
|
+
function Dr({
|
|
68
68
|
children: v,
|
|
69
69
|
notLoginContent: L = null,
|
|
70
70
|
currentTab: h,
|
|
@@ -76,18 +76,19 @@ function Sr({
|
|
|
76
76
|
userDid: P = void 0,
|
|
77
77
|
stickySidebar: R = !1,
|
|
78
78
|
embed: I = !1,
|
|
79
|
-
onlyProfile: w = !1
|
|
79
|
+
onlyProfile: w = !1,
|
|
80
80
|
// 只显示 profile 页面,用于 ArcSphere 只需要显示 Profile 的内容
|
|
81
|
+
onDestroySelf: le = void 0
|
|
81
82
|
}) {
|
|
82
|
-
const { locale: x } =
|
|
83
|
+
const { locale: x } = Pe(), l = Be({ key: "md" }), g = y((r, o = {}) => ke(We, r, x, "en", o)), t = pe(ve)?.session, p = d(() => {
|
|
83
84
|
if (P)
|
|
84
85
|
return P;
|
|
85
|
-
const r = window.location.href, o =
|
|
86
|
+
const r = window.location.href, o = Me(r);
|
|
86
87
|
return o?.did ? Array.isArray(o.did) ? o.did[0] : o.did : t?.user?.did;
|
|
87
88
|
}, [t?.user?.did, P]), i = d(() => t?.user ? p === t?.user?.did : !1, [p, t?.user?.did]), n = Y(
|
|
88
89
|
// eslint-disable-next-line consistent-return
|
|
89
90
|
async () => {
|
|
90
|
-
if (await
|
|
91
|
+
if (await ge(() => t?.initialized), i)
|
|
91
92
|
return t.user;
|
|
92
93
|
if (p)
|
|
93
94
|
return te.user.getUserPublicInfo({ did: p });
|
|
@@ -101,7 +102,7 @@ function Sr({
|
|
|
101
102
|
refreshDeps: [p, n.data, h],
|
|
102
103
|
loadingDelay: 300
|
|
103
104
|
}
|
|
104
|
-
), { confirmHolder: H } =
|
|
105
|
+
), { confirmHolder: H } = Ce({
|
|
105
106
|
fullScreen: l,
|
|
106
107
|
sx: {
|
|
107
108
|
".MuiDialog-paper": {
|
|
@@ -122,9 +123,9 @@ function Sr({
|
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
}), N = d(() => {
|
|
125
|
-
const r =
|
|
126
|
+
const r = De(window.blocklet);
|
|
126
127
|
try {
|
|
127
|
-
return
|
|
128
|
+
return ze(r);
|
|
128
129
|
} catch (o) {
|
|
129
130
|
return console.error("Failed to format blocklet info", o, r), r;
|
|
130
131
|
}
|
|
@@ -157,7 +158,7 @@ function Sr({
|
|
|
157
158
|
]), o;
|
|
158
159
|
}, [i, x]), c = d(() => {
|
|
159
160
|
const r = N?.navigation?.userCenter || [];
|
|
160
|
-
return (
|
|
161
|
+
return (Ae(r, x) || []).concat(_).map((u) => {
|
|
161
162
|
const X = u.value ?? u._rawLink ?? u.link ?? u.url;
|
|
162
163
|
return {
|
|
163
164
|
value: X,
|
|
@@ -169,21 +170,22 @@ function Sr({
|
|
|
169
170
|
// icon: x.icon,
|
|
170
171
|
};
|
|
171
172
|
}).filter((u) => i || !u.isPrivate);
|
|
172
|
-
}, [N, n.data, m?.data, x, _, i]), s = d(() => c.find((r) => Z(r.value) === Z(h)), [c]),
|
|
173
|
+
}, [N, n.data, m?.data, x, _, i]), s = d(() => c.find((r) => Z(r.value) === Z(h)), [c]), de = y((r) => {
|
|
173
174
|
const o = c.find((b) => b.value === r);
|
|
174
175
|
o && (window.location.href = $(o.url, {
|
|
175
176
|
did: i ? void 0 : p
|
|
176
177
|
}));
|
|
177
178
|
}), E = d(() => /* @__PURE__ */ e(
|
|
178
|
-
|
|
179
|
+
Le,
|
|
179
180
|
{
|
|
180
181
|
user: n.data,
|
|
181
182
|
settings: { userCenterTabs: c },
|
|
182
183
|
onSave: async (r) => r === "privacy" ? (await m.runAsync(), m.data) : (r === "profile" && await t.refresh(), null),
|
|
183
|
-
isMobile: l
|
|
184
|
+
isMobile: l,
|
|
185
|
+
onDestroySelf: le
|
|
184
186
|
}
|
|
185
|
-
), [n.data, c, m.data, m.runAsync]), O = d(() => s && s?.value === z, [s]), q = d(() => s && s?.value === C(k, "/profile") || s?.value === W, [s]),
|
|
186
|
-
t?.user?.sourceProvider === "passkey" ?
|
|
187
|
+
), [n.data, c, m.data, m.runAsync]), O = d(() => s && s?.value === z, [s]), q = d(() => s && s?.value === C(k, "/profile") || s?.value === W, [s]), ce = d(() => s && s?.value === A, [s]), ue = t.useOAuth(), fe = t.usePasskey(), Q = y(() => {
|
|
188
|
+
t?.user?.sourceProvider === "passkey" ? fe.switchPassport(t.user) : ["google", "apple", "email", "github"].includes(t?.user?.sourceProvider ?? "") ? ue.switchOAuthPassport(t.user) : t && t.switchPassport();
|
|
187
189
|
}), S = d(() => q ? /* @__PURE__ */ f(
|
|
188
190
|
a,
|
|
189
191
|
{
|
|
@@ -195,7 +197,7 @@ function Sr({
|
|
|
195
197
|
children: [
|
|
196
198
|
i ? /* @__PURE__ */ f(a, { sx: { border: "1px solid", borderColor: "divider", borderRadius: 1.5, p: 2 }, children: [
|
|
197
199
|
/* @__PURE__ */ e(
|
|
198
|
-
|
|
200
|
+
me,
|
|
199
201
|
{
|
|
200
202
|
sx: {
|
|
201
203
|
color: "text.primary",
|
|
@@ -205,12 +207,12 @@ function Sr({
|
|
|
205
207
|
children: g("passport")
|
|
206
208
|
}
|
|
207
209
|
),
|
|
208
|
-
/* @__PURE__ */ e(
|
|
210
|
+
/* @__PURE__ */ e(Ue, { user: n.data })
|
|
209
211
|
] }) : null,
|
|
210
|
-
/* @__PURE__ */ e(
|
|
212
|
+
/* @__PURE__ */ e(Ie, { user: n.data })
|
|
211
213
|
]
|
|
212
214
|
}
|
|
213
|
-
) : O && i ? E :
|
|
215
|
+
) : O && i ? E : ce && i ? /* @__PURE__ */ e(Fe, { children: /* @__PURE__ */ e(Re, {}) }) : null, [O, q, n, i, R, E]), G = d(() => /* @__PURE__ */ e(
|
|
214
216
|
a,
|
|
215
217
|
{
|
|
216
218
|
sx: {
|
|
@@ -234,7 +236,7 @@ function Sr({
|
|
|
234
236
|
alignItems: "center",
|
|
235
237
|
flex: 1
|
|
236
238
|
},
|
|
237
|
-
children: /* @__PURE__ */ e(
|
|
239
|
+
children: /* @__PURE__ */ e(he, {})
|
|
238
240
|
}
|
|
239
241
|
) : (
|
|
240
242
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
@@ -247,11 +249,11 @@ function Sr({
|
|
|
247
249
|
return null;
|
|
248
250
|
if (n.error) {
|
|
249
251
|
if (n.error?.response?.status === 404)
|
|
250
|
-
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(
|
|
252
|
+
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(ye, { status: 404, description: g("noUserFound") }) });
|
|
251
253
|
const b = {
|
|
252
254
|
message: n.error.response?.data?.error || n.error.message || "error occurred"
|
|
253
255
|
};
|
|
254
|
-
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(
|
|
256
|
+
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(Se, { error: b }) });
|
|
255
257
|
}
|
|
256
258
|
return !p && !n.data ? L || /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ f(
|
|
257
259
|
a,
|
|
@@ -265,7 +267,7 @@ function Sr({
|
|
|
265
267
|
},
|
|
266
268
|
children: [
|
|
267
269
|
/* @__PURE__ */ e(M, { children: g("viewAfterLogin") }),
|
|
268
|
-
/* @__PURE__ */ e(
|
|
270
|
+
/* @__PURE__ */ e(we, { size: "small", variant: "contained", onClick: () => t.login(), children: g("loginNow") })
|
|
269
271
|
]
|
|
270
272
|
}
|
|
271
273
|
) }) : I ? /* @__PURE__ */ f(U, { children: [
|
|
@@ -322,19 +324,20 @@ function Sr({
|
|
|
322
324
|
},
|
|
323
325
|
children: [
|
|
324
326
|
/* @__PURE__ */ e(
|
|
325
|
-
|
|
327
|
+
be,
|
|
326
328
|
{
|
|
327
329
|
orientation: "horizontal",
|
|
328
330
|
variant: "line",
|
|
329
331
|
tabs: c,
|
|
330
332
|
current: s?.value ?? h,
|
|
331
|
-
onChange:
|
|
333
|
+
onChange: de,
|
|
334
|
+
enableTabClick: !0,
|
|
332
335
|
sx: {
|
|
333
336
|
mb: 2,
|
|
334
337
|
".MuiTabs-flexContainer": {
|
|
335
338
|
gap: 3,
|
|
336
339
|
".MuiButtonBase-root": {
|
|
337
|
-
padding: l ? "16px 4px" : "
|
|
340
|
+
padding: l ? "16px 4px" : "32px 4px 16px 4px",
|
|
338
341
|
fontSize: 16
|
|
339
342
|
},
|
|
340
343
|
".MuiTab-root": {
|
|
@@ -365,7 +368,7 @@ function Sr({
|
|
|
365
368
|
]
|
|
366
369
|
}
|
|
367
370
|
),
|
|
368
|
-
!l && /* @__PURE__ */ e(
|
|
371
|
+
!l && /* @__PURE__ */ e(xe, { orientation: "vertical", sx: { ml: 5 } }),
|
|
369
372
|
/* @__PURE__ */ e(
|
|
370
373
|
re,
|
|
371
374
|
{
|
|
@@ -424,7 +427,7 @@ function Sr({
|
|
|
424
427
|
H
|
|
425
428
|
] }),
|
|
426
429
|
ne ? null : /* @__PURE__ */ e(
|
|
427
|
-
|
|
430
|
+
Te,
|
|
428
431
|
{
|
|
429
432
|
bordered: !0,
|
|
430
433
|
...ae,
|
|
@@ -440,5 +443,5 @@ function Sr({
|
|
|
440
443
|
);
|
|
441
444
|
}
|
|
442
445
|
export {
|
|
443
|
-
|
|
446
|
+
Dr as default
|
|
444
447
|
};
|
|
@@ -1,72 +1,72 @@
|
|
|
1
1
|
import { jsx as i } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import { useMemo as
|
|
4
|
-
import { IconButton as
|
|
5
|
-
import { useSnackbar as
|
|
6
|
-
import
|
|
2
|
+
import O from "prop-types";
|
|
3
|
+
import { useMemo as _, useCallback as h, useEffect as $ } from "react";
|
|
4
|
+
import { IconButton as g, Badge as B } from "@mui/material";
|
|
5
|
+
import { useSnackbar as D } from "notistack";
|
|
6
|
+
import S from "@arcblock/icons/lib/Notification";
|
|
7
7
|
import { useCreation as s } from "ahooks";
|
|
8
|
-
import { WELLKNOWN_SERVICE_PATH_PREFIX as
|
|
9
|
-
import
|
|
10
|
-
import { joinURL as
|
|
8
|
+
import { WELLKNOWN_SERVICE_PATH_PREFIX as V, EVENTS as y } from "@abtnode/constant";
|
|
9
|
+
import x from "@arcblock/react-hooks/lib/useBrowser";
|
|
10
|
+
import { joinURL as U, withQuery as I } from "ufo";
|
|
11
11
|
import { useListenWsClient as j } from "./ws.js";
|
|
12
12
|
import F from "../Notifications/Snackbar.js";
|
|
13
13
|
import { compareVersions as H } from "../utils.js";
|
|
14
|
-
const
|
|
14
|
+
const b = U(V, "user", "notifications"), K = (r) => I(b, {
|
|
15
15
|
id: r.id,
|
|
16
16
|
severity: r.severity || "all",
|
|
17
17
|
componentDid: r.source === "system" ? "system" : r.componentDid || "all"
|
|
18
18
|
});
|
|
19
19
|
function P({ session: r = {} }) {
|
|
20
|
-
const { unReadCount:
|
|
20
|
+
const { unReadCount: c, user: w, setUnReadCount: n } = r, e = s(() => w?.did, [w]), { enqueueSnackbar: E } = D(), l = x(), k = _(() => l.arcSphere || l.wallet, [l]), N = s(() => window.blocklet?.serverVersion, []), t = j("user"), d = s(
|
|
21
21
|
() => `${window.blocklet.did}/${e}/${y.NOTIFICATION_BLOCKLET_CREATE}`,
|
|
22
22
|
[e]
|
|
23
23
|
), u = s(
|
|
24
24
|
() => `${window.blocklet.did}/${e}/${y.NOTIFICATION_BLOCKLET_READ}`,
|
|
25
25
|
[e]
|
|
26
|
-
),
|
|
26
|
+
), a = h(
|
|
27
27
|
(o) => {
|
|
28
|
-
const { receivers:
|
|
29
|
-
if (
|
|
30
|
-
n((
|
|
31
|
-
const
|
|
32
|
-
if (!k && o.source === "component" &&
|
|
33
|
-
const
|
|
34
|
-
E(
|
|
28
|
+
const { receivers: f } = o ?? {}, { receiver: p } = f[0] ?? {};
|
|
29
|
+
if (p === e) {
|
|
30
|
+
n((v) => v + 1);
|
|
31
|
+
const C = H(N, "1.16.42-beta-20250407");
|
|
32
|
+
if (!k && o.source === "component" && C) {
|
|
33
|
+
const v = K(o), { severity: T, description: L } = o || {}, A = ["error", "warning"].includes(T) || o.sticky;
|
|
34
|
+
E(L, {
|
|
35
35
|
variant: T,
|
|
36
|
-
autoHideDuration:
|
|
36
|
+
autoHideDuration: A ? null : 5e3,
|
|
37
37
|
// eslint-disable-next-line react/no-unstable-nested-components
|
|
38
|
-
content: (
|
|
38
|
+
content: (R) => /* @__PURE__ */ i(F, { viewAllUrl: v, keyId: R, notification: o })
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
[e, n, E, N, k]
|
|
44
|
-
),
|
|
44
|
+
), m = h(
|
|
45
45
|
(o) => {
|
|
46
|
-
const { receiver:
|
|
47
|
-
|
|
46
|
+
const { receiver: f, readCount: p } = o ?? {};
|
|
47
|
+
f === e && n((C) => Math.max(C - p, 0));
|
|
48
48
|
},
|
|
49
49
|
[e, n]
|
|
50
50
|
);
|
|
51
|
-
return
|
|
52
|
-
t && (t.off(
|
|
53
|
-
}), [t, n,
|
|
54
|
-
|
|
51
|
+
return $(() => (t && (t.on(d, a), t.on(u, m)), () => {
|
|
52
|
+
t && (t.off(d, a), t.off(u, m));
|
|
53
|
+
}), [t, n, a, d, m, u]), !r.user || !b ? null : /* @__PURE__ */ i(
|
|
54
|
+
g,
|
|
55
55
|
{
|
|
56
56
|
size: "medium",
|
|
57
57
|
variant: "outlined",
|
|
58
|
-
href:
|
|
58
|
+
href: I(b, { read: c <= 0 }),
|
|
59
59
|
sx: {
|
|
60
60
|
"&:hover": {
|
|
61
61
|
borderRadius: "50%"
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
|
-
children: /* @__PURE__ */ i(
|
|
64
|
+
children: /* @__PURE__ */ i(B, { badgeContent: c, color: "error", invisible: c === 0, children: /* @__PURE__ */ i(S, { style: { width: "auto", height: 24 } }) })
|
|
65
65
|
}
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
P.propTypes = {
|
|
69
|
-
session:
|
|
69
|
+
session: O.object
|
|
70
70
|
};
|
|
71
71
|
export {
|
|
72
72
|
P as default
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.19",
|
|
4
4
|
"description": "Some useful front-end web components that can be used in Blocklets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@abtnode/constant": "^1.16.45",
|
|
37
37
|
"@abtnode/util": "^1.16.45",
|
|
38
|
-
"@arcblock/bridge": "3.0.
|
|
39
|
-
"@arcblock/icons": "3.0.
|
|
40
|
-
"@arcblock/react-hooks": "3.0.
|
|
38
|
+
"@arcblock/bridge": "3.0.19",
|
|
39
|
+
"@arcblock/icons": "3.0.19",
|
|
40
|
+
"@arcblock/react-hooks": "3.0.19",
|
|
41
41
|
"@arcblock/ws": "^1.20.15",
|
|
42
42
|
"@blocklet/constant": "^1.16.45",
|
|
43
43
|
"@blocklet/did-space-react": "^1.1.0",
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"jest": "^29.7.0",
|
|
91
91
|
"unbuild": "^2.0.0"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "c7886f76502bc62236cc1dd28aa26c050a702d1c"
|
|
94
94
|
}
|
package/src/@types/index.ts
CHANGED
|
@@ -2,103 +2,45 @@ import { use } from 'react';
|
|
|
2
2
|
import { Box, Button, Typography } from '@mui/material';
|
|
3
3
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
4
|
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
5
|
-
import {
|
|
5
|
+
import { useMemoizedFn } from 'ahooks';
|
|
6
6
|
import { useConfirm } from '@arcblock/ux/lib/Dialog';
|
|
7
7
|
import { SessionContext } from '@arcblock/did-connect/lib/Session';
|
|
8
|
-
import { LOGIN_PROVIDER } from '@blocklet/constant';
|
|
9
8
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
10
|
-
import type { ConnectProps } from '@arcblock/did-connect/lib/types';
|
|
11
9
|
|
|
12
10
|
import { translations } from '../libs/locales';
|
|
13
|
-
import { client } from '../../libs/client';
|
|
14
11
|
import type { SessionContext as TSessionContext } from '../../@types';
|
|
15
12
|
|
|
16
|
-
export default function DangerZone() {
|
|
17
|
-
const {
|
|
13
|
+
export default function DangerZone({ onDestroySelf = undefined }: { onDestroySelf?: () => void }) {
|
|
14
|
+
const { confirmHolder } = useConfirm();
|
|
18
15
|
|
|
19
16
|
const { locale } = useLocaleContext();
|
|
20
|
-
const { session
|
|
17
|
+
const { session } = use<TSessionContext>(SessionContext);
|
|
21
18
|
const t = useMemoizedFn((key, data = {}) => {
|
|
22
19
|
return translate(translations, key, locale, 'en', data);
|
|
23
20
|
});
|
|
24
|
-
const isNeedVerify = useCreation(() => {
|
|
25
|
-
if (['true', true].includes(window?.blocklet?.ALLOW_SKIP_DESTROY_MYSELF_VERIFY)) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
const connectedAccounts = session?.user?.connectedAccounts || [];
|
|
29
|
-
const ALLOW_VERIFY_PROVIDERS = [LOGIN_PROVIDER.WALLET];
|
|
30
|
-
if (connectedAccounts.some((x) => ALLOW_VERIFY_PROVIDERS.includes(x.provider))) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
const handleRemoveMyself = useMemoizedFn(async () => {
|
|
23
|
+
if (!onDestroySelf || typeof onDestroySelf !== 'function') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
saveConnect: false,
|
|
45
|
-
autoConnect: false,
|
|
46
|
-
// 暂不允许使用 passkey 进行验证
|
|
47
|
-
passkeyBehavior: 'none',
|
|
48
|
-
extraParams: {
|
|
49
|
-
removeUserDid: userDid,
|
|
50
|
-
},
|
|
51
|
-
messages: {
|
|
52
|
-
title: t('destroyMyself.title'),
|
|
53
|
-
scan: t('destroyMyself.scan'),
|
|
54
|
-
confirm: t('destroyMyself.confirm'),
|
|
55
|
-
success: t('destroyMyself.success'),
|
|
56
|
-
},
|
|
57
|
-
// @ts-expect-error 该 did-connect 后端api 将结果塞在了 result 中,并做了加密,所以已经变成一个字符串了
|
|
58
|
-
onSuccess: ({ result }: { result: string }, decrypt = (x: string) => x) => {
|
|
59
|
-
const decryptResult = decrypt(result) as unknown as { did: string };
|
|
60
|
-
resolve(decryptResult);
|
|
61
|
-
},
|
|
62
|
-
onClose: () => {
|
|
63
|
-
connectApi.close();
|
|
64
|
-
reject(new Error(t('destroyMyself.abort')));
|
|
27
|
+
const handle = session.withSecondaryAuth(onDestroySelf, {
|
|
28
|
+
extraParams: {
|
|
29
|
+
locale,
|
|
30
|
+
removeUserDid: session?.user?.did,
|
|
31
|
+
input: {
|
|
32
|
+
user: { did: session?.user?.did },
|
|
33
|
+
teamDid: window?.blocklet?.did,
|
|
65
34
|
},
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const handleDeleteAccount = useMemoizedFn(() => {
|
|
71
|
-
confirmApi.open({
|
|
72
|
-
title: t('dangerZone.deleteAccount'),
|
|
73
|
-
content: t('dangerZone.deleteAccountDescription'),
|
|
74
|
-
confirmButtonText: t('common.confirm'),
|
|
75
|
-
confirmButtonProps: {
|
|
76
|
-
color: 'error',
|
|
77
|
-
},
|
|
78
|
-
cancelButtonText: t('common.cancel'),
|
|
79
|
-
async onConfirm(close: () => void) {
|
|
80
|
-
let result;
|
|
81
|
-
try {
|
|
82
|
-
if (isNeedVerify) {
|
|
83
|
-
result = await handleVerify();
|
|
84
|
-
} else if (client?.user?.destroyMyself instanceof Function) {
|
|
85
|
-
result = await client.user.destroyMyself();
|
|
86
|
-
} else {
|
|
87
|
-
Toast.error(t('notImplemented'));
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
if (result?.did === session?.user?.did) {
|
|
91
|
-
// TODO: 前端执行退出等清理操作
|
|
92
|
-
session.logout(close);
|
|
93
|
-
} else {
|
|
94
|
-
Toast.error(t('destroyMyself.error'));
|
|
95
|
-
}
|
|
96
|
-
} catch (error: any) {
|
|
97
|
-
const errorMessage = error?.response?.data.error || error?.message || t('destroyMyself.error');
|
|
98
|
-
Toast.error(errorMessage);
|
|
99
|
-
}
|
|
100
35
|
},
|
|
36
|
+
operation: 'destroySelf',
|
|
101
37
|
});
|
|
38
|
+
try {
|
|
39
|
+
await handle();
|
|
40
|
+
session.logout();
|
|
41
|
+
} catch (error: any) {
|
|
42
|
+
Toast.error(error?.message || t('destroyMyself.error'));
|
|
43
|
+
}
|
|
102
44
|
});
|
|
103
45
|
|
|
104
46
|
return (
|
|
@@ -129,7 +71,7 @@ export default function DangerZone() {
|
|
|
129
71
|
{t('dangerZone.deleteAccountDescription')}
|
|
130
72
|
</Typography>
|
|
131
73
|
</Box>
|
|
132
|
-
<Button variant="contained" color="error" size="small" onClick={
|
|
74
|
+
<Button variant="contained" color="error" size="small" onClick={handleRemoveMyself}>
|
|
133
75
|
{t('dangerZone.delete')}
|
|
134
76
|
</Button>
|
|
135
77
|
</Box>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
import { Box, Typography } from '@mui/material';
|
|
3
3
|
import type { BoxProps } from '@mui/material';
|
|
4
|
+
import { ROLES } from '@abtnode/constant';
|
|
4
5
|
import { useCreation, useMemoizedFn } from 'ahooks';
|
|
5
6
|
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
6
7
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
@@ -29,6 +30,7 @@ export default function Settings({
|
|
|
29
30
|
userCenterTabs: UserCenterTab[];
|
|
30
31
|
};
|
|
31
32
|
isMobile: boolean;
|
|
33
|
+
onDestroySelf?: () => void;
|
|
32
34
|
} & BoxProps) {
|
|
33
35
|
const { locale } = useLocaleContext();
|
|
34
36
|
const browser = useBrowser();
|
|
@@ -36,6 +38,11 @@ export default function Settings({
|
|
|
36
38
|
const t = useMemoizedFn((key, data = {}) => {
|
|
37
39
|
return translate(translations, key, locale, 'en', data);
|
|
38
40
|
});
|
|
41
|
+
|
|
42
|
+
const isOwner = useCreation(() => {
|
|
43
|
+
return user.passports?.some((x) => x.role === ROLES.OWNER);
|
|
44
|
+
}, [user]);
|
|
45
|
+
|
|
39
46
|
const privacyConfigList = useCreation(() => {
|
|
40
47
|
const userCenterTabs = settings?.userCenterTabs || [];
|
|
41
48
|
return userCenterTabs.map((item) => {
|
|
@@ -84,14 +91,16 @@ export default function Settings({
|
|
|
84
91
|
/>
|
|
85
92
|
),
|
|
86
93
|
},
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
!isOwner && rest.onDestroySelf && typeof rest.onDestroySelf === 'function'
|
|
95
|
+
? {
|
|
96
|
+
label: t('dangerZone.title'),
|
|
97
|
+
value: 'dangerZone',
|
|
98
|
+
content: <DangerZone onDestroySelf={rest.onDestroySelf} />,
|
|
99
|
+
sx: {
|
|
100
|
+
borderColor: 'error.main',
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
: null,
|
|
95
104
|
].filter(Boolean);
|
|
96
105
|
}, [user, privacyConfigList, isMobile]);
|
|
97
106
|
|
|
@@ -90,6 +90,7 @@ export default function UserCenter({
|
|
|
90
90
|
stickySidebar = false,
|
|
91
91
|
embed = false,
|
|
92
92
|
onlyProfile = false, // 只显示 profile 页面,用于 ArcSphere 只需要显示 Profile 的内容
|
|
93
|
+
onDestroySelf = undefined,
|
|
93
94
|
}: {
|
|
94
95
|
readonly children: any;
|
|
95
96
|
readonly notLoginContent?: any;
|
|
@@ -105,6 +106,7 @@ export default function UserCenter({
|
|
|
105
106
|
readonly stickySidebar?: boolean;
|
|
106
107
|
readonly embed?: boolean;
|
|
107
108
|
readonly onlyProfile?: boolean;
|
|
109
|
+
readonly onDestroySelf?: () => void;
|
|
108
110
|
}) {
|
|
109
111
|
const { locale } = useLocaleContext();
|
|
110
112
|
const isMobile = useMobile({ key: 'md' });
|
|
@@ -287,6 +289,7 @@ export default function UserCenter({
|
|
|
287
289
|
return null;
|
|
288
290
|
}}
|
|
289
291
|
isMobile={isMobile}
|
|
292
|
+
onDestroySelf={onDestroySelf}
|
|
290
293
|
/>
|
|
291
294
|
);
|
|
292
295
|
}, [userState.data, userCenterTabs, privacyState.data, privacyState.runAsync]);
|
|
@@ -523,12 +526,13 @@ export default function UserCenter({
|
|
|
523
526
|
tabs={userCenterTabs}
|
|
524
527
|
current={currentActiveTab?.value ?? currentTab}
|
|
525
528
|
onChange={handleChangeTab}
|
|
529
|
+
enableTabClick
|
|
526
530
|
sx={{
|
|
527
531
|
mb: 2,
|
|
528
532
|
'.MuiTabs-flexContainer': {
|
|
529
533
|
gap: 3,
|
|
530
534
|
'.MuiButtonBase-root': {
|
|
531
|
-
padding: isMobile ? '16px 4px' : '
|
|
535
|
+
padding: isMobile ? '16px 4px' : '32px 4px 16px 4px',
|
|
532
536
|
fontSize: 16,
|
|
533
537
|
},
|
|
534
538
|
'.MuiTab-root': {
|
|
@@ -107,7 +107,7 @@ export default function NotificationAddon({ session = {} }) {
|
|
|
107
107
|
<IconButton
|
|
108
108
|
size="medium"
|
|
109
109
|
variant="outlined"
|
|
110
|
-
href={viewAllUrl}
|
|
110
|
+
href={withQuery(viewAllUrl, { read: unReadCount <= 0 })}
|
|
111
111
|
sx={{
|
|
112
112
|
'&:hover': {
|
|
113
113
|
borderRadius: '50%',
|