@blocklet/ui-react 3.1.25 → 3.1.27
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 -1
- package/lib/UserCenter/components/fallback.d.ts +8 -0
- package/lib/UserCenter/components/fallback.js +21 -0
- package/lib/UserCenter/components/user-center.js +205 -200
- package/lib/UserCenter/components/user-info/social-actions/chat.d.ts +5 -0
- package/lib/UserCenter/components/user-info/social-actions/chat.js +24 -0
- package/lib/UserCenter/components/user-info/social-actions/follow.d.ts +2 -0
- package/lib/UserCenter/components/user-info/social-actions/follow.js +19 -0
- package/lib/UserCenter/components/user-info/social-actions/index.d.ts +5 -0
- package/lib/UserCenter/components/user-info/social-actions/index.js +13 -0
- package/lib/UserCenter/components/user-info/user-basic-info.js +37 -35
- package/lib/UserCenter/libs/locales.d.ts +14 -0
- package/lib/UserCenter/libs/locales.js +16 -2
- package/lib/contexts/user-followers.d.ts +13 -0
- package/lib/contexts/user-followers.js +40 -0
- package/lib/hooks/use-follow.d.ts +12 -0
- package/lib/hooks/use-follow.js +47 -0
- package/package.json +6 -6
- package/src/@types/index.ts +1 -1
- package/src/UserCenter/components/fallback.tsx +51 -0
- package/src/UserCenter/components/user-center.tsx +22 -12
- package/src/UserCenter/components/user-info/social-actions/chat.tsx +42 -0
- package/src/UserCenter/components/user-info/social-actions/follow.tsx +30 -0
- package/src/UserCenter/components/user-info/social-actions/index.tsx +17 -0
- package/src/UserCenter/components/user-info/user-basic-info.tsx +6 -0
- package/src/UserCenter/libs/locales.ts +14 -0
- package/src/contexts/user-followers.tsx +54 -0
- package/src/hooks/use-follow.tsx +74 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsxs as m, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { Button as s } from "@mui/material";
|
|
3
|
+
import { useMemoizedFn as p } from "ahooks";
|
|
4
|
+
import { translate as a } from "@arcblock/ux/lib/Locale/util";
|
|
5
|
+
import { useLocaleContext as c } from "@arcblock/ux/lib/Locale/context";
|
|
6
|
+
import u from "@mui/icons-material/Notifications";
|
|
7
|
+
import x from "@mui/icons-material/NotificationsOff";
|
|
8
|
+
import { translations as w } from "../../../libs/locales.js";
|
|
9
|
+
import { useUserFollowersContext as d } from "../../../../contexts/user-followers.js";
|
|
10
|
+
function R() {
|
|
11
|
+
const { locale: i } = c(), t = p((l, f = {}) => a(w, l, i, "en", f)), { followed: o, followUser: n, unfollowUser: e } = d();
|
|
12
|
+
return /* @__PURE__ */ m(s, { variant: "contained", onClick: () => o ? e() : n(), fullWidth: !0, children: [
|
|
13
|
+
o ? /* @__PURE__ */ r(x, { sx: { fontSize: "14px", marginRight: "4px" } }) : /* @__PURE__ */ r(u, { sx: { fontSize: "14px", marginRight: "4px" } }),
|
|
14
|
+
t(o ? "profile.unfollow" : "profile.follow")
|
|
15
|
+
] });
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
R as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsxs as t, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { Box as i } from "@mui/material";
|
|
3
|
+
import m from "./chat.js";
|
|
4
|
+
import f from "./follow.js";
|
|
5
|
+
function x({ user: r }) {
|
|
6
|
+
return /* @__PURE__ */ t(i, { sx: { display: "flex", gap: 1 }, children: [
|
|
7
|
+
/* @__PURE__ */ o(m, { user: r }),
|
|
8
|
+
/* @__PURE__ */ o(f, {})
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
x as default
|
|
13
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsxs as c, jsx as r, Fragment as E } from "react/jsx-runtime";
|
|
2
|
-
import { Box as l, Typography as
|
|
2
|
+
import { Box as l, Typography as S, Divider as B, IconButton as N, Collapse as T } from "@mui/material";
|
|
3
3
|
import F from "@arcblock/ux/lib/Avatar";
|
|
4
4
|
import K from "@arcblock/ux/lib/DID";
|
|
5
5
|
import { useMemoizedFn as W } from "ahooks";
|
|
6
6
|
import { translate as O } from "@arcblock/ux/lib/Locale/util";
|
|
7
7
|
import { useLocaleContext as Q } from "@arcblock/ux/lib/Locale/context";
|
|
8
8
|
import V from "lodash/noop";
|
|
9
|
-
import { useState as
|
|
9
|
+
import { useState as U, useEffect as y } from "react";
|
|
10
10
|
import C from "@arcblock/ux/lib/Toast";
|
|
11
11
|
import { parseURL as Y, joinURL as $ } from "ufo";
|
|
12
12
|
import { KeyboardArrowUp as q, KeyboardArrowDown as G } from "@mui/icons-material";
|
|
@@ -18,29 +18,30 @@ import P from "./metadata.js";
|
|
|
18
18
|
import M from "./user-status.js";
|
|
19
19
|
import tt from "./user-info.js";
|
|
20
20
|
import { client as j } from "../../../libs/client.js";
|
|
21
|
-
|
|
21
|
+
import rt from "./social-actions/index.js";
|
|
22
|
+
function Ct({
|
|
22
23
|
user: t,
|
|
23
|
-
isMyself:
|
|
24
|
+
isMyself: e = !0,
|
|
24
25
|
showFullDid: f = !0,
|
|
25
26
|
switchPassport: I,
|
|
26
27
|
switchProfile: R,
|
|
27
|
-
isMobile:
|
|
28
|
+
isMobile: a = !1,
|
|
28
29
|
onlyProfile: s = !1,
|
|
29
30
|
refreshProfile: u,
|
|
30
31
|
...m
|
|
31
32
|
}) {
|
|
32
|
-
const { locale: x } = Q(), [h, g] =
|
|
33
|
-
|
|
33
|
+
const { locale: x } = Q(), [h, g] = U(void 0), w = W((n, o = {}) => O(H, n, x, "en", o)), [d, v] = U(!a || s);
|
|
34
|
+
y(() => {
|
|
34
35
|
g(t?.metadata?.status);
|
|
35
|
-
}, [t]),
|
|
36
|
-
v(!
|
|
37
|
-
}, [
|
|
36
|
+
}, [t]), y(() => {
|
|
37
|
+
v(!a || s);
|
|
38
|
+
}, [a, s]);
|
|
38
39
|
const A = async (n) => {
|
|
39
|
-
if (
|
|
40
|
+
if (e)
|
|
40
41
|
try {
|
|
41
42
|
if (n) {
|
|
42
|
-
const
|
|
43
|
-
n.dateRange =
|
|
43
|
+
const o = X(n);
|
|
44
|
+
n.dateRange = o.length > 0 ? o : h?.dateRange ?? [];
|
|
44
45
|
}
|
|
45
46
|
g(n), await j.user.saveProfile({
|
|
46
47
|
// @ts-ignore
|
|
@@ -49,8 +50,8 @@ function St({
|
|
|
49
50
|
status: n || {}
|
|
50
51
|
}
|
|
51
52
|
}), u();
|
|
52
|
-
} catch (
|
|
53
|
-
console.error(
|
|
53
|
+
} catch (o) {
|
|
54
|
+
console.error(o), C.error(z(o));
|
|
54
55
|
}
|
|
55
56
|
}, b = () => {
|
|
56
57
|
v(!d);
|
|
@@ -58,11 +59,11 @@ function St({
|
|
|
58
59
|
if (!t)
|
|
59
60
|
return null;
|
|
60
61
|
const D = async (n) => {
|
|
61
|
-
if (!
|
|
62
|
+
if (!e)
|
|
62
63
|
return;
|
|
63
|
-
const { metadata:
|
|
64
|
+
const { metadata: o, address: L } = n;
|
|
64
65
|
try {
|
|
65
|
-
const p =
|
|
66
|
+
const p = o?.links?.map((i) => {
|
|
66
67
|
if (!i.url || !Z(i.url)) return null;
|
|
67
68
|
try {
|
|
68
69
|
return Y(i.url).protocol || (i.url = $("https://", i.url)), i;
|
|
@@ -70,7 +71,7 @@ function St({
|
|
|
70
71
|
return console.error("Invalid URL:", i.url), null;
|
|
71
72
|
}
|
|
72
73
|
}).filter((i) => !!i) || [];
|
|
73
|
-
|
|
74
|
+
o.links = p, await j.user.saveProfile({ metadata: o, address: L }), u();
|
|
74
75
|
} catch (p) {
|
|
75
76
|
console.error(p), C.error(z(p));
|
|
76
77
|
}
|
|
@@ -90,7 +91,7 @@ function St({
|
|
|
90
91
|
className: "user-info",
|
|
91
92
|
sx: {
|
|
92
93
|
display: "flex",
|
|
93
|
-
flexDirection:
|
|
94
|
+
flexDirection: a ? "row" : "column",
|
|
94
95
|
gap: 2
|
|
95
96
|
},
|
|
96
97
|
children: [
|
|
@@ -110,7 +111,7 @@ function St({
|
|
|
110
111
|
{
|
|
111
112
|
src: t?.avatar,
|
|
112
113
|
did: t?.did,
|
|
113
|
-
size: m.size || (
|
|
114
|
+
size: m.size || (a ? 64 : 100),
|
|
114
115
|
variant: "circle",
|
|
115
116
|
shape: "circle",
|
|
116
117
|
sx: {
|
|
@@ -119,7 +120,7 @@ function St({
|
|
|
119
120
|
position: "relative",
|
|
120
121
|
overflow: "hidden",
|
|
121
122
|
flexShrink: 0,
|
|
122
|
-
...
|
|
123
|
+
...e ? {
|
|
123
124
|
cursor: "pointer",
|
|
124
125
|
"&::after": {
|
|
125
126
|
content: `"${w("switchProfile")}"`,
|
|
@@ -137,15 +138,15 @@ function St({
|
|
|
137
138
|
}
|
|
138
139
|
} : {}
|
|
139
140
|
},
|
|
140
|
-
onClick:
|
|
141
|
+
onClick: e ? R : V
|
|
141
142
|
}
|
|
142
143
|
),
|
|
143
144
|
/* @__PURE__ */ r(
|
|
144
145
|
M,
|
|
145
146
|
{
|
|
146
|
-
isMobile:
|
|
147
|
-
size: m.size || (
|
|
148
|
-
isMyself:
|
|
147
|
+
isMobile: a,
|
|
148
|
+
size: m.size || (a ? 64 : 100),
|
|
149
|
+
isMyself: e,
|
|
149
150
|
timezone: t?.metadata?.timezone || J,
|
|
150
151
|
status: h,
|
|
151
152
|
onChange: A
|
|
@@ -163,7 +164,7 @@ function St({
|
|
|
163
164
|
},
|
|
164
165
|
children: [
|
|
165
166
|
/* @__PURE__ */ c(
|
|
166
|
-
|
|
167
|
+
S,
|
|
167
168
|
{
|
|
168
169
|
variant: "h6",
|
|
169
170
|
component: "div",
|
|
@@ -188,7 +189,7 @@ function St({
|
|
|
188
189
|
children: t?.fullName
|
|
189
190
|
}
|
|
190
191
|
),
|
|
191
|
-
|
|
192
|
+
e ? /* @__PURE__ */ r(_, { user: t, switchPassport: I }) : null
|
|
192
193
|
]
|
|
193
194
|
}
|
|
194
195
|
),
|
|
@@ -199,10 +200,11 @@ function St({
|
|
|
199
200
|
]
|
|
200
201
|
}
|
|
201
202
|
),
|
|
202
|
-
/* @__PURE__ */ r(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
e ? null : /* @__PURE__ */ r(l, { sx: { mt: 2 }, children: /* @__PURE__ */ r(rt, { user: t }) }),
|
|
204
|
+
/* @__PURE__ */ r(P, { isMobile: a, isMyself: e, user: t, onSave: D }),
|
|
205
|
+
e ? /* @__PURE__ */ c(E, { children: [
|
|
206
|
+
/* @__PURE__ */ r(B, { sx: { my: a ? 1 : 3 } }),
|
|
207
|
+
a && !s ? /* @__PURE__ */ r(
|
|
206
208
|
l,
|
|
207
209
|
{
|
|
208
210
|
sx: {
|
|
@@ -229,7 +231,7 @@ function St({
|
|
|
229
231
|
) : null,
|
|
230
232
|
/* @__PURE__ */ c(T, { in: d, timeout: "auto", children: [
|
|
231
233
|
/* @__PURE__ */ r(
|
|
232
|
-
|
|
234
|
+
S,
|
|
233
235
|
{
|
|
234
236
|
component: "p",
|
|
235
237
|
sx: {
|
|
@@ -240,7 +242,7 @@ function St({
|
|
|
240
242
|
children: w("profile.justForYou")
|
|
241
243
|
}
|
|
242
244
|
),
|
|
243
|
-
/* @__PURE__ */ r(tt, { user: t, isMySelf:
|
|
245
|
+
/* @__PURE__ */ r(tt, { user: t, isMySelf: e })
|
|
244
246
|
] })
|
|
245
247
|
] }) : null
|
|
246
248
|
]
|
|
@@ -248,5 +250,5 @@ function St({
|
|
|
248
250
|
);
|
|
249
251
|
}
|
|
250
252
|
export {
|
|
251
|
-
|
|
253
|
+
Ct as default
|
|
252
254
|
};
|
|
@@ -25,10 +25,12 @@ export declare const translations: {
|
|
|
25
25
|
emptyField: string;
|
|
26
26
|
emptyContent: string;
|
|
27
27
|
underProtected: string;
|
|
28
|
+
followersOnly: string;
|
|
28
29
|
noUserFound: string;
|
|
29
30
|
notificationManagement: string;
|
|
30
31
|
privacyManagement: string;
|
|
31
32
|
storageManagement: string;
|
|
33
|
+
userFollowers: string;
|
|
32
34
|
webhook: {
|
|
33
35
|
url: string;
|
|
34
36
|
slack: string;
|
|
@@ -159,6 +161,11 @@ export declare const translations: {
|
|
|
159
161
|
invalidPostalCode: string;
|
|
160
162
|
};
|
|
161
163
|
maxLinkCount: string;
|
|
164
|
+
chat: string;
|
|
165
|
+
follow: string;
|
|
166
|
+
unfollow: string;
|
|
167
|
+
follow_success: string;
|
|
168
|
+
unfollow_success: string;
|
|
162
169
|
};
|
|
163
170
|
destroyMyself: {
|
|
164
171
|
title: string;
|
|
@@ -201,8 +208,10 @@ export declare const translations: {
|
|
|
201
208
|
notificationManagement: string;
|
|
202
209
|
privacyManagement: string;
|
|
203
210
|
storageManagement: string;
|
|
211
|
+
userFollowers: string;
|
|
204
212
|
emptyContent: string;
|
|
205
213
|
underProtected: string;
|
|
214
|
+
followersOnly: string;
|
|
206
215
|
noUserFound: string;
|
|
207
216
|
webhook: {
|
|
208
217
|
url: string;
|
|
@@ -335,6 +344,11 @@ export declare const translations: {
|
|
|
335
344
|
invalidPostalCode: string;
|
|
336
345
|
};
|
|
337
346
|
maxLinkCount: string;
|
|
347
|
+
chat: string;
|
|
348
|
+
follow: string;
|
|
349
|
+
unfollow: string;
|
|
350
|
+
follow_success: string;
|
|
351
|
+
unfollow_success: string;
|
|
338
352
|
};
|
|
339
353
|
destroyMyself: {
|
|
340
354
|
title: string;
|
|
@@ -25,10 +25,12 @@ const e = {
|
|
|
25
25
|
emptyField: "未填写",
|
|
26
26
|
emptyContent: "暂无内容",
|
|
27
27
|
underProtected: "用户已设置隐私保护",
|
|
28
|
+
followersOnly: "用户已设置仅粉丝可见,关注用户后可查看",
|
|
28
29
|
noUserFound: "未找到指定的用户",
|
|
29
30
|
notificationManagement: "通知管理",
|
|
30
31
|
privacyManagement: "隐私管理",
|
|
31
32
|
storageManagement: "DID Spaces",
|
|
33
|
+
userFollowers: "关注 & 粉丝",
|
|
32
34
|
webhook: {
|
|
33
35
|
url: "自定义URL",
|
|
34
36
|
slack: "Slack"
|
|
@@ -158,7 +160,12 @@ const e = {
|
|
|
158
160
|
postalCode: "邮政编码",
|
|
159
161
|
invalidPostalCode: "邮政编码格式不正确"
|
|
160
162
|
},
|
|
161
|
-
maxLinkCount: "最多可添加 {count} 个社交链接"
|
|
163
|
+
maxLinkCount: "最多可添加 {count} 个社交链接",
|
|
164
|
+
chat: "聊天",
|
|
165
|
+
follow: "关注",
|
|
166
|
+
unfollow: "取消关注",
|
|
167
|
+
follow_success: "关注成功",
|
|
168
|
+
unfollow_success: "取消关注成功"
|
|
162
169
|
},
|
|
163
170
|
destroyMyself: {
|
|
164
171
|
title: "删除账户",
|
|
@@ -201,8 +208,10 @@ const e = {
|
|
|
201
208
|
notificationManagement: "Notifications",
|
|
202
209
|
privacyManagement: "Privacy",
|
|
203
210
|
storageManagement: "DID Spaces",
|
|
211
|
+
userFollowers: "Following & Followers",
|
|
204
212
|
emptyContent: "Empty",
|
|
205
213
|
underProtected: "This page has protected privacy",
|
|
214
|
+
followersOnly: "This page is only visible to followers, follow the user to view",
|
|
206
215
|
noUserFound: "No user found",
|
|
207
216
|
webhook: {
|
|
208
217
|
url: "Custom url",
|
|
@@ -334,7 +343,12 @@ const e = {
|
|
|
334
343
|
postalCode: "Postal Code",
|
|
335
344
|
invalidPostalCode: "Postal code is invalid"
|
|
336
345
|
},
|
|
337
|
-
maxLinkCount: "Up to {count} social links can be added"
|
|
346
|
+
maxLinkCount: "Up to {count} social links can be added",
|
|
347
|
+
chat: "Chat",
|
|
348
|
+
follow: "Follow",
|
|
349
|
+
unfollow: "Unfollow",
|
|
350
|
+
follow_success: "Follow successfully",
|
|
351
|
+
unfollow_success: "Unfollow successfully"
|
|
338
352
|
},
|
|
339
353
|
destroyMyself: {
|
|
340
354
|
title: "Delete Account",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const UserFollowersContext: import('react').Context<UserFollowersContextType>;
|
|
2
|
+
type UserFollowersContextType = {
|
|
3
|
+
followed: boolean;
|
|
4
|
+
followUser: () => void;
|
|
5
|
+
unfollowUser: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare function UserFollowersProvider({ isMySelf, userDid, children, }: {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
isMySelf: boolean;
|
|
10
|
+
userDid: string;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
declare function useUserFollowersContext(): UserFollowersContextType;
|
|
13
|
+
export { UserFollowersContext, useUserFollowersContext, UserFollowersProvider };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as c } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as w, useContext as a } from "react";
|
|
3
|
+
import { translate as p } from "@arcblock/ux/lib/Locale/util";
|
|
4
|
+
import { useMemoizedFn as x } from "ahooks";
|
|
5
|
+
import { useLocaleContext as U } from "@arcblock/ux/lib/Locale/context";
|
|
6
|
+
import d from "../hooks/use-follow.js";
|
|
7
|
+
import { translations as C } from "../UserCenter/libs/locales.js";
|
|
8
|
+
const e = w({
|
|
9
|
+
followed: !1,
|
|
10
|
+
followUser: () => {
|
|
11
|
+
},
|
|
12
|
+
unfollowUser: () => {
|
|
13
|
+
}
|
|
14
|
+
}), { Provider: F } = e;
|
|
15
|
+
function g({
|
|
16
|
+
isMySelf: o,
|
|
17
|
+
userDid: r,
|
|
18
|
+
children: t
|
|
19
|
+
}) {
|
|
20
|
+
const { locale: s } = U(), l = x((i, u = {}) => p(C, i, s, "en", u)), { followed: n, followUser: f, unfollowUser: m } = d({ userDid: r, t: l, isMySelf: o });
|
|
21
|
+
return /* @__PURE__ */ c(
|
|
22
|
+
F,
|
|
23
|
+
{
|
|
24
|
+
value: {
|
|
25
|
+
followed: n,
|
|
26
|
+
followUser: f,
|
|
27
|
+
unfollowUser: m
|
|
28
|
+
},
|
|
29
|
+
children: t
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function h() {
|
|
34
|
+
return a(e);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
e as UserFollowersContext,
|
|
38
|
+
g as UserFollowersProvider,
|
|
39
|
+
h as useUserFollowersContext
|
|
40
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 登录用户与当前用户(userDid)的关注关系
|
|
3
|
+
*/
|
|
4
|
+
export default function useFollow({ userDid, t, isMySelf, }: {
|
|
5
|
+
userDid: string;
|
|
6
|
+
t: (k: string) => string;
|
|
7
|
+
isMySelf: boolean;
|
|
8
|
+
}): {
|
|
9
|
+
followed: boolean;
|
|
10
|
+
followUser: (this: unknown, followUserDid?: string | undefined) => Promise<void>;
|
|
11
|
+
unfollowUser: (this: unknown, unfollowUserDid?: string | undefined) => Promise<void>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useState as p, useEffect as F } from "react";
|
|
2
|
+
import { useMemoizedFn as n } from "ahooks";
|
|
3
|
+
import c from "@arcblock/ux/lib/Toast";
|
|
4
|
+
import { client as l } from "../libs/client.js";
|
|
5
|
+
import { formatAxiosError as u } from "../UserCenter/libs/utils.js";
|
|
6
|
+
function E({
|
|
7
|
+
userDid: o,
|
|
8
|
+
t: a,
|
|
9
|
+
isMySelf: e
|
|
10
|
+
}) {
|
|
11
|
+
const [i, f] = p(!1), t = n(async () => {
|
|
12
|
+
try {
|
|
13
|
+
if (e) {
|
|
14
|
+
f(!0);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const r = await l.user.isFollowingUser({ userDid: o });
|
|
18
|
+
f(r);
|
|
19
|
+
} catch (r) {
|
|
20
|
+
console.error(r);
|
|
21
|
+
}
|
|
22
|
+
}), m = n(async (r = o) => {
|
|
23
|
+
if (!(e && r === o))
|
|
24
|
+
try {
|
|
25
|
+
await l.user.followUser({ userDid: r }), c.success(a("profile.follow_success")), t();
|
|
26
|
+
} catch (s) {
|
|
27
|
+
console.error(s), c.error(u(s));
|
|
28
|
+
}
|
|
29
|
+
}), w = n(async (r = o) => {
|
|
30
|
+
if (!(e && r === o))
|
|
31
|
+
try {
|
|
32
|
+
await l.user.unfollowUser({ userDid: r }), c.success(a("profile.unfollow_success")), t();
|
|
33
|
+
} catch (s) {
|
|
34
|
+
console.error(s), c.error(u(s));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return F(() => {
|
|
38
|
+
o && !e && t();
|
|
39
|
+
}, [t, o, e]), {
|
|
40
|
+
followed: i,
|
|
41
|
+
followUser: m,
|
|
42
|
+
unfollowUser: w
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
E as default
|
|
47
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.27",
|
|
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.48",
|
|
37
37
|
"@abtnode/util": "^1.16.48",
|
|
38
|
-
"@arcblock/bridge": "3.1.
|
|
39
|
-
"@arcblock/icons": "3.1.
|
|
40
|
-
"@arcblock/react-hooks": "3.1.
|
|
38
|
+
"@arcblock/bridge": "3.1.27",
|
|
39
|
+
"@arcblock/icons": "3.1.27",
|
|
40
|
+
"@arcblock/react-hooks": "3.1.27",
|
|
41
41
|
"@arcblock/ws": "^1.21.3",
|
|
42
42
|
"@blocklet/constant": "^1.16.48",
|
|
43
43
|
"@blocklet/did-space-react": "^1.1.16",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"access": "public"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"@arcblock/did-connect-react": "3.1.
|
|
87
|
+
"@arcblock/did-connect-react": "3.1.27",
|
|
88
88
|
"@types/dompurify": "^3.2.0",
|
|
89
89
|
"@types/ua-parser-js": "^0.7.39",
|
|
90
90
|
"@types/validator": "^13.15.2",
|
|
@@ -92,5 +92,5 @@
|
|
|
92
92
|
"jest": "^29.7.0",
|
|
93
93
|
"unbuild": "^2.0.0"
|
|
94
94
|
},
|
|
95
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "9cbf9135aa96ce8d13481db7b21f755d009d2f9f"
|
|
96
96
|
}
|
package/src/@types/index.ts
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户中心 fallback 组件,用于没有权限访问时展示的页面
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Empty from '@arcblock/ux/lib/Empty';
|
|
7
|
+
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
8
|
+
import { useMemoizedFn } from 'ahooks';
|
|
9
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
10
|
+
|
|
11
|
+
import { translations } from '../libs/locales';
|
|
12
|
+
import { UserCenterTab } from '../../@types';
|
|
13
|
+
import { useUserFollowersContext } from '../../contexts/user-followers';
|
|
14
|
+
|
|
15
|
+
function Fallback({
|
|
16
|
+
currentActiveTab,
|
|
17
|
+
isMyself,
|
|
18
|
+
children,
|
|
19
|
+
}: {
|
|
20
|
+
currentActiveTab: UserCenterTab;
|
|
21
|
+
isMyself: boolean;
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}) {
|
|
24
|
+
const { locale } = useLocaleContext();
|
|
25
|
+
const t = useMemoizedFn((key, data = {}) => {
|
|
26
|
+
return translate(translations, key, locale, 'en', data);
|
|
27
|
+
});
|
|
28
|
+
const { followed } = useUserFollowersContext();
|
|
29
|
+
|
|
30
|
+
// 自己的页面或公开内容,直接显示
|
|
31
|
+
if (isMyself || !currentActiveTab?.protected || currentActiveTab?.protected === 'all') {
|
|
32
|
+
return children;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { protected: protection } = currentActiveTab;
|
|
36
|
+
|
|
37
|
+
// 私密内容(仅自己可见)
|
|
38
|
+
if (protection === true || protection === 'private') {
|
|
39
|
+
return <Empty>{t('underProtected')}</Empty>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 仅粉丝可见内容
|
|
43
|
+
if (protection === 'follower-only') {
|
|
44
|
+
return followed ? children : <Empty>{t('followersOnly')}</Empty>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 未知的保护类型,默认不显示
|
|
48
|
+
return <Empty>{t('underProtected')}</Empty>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default Fallback;
|
|
@@ -35,10 +35,13 @@ import useMobile from '../../hooks/use-mobile';
|
|
|
35
35
|
import { ConfigUserSpaceProvider } from '../../contexts/config-user-space';
|
|
36
36
|
import DidSpace from './storage';
|
|
37
37
|
import Nft from './nft';
|
|
38
|
+
import { UserFollowersProvider } from '../../contexts/user-followers';
|
|
39
|
+
import Fallback from './fallback';
|
|
38
40
|
|
|
39
41
|
const nftsLink = joinURL(PROFILE_URL, '/nfts');
|
|
40
42
|
const settingsLink = joinURL(PROFILE_URL, '/settings');
|
|
41
43
|
const didSpacesLink = joinURL(PROFILE_URL, '/did-spaces');
|
|
44
|
+
const userFollowersLink = joinURL(PROFILE_URL, '/user-followers');
|
|
42
45
|
|
|
43
46
|
interface NavigationTabProps {
|
|
44
47
|
label: string;
|
|
@@ -217,7 +220,14 @@ export default function UserCenter({
|
|
|
217
220
|
value: nftsLink,
|
|
218
221
|
url: getLink(nftsLink, locale),
|
|
219
222
|
};
|
|
220
|
-
|
|
223
|
+
const userFollowersTab = {
|
|
224
|
+
label: t('userFollowers'),
|
|
225
|
+
protected: false,
|
|
226
|
+
isPrivate: false,
|
|
227
|
+
value: userFollowersLink,
|
|
228
|
+
url: getLink(userFollowersLink, locale),
|
|
229
|
+
};
|
|
230
|
+
let tabs: NavigationTabProps[] = [nftTab, userFollowersTab];
|
|
221
231
|
if (isMyself) {
|
|
222
232
|
tabs = [
|
|
223
233
|
nftTab,
|
|
@@ -235,6 +245,7 @@ export default function UserCenter({
|
|
|
235
245
|
value: didSpacesLink,
|
|
236
246
|
url: getLink(didSpacesLink, locale),
|
|
237
247
|
},
|
|
248
|
+
userFollowersTab,
|
|
238
249
|
];
|
|
239
250
|
}
|
|
240
251
|
return tabs;
|
|
@@ -254,6 +265,7 @@ export default function UserCenter({
|
|
|
254
265
|
url: x.link || x.url,
|
|
255
266
|
protected: privacyState?.data?.[value] ?? false,
|
|
256
267
|
isPrivate: x.isPrivate || x.private || (x?._rawLink?.includes('/customer') ?? false), // FIXME: HACK: 隐藏 /customer 菜单, 需要一个通用的解决方案,在嵌入的时候就决定是否是私有的
|
|
268
|
+
followersOnly: x.component === 'did-comments', // 是否开启仅粉丝可查看的功能,目前只对 discuss kit 开启
|
|
257
269
|
// icon: x.icon,
|
|
258
270
|
};
|
|
259
271
|
})
|
|
@@ -429,16 +441,10 @@ export default function UserCenter({
|
|
|
429
441
|
}
|
|
430
442
|
|
|
431
443
|
return (
|
|
432
|
-
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
433
444
|
<Box sx={{ flex: 1 }}>
|
|
434
|
-
{currentActiveTab
|
|
435
|
-
<Box>
|
|
436
|
-
|
|
437
|
-
</Box>
|
|
438
|
-
) : (
|
|
439
|
-
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
440
|
-
<>{children ? <Box {...contentProps}>{renderChildrenWithProps(children)}</Box> : <>{renderDefaultTab}</>}</>
|
|
441
|
-
)}
|
|
445
|
+
<Fallback currentActiveTab={currentActiveTab as UserCenterTab} isMyself={isMyself}>
|
|
446
|
+
{children ? <Box {...contentProps}>{renderChildrenWithProps(children)}</Box> : renderDefaultTab}
|
|
447
|
+
</Fallback>
|
|
442
448
|
</Box>
|
|
443
449
|
);
|
|
444
450
|
}, [privacyState, currentActiveTab, isMyself, children, contentProps, renderDefaultTab, locale]);
|
|
@@ -681,7 +687,9 @@ export default function UserCenter({
|
|
|
681
687
|
</Helmet>
|
|
682
688
|
<Header style={{ display: 'none' }} />
|
|
683
689
|
<Main>
|
|
684
|
-
{
|
|
690
|
+
<UserFollowersProvider isMySelf={isMyself} userDid={userState.data?.did ?? ''}>
|
|
691
|
+
{content}
|
|
692
|
+
</UserFollowersProvider>
|
|
685
693
|
{confirmHolder}
|
|
686
694
|
</Main>
|
|
687
695
|
</Box>
|
|
@@ -700,7 +708,9 @@ export default function UserCenter({
|
|
|
700
708
|
</Helmet>
|
|
701
709
|
<Header bordered {...headerProps} maxWidth="100%" />
|
|
702
710
|
<Main>
|
|
703
|
-
{
|
|
711
|
+
<UserFollowersProvider isMySelf={isMyself} userDid={userState.data?.did ?? ''}>
|
|
712
|
+
{content}
|
|
713
|
+
</UserFollowersProvider>
|
|
704
714
|
{confirmHolder}
|
|
705
715
|
</Main>
|
|
706
716
|
{hideFooter ? null : (
|