@arcblock/ux 3.1.28 → 3.1.31
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/SessionUser/components/logged-in.js +41 -39
- package/lib/UserCard/Cards/avatar-only.js +11 -22
- package/lib/UserCard/Cards/index.js +4 -12
- package/lib/UserCard/Cards/social-actions.d.ts +7 -0
- package/lib/UserCard/Cards/social-actions.js +112 -0
- package/lib/UserCard/Content/minimal.js +62 -47
- package/lib/UserCard/index.d.ts +2 -0
- package/lib/UserCard/index.js +31 -28
- package/lib/UserCard/types.d.ts +8 -1
- package/lib/UserCard/types.js +4 -4
- package/lib/UserCard/use-follow.d.ts +16 -0
- package/lib/UserCard/use-follow.js +67 -0
- package/lib/Util/index.d.ts +15 -0
- package/lib/Util/index.js +191 -171
- package/lib/package.json.js +9 -0
- package/lib/withTracker/action/bind-wallet.d.ts +14 -0
- package/lib/withTracker/action/bind-wallet.js +1 -0
- package/lib/withTracker/action/login.d.ts +15 -0
- package/lib/withTracker/action/login.js +1 -0
- package/lib/withTracker/action/pay.d.ts +12 -0
- package/lib/withTracker/action/pay.js +1 -0
- package/lib/withTracker/action/switch-passport.d.ts +18 -0
- package/lib/withTracker/action/switch-passport.js +1 -0
- package/lib/withTracker/constant/index.d.ts +3 -0
- package/lib/withTracker/constant/index.js +6 -0
- package/lib/withTracker/env.d.ts +1 -0
- package/lib/withTracker/env.js +4 -0
- package/lib/withTracker/index.d.ts +2 -0
- package/lib/withTracker/index.js +21 -17
- package/package.json +10 -8
- package/src/SessionUser/components/logged-in.tsx +2 -0
- package/src/UserCard/Cards/avatar-only.tsx +1 -15
- package/src/UserCard/Cards/index.tsx +2 -11
- package/src/UserCard/Cards/social-actions.tsx +196 -0
- package/src/UserCard/Content/minimal.tsx +43 -31
- package/src/UserCard/UserCard.stories.jsx +1 -0
- package/src/UserCard/index.tsx +6 -0
- package/src/UserCard/types.ts +10 -1
- package/src/UserCard/use-follow.tsx +119 -0
- package/src/Util/index.ts +67 -0
- package/src/withTracker/action/bind-wallet.tsx +17 -0
- package/src/withTracker/action/login.tsx +18 -0
- package/src/withTracker/action/pay.tsx +14 -0
- package/src/withTracker/action/switch-passport.tsx +20 -0
- package/src/withTracker/constant/index.tsx +3 -0
- package/src/withTracker/env.tsx +1 -0
- package/src/withTracker/index.tsx +8 -11
- package/lib/UserCard/Cards/name-only.d.ts +0 -5
- package/lib/UserCard/Cards/name-only.js +0 -13
- package/src/UserCard/Cards/name-only.tsx +0 -17
@@ -0,0 +1,14 @@
|
|
1
|
+
import { LiteralUnion } from 'type-fest';
|
2
|
+
export interface BindWalletEvent {
|
3
|
+
action: 'bindWalletSuccess' | 'bindWalletFailed';
|
4
|
+
provider: LiteralUnion<'wallet' | 'apple' | 'github' | 'google' | 'email' | 'twitter' | 'passkey', string>;
|
5
|
+
}
|
6
|
+
export interface BindWalletSuccessEvent extends BindWalletEvent {
|
7
|
+
action: 'bindWalletSuccess';
|
8
|
+
success: true;
|
9
|
+
}
|
10
|
+
export interface BindWalletFailedEvent extends BindWalletEvent {
|
11
|
+
action: 'bindWalletFailed';
|
12
|
+
success: false;
|
13
|
+
errorMessage: string;
|
14
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { LiteralUnion } from 'type-fest';
|
2
|
+
export interface LoginEvent {
|
3
|
+
action: 'loginSuccess' | 'loginFailed';
|
4
|
+
provider: LiteralUnion<'wallet' | 'apple' | 'github' | 'google' | 'email' | 'twitter' | 'passkey', string>;
|
5
|
+
success: boolean;
|
6
|
+
}
|
7
|
+
export interface LoginSuccessEvent extends LoginEvent {
|
8
|
+
action: 'loginSuccess';
|
9
|
+
success: true;
|
10
|
+
}
|
11
|
+
export interface LoginFailedEvent extends LoginEvent {
|
12
|
+
action: 'loginFailed';
|
13
|
+
success: false;
|
14
|
+
errorMessage: string;
|
15
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
export interface PayEvent {
|
2
|
+
action: 'paySuccess' | 'payFailed';
|
3
|
+
checkoutSessionMode: string;
|
4
|
+
success: boolean;
|
5
|
+
}
|
6
|
+
export interface PaySuccessEvent extends PayEvent {
|
7
|
+
success: true;
|
8
|
+
}
|
9
|
+
export interface PayFailedEvent extends PayEvent {
|
10
|
+
success: false;
|
11
|
+
errorMessage: string;
|
12
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
export interface SwitchPassportEvent {
|
2
|
+
action: 'switchPassportSuccess' | 'switchPassportFailed';
|
3
|
+
success: boolean;
|
4
|
+
}
|
5
|
+
export interface SwitchPassportSuccessEvent extends SwitchPassportEvent {
|
6
|
+
success: true;
|
7
|
+
/**
|
8
|
+
*
|
9
|
+
* @example guest -> admin
|
10
|
+
* @type {string}
|
11
|
+
* @memberof SwitchPassportEvent
|
12
|
+
*/
|
13
|
+
change: string;
|
14
|
+
}
|
15
|
+
export interface SwitchPassportFailedEvent extends SwitchPassportEvent {
|
16
|
+
success: false;
|
17
|
+
errorMessage: string;
|
18
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const googleAnalyticsMeasurementId: string;
|
package/lib/withTracker/index.js
CHANGED
@@ -1,22 +1,26 @@
|
|
1
|
-
import { jsx as
|
2
|
-
import { useLocation as
|
3
|
-
import { useMount as
|
4
|
-
import
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
import { jsx as p } from "react/jsx-runtime";
|
2
|
+
import { useLocation as f } from "react-router-dom";
|
3
|
+
import { useMount as s, useDeepCompareEffect as u } from "ahooks";
|
4
|
+
import r from "react-ga4";
|
5
|
+
import { default as A } from "react-ga4";
|
6
|
+
import { googleAnalyticsMeasurementId as n } from "./env.js";
|
7
|
+
n && r.initialize(n);
|
8
|
+
const h = (i) => {
|
9
|
+
const a = (o, t = document.title) => {
|
10
|
+
n && r.send({ hitType: "pageview", page: o, title: t });
|
11
|
+
}, c = (o, t, e, m) => {
|
12
|
+
n && r.event({ category: o, action: t, label: e, value: m, transport: "beacon" });
|
10
13
|
};
|
11
|
-
return
|
12
|
-
const
|
13
|
-
return
|
14
|
-
|
15
|
-
}),
|
16
|
-
|
17
|
-
}, [
|
14
|
+
return window.trackPage = a, window.trackEvent = c, function(t) {
|
15
|
+
const e = f();
|
16
|
+
return s(() => {
|
17
|
+
a(e.pathname);
|
18
|
+
}), u(() => {
|
19
|
+
a(e.pathname);
|
20
|
+
}, [e.pathname]), /* @__PURE__ */ p(i, { ...t });
|
18
21
|
};
|
19
22
|
};
|
20
23
|
export {
|
21
|
-
|
24
|
+
A as ReactGA,
|
25
|
+
h as default
|
22
26
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.1.
|
3
|
+
"version": "3.1.31",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -45,6 +45,7 @@
|
|
45
45
|
"@types/pako": "^2.0.3",
|
46
46
|
"@types/react": "^19.1.8",
|
47
47
|
"@types/react-helmet": "^6.1.11",
|
48
|
+
"@types/semver": "^7.7.0",
|
48
49
|
"@types/webfontloader": "^1.6.38",
|
49
50
|
"babel-jest": "29",
|
50
51
|
"babel-plugin-inline-react-svg": "^2.0.2",
|
@@ -67,16 +68,16 @@
|
|
67
68
|
"react": "^19.0.0",
|
68
69
|
"react-router-dom": "^6.22.3"
|
69
70
|
},
|
70
|
-
"gitHead": "
|
71
|
+
"gitHead": "a904bcfb38156f7cdff5b2134c126b19d528f4b2",
|
71
72
|
"dependencies": {
|
72
|
-
"@arcblock/bridge": "3.1.
|
73
|
+
"@arcblock/bridge": "3.1.31",
|
73
74
|
"@arcblock/did": "^1.21.3",
|
74
75
|
"@arcblock/did-motif": "^1.1.14",
|
75
|
-
"@arcblock/icons": "3.1.
|
76
|
-
"@arcblock/nft-display": "3.1.
|
77
|
-
"@arcblock/react-hooks": "3.1.
|
78
|
-
"@blocklet/js-sdk": "^1.16.
|
79
|
-
"@blocklet/theme": "3.1.
|
76
|
+
"@arcblock/icons": "3.1.31",
|
77
|
+
"@arcblock/nft-display": "3.1.31",
|
78
|
+
"@arcblock/react-hooks": "3.1.31",
|
79
|
+
"@blocklet/js-sdk": "^1.16.49-beta-20250823-082650-626c1473",
|
80
|
+
"@blocklet/theme": "3.1.31",
|
80
81
|
"@fontsource/roboto": "~5.1.1",
|
81
82
|
"@fontsource/ubuntu-mono": "^5.2.6",
|
82
83
|
"@iconify-icons/logos": "^1.2.36",
|
@@ -123,6 +124,7 @@
|
|
123
124
|
"react-svg": "^16.3.0",
|
124
125
|
"react-use": "^17.6.0",
|
125
126
|
"rebound": "^0.1.0",
|
127
|
+
"semver": "^7.7.2",
|
126
128
|
"topojson-client": "^3.1.0",
|
127
129
|
"type-fest": "^4.41.0",
|
128
130
|
"validator": "^13.15.15",
|
@@ -33,6 +33,7 @@ import type { Locale, Session } from '../../type';
|
|
33
33
|
import DidSpace from './did-space';
|
34
34
|
import { mergeSx } from '../../Util/style';
|
35
35
|
import { createDebug } from '../../Util/logger';
|
36
|
+
import { GA_LAST_ROLE } from '../../withTracker/constant';
|
36
37
|
|
37
38
|
const getInviteLink = (inviter: string) => {
|
38
39
|
const url = new URL(window.location.href);
|
@@ -86,6 +87,7 @@ export default function LoggedIn({
|
|
86
87
|
const oauth = session.useOAuth();
|
87
88
|
const passkey = typeof session.usePasskey === 'function' ? session.usePasskey() : null;
|
88
89
|
const handleSwitchPassport = useMemoizedFn(({ inArcSphere = false } = {}) => {
|
90
|
+
localStorage.setItem(GA_LAST_ROLE, session?.user?.role);
|
89
91
|
const extraParams: Record<string, any> = {};
|
90
92
|
if (inArcSphere) {
|
91
93
|
if (session?.user?.sourceAppPid) {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps,
|
2
|
+
import { UserCardProps, User } from '../types';
|
3
3
|
import TooltipAvatar from '../Content/tooltip-avatar';
|
4
4
|
|
5
5
|
interface AvatarOnlyCardProps extends Omit<UserCardProps, 'user'> {
|
@@ -12,20 +12,6 @@ interface AvatarOnlyCardProps extends Omit<UserCardProps, 'user'> {
|
|
12
12
|
function AvatarOnlyCard(props: AvatarOnlyCardProps) {
|
13
13
|
const { user, infoType, avatarSize = 48, shouldShowHoverCard = false, renderCardContent, ...rest } = props;
|
14
14
|
|
15
|
-
// 对于NameOnly类型使用普通Tooltip
|
16
|
-
if (infoType === InfoType.NameOnly) {
|
17
|
-
return (
|
18
|
-
<TooltipAvatar
|
19
|
-
user={user}
|
20
|
-
avatarSize={avatarSize}
|
21
|
-
shouldShowHoverCard={false}
|
22
|
-
renderCardContent={renderCardContent}
|
23
|
-
tooltipTitle={user.fullName || user.email || user.did}
|
24
|
-
{...rest}
|
25
|
-
/>
|
26
|
-
);
|
27
|
-
}
|
28
|
-
|
29
15
|
// 其他类型使用自定义Tooltip或无Tooltip
|
30
16
|
return (
|
31
17
|
<TooltipAvatar
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps,
|
3
|
-
import NameOnlyCard from './name-only';
|
2
|
+
import { UserCardProps, User } from '../types';
|
4
3
|
import BasicCard from './basic-info';
|
5
4
|
|
6
5
|
interface DetailedCardProps extends Omit<UserCardProps, 'user'> {
|
@@ -11,15 +10,7 @@ interface DetailedCardProps extends Omit<UserCardProps, 'user'> {
|
|
11
10
|
|
12
11
|
// DetailedCard组件,根据infoType选择不同的卡片组件进行渲染
|
13
12
|
function DetailedCard({ ...props }: DetailedCardProps) {
|
14
|
-
|
15
|
-
|
16
|
-
// 根据信息类型选择合适的卡片组件
|
17
|
-
switch (infoType) {
|
18
|
-
case InfoType.NameOnly:
|
19
|
-
return <NameOnlyCard {...props} />;
|
20
|
-
default:
|
21
|
-
return <BasicCard {...props} />;
|
22
|
-
}
|
13
|
+
return <BasicCard {...props} />;
|
23
14
|
}
|
24
15
|
|
25
16
|
export default DetailedCard;
|
@@ -0,0 +1,196 @@
|
|
1
|
+
import { useMemo } from 'react';
|
2
|
+
import { Box, Button, styled } from '@mui/material';
|
3
|
+
import { useMemoizedFn } from 'ahooks';
|
4
|
+
import { joinURL } from 'ufo';
|
5
|
+
import noop from 'lodash/noop';
|
6
|
+
import { Icon } from '@iconify/react';
|
7
|
+
import NotificationsIcon from '@mui/icons-material/Notifications';
|
8
|
+
import NotificationsOffIcon from '@mui/icons-material/NotificationsOff';
|
9
|
+
|
10
|
+
import useFollow from '../use-follow';
|
11
|
+
import { User, UserCardProps } from '../types';
|
12
|
+
import { useLocaleContext } from '../../Locale/context';
|
13
|
+
import { translate } from '../../Locale/util';
|
14
|
+
import { isSupportFollow } from '../../Util';
|
15
|
+
|
16
|
+
type SocialActionsProps = Pick<UserCardProps, 'showSocialActions' | 'session'> & {
|
17
|
+
user: User; // 当前卡片显示的用户,要与 session.user 区分开
|
18
|
+
};
|
19
|
+
|
20
|
+
const translations = {
|
21
|
+
zh: {
|
22
|
+
chat: '聊天',
|
23
|
+
follow: '关注',
|
24
|
+
unfollow: '取消关注',
|
25
|
+
follow_success: '关注成功',
|
26
|
+
unfollow_success: '取消关注成功',
|
27
|
+
},
|
28
|
+
en: {
|
29
|
+
chat: 'Chat',
|
30
|
+
follow: 'Follow',
|
31
|
+
unfollow: 'Unfollow',
|
32
|
+
follow_success: 'Follow success',
|
33
|
+
unfollow_success: 'Unfollow success',
|
34
|
+
},
|
35
|
+
};
|
36
|
+
|
37
|
+
const getDiscussKitMountPoint = () => {
|
38
|
+
const { componentMountPoints = [] } = window.blocklet || {};
|
39
|
+
const component = componentMountPoints.find((c: any) => c.name === 'did-comments');
|
40
|
+
return component?.mountPoint;
|
41
|
+
};
|
42
|
+
|
43
|
+
// chat: 1. showSocialActions.chat 为 true,2. 必须安装了 discuss kit
|
44
|
+
function Chat({
|
45
|
+
user,
|
46
|
+
showSocialActions,
|
47
|
+
session,
|
48
|
+
}: {
|
49
|
+
user: SocialActionsProps['user'];
|
50
|
+
showSocialActions: SocialActionsProps['showSocialActions'];
|
51
|
+
session: SocialActionsProps['session'];
|
52
|
+
}) {
|
53
|
+
const { locale } = useLocaleContext() || { locale: 'en' };
|
54
|
+
const t = useMemoizedFn((key, data = {}) => {
|
55
|
+
return translate(translations, key, locale, 'en', data);
|
56
|
+
});
|
57
|
+
|
58
|
+
const isLogin = useMemo(() => {
|
59
|
+
return !!session?.user?.did;
|
60
|
+
}, [session?.user?.did]);
|
61
|
+
|
62
|
+
// 获取 discuss kit 的挂载点
|
63
|
+
const discussKitMountPoint = useMemo(() => getDiscussKitMountPoint(), []);
|
64
|
+
|
65
|
+
const onNavigateToChat = useMemoizedFn(() => {
|
66
|
+
if (!isLogin) {
|
67
|
+
session?.login(noop, {
|
68
|
+
openMode: 'redirect',
|
69
|
+
redirect: window.location.href,
|
70
|
+
}); // TODO: 需要确认使用是否正确
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
window.open(joinURL(discussKitMountPoint, `/chat/dm/${user?.did}`), '_blank');
|
74
|
+
});
|
75
|
+
|
76
|
+
const showChat = useMemo(() => {
|
77
|
+
// boolean:直接使用原值;对象:取对应属性值
|
78
|
+
const chatEnabled = typeof showSocialActions === 'boolean' ? !!showSocialActions : showSocialActions?.chat;
|
79
|
+
|
80
|
+
return chatEnabled && !!discussKitMountPoint;
|
81
|
+
}, [showSocialActions, discussKitMountPoint]);
|
82
|
+
|
83
|
+
if (!showChat) {
|
84
|
+
return null;
|
85
|
+
}
|
86
|
+
return (
|
87
|
+
<ButtonWrapper
|
88
|
+
className="user-card__social-actions-chat"
|
89
|
+
variant="outlined"
|
90
|
+
color="inherit"
|
91
|
+
onClick={onNavigateToChat}>
|
92
|
+
<Icon icon="tabler:message-dots" style={{ marginRight: 4 }} />
|
93
|
+
{t('chat')}
|
94
|
+
</ButtonWrapper>
|
95
|
+
);
|
96
|
+
}
|
97
|
+
|
98
|
+
// follow: 1. showSocialActions.follow 为 true
|
99
|
+
function Follow({
|
100
|
+
user,
|
101
|
+
showSocialActions,
|
102
|
+
session,
|
103
|
+
}: {
|
104
|
+
user: SocialActionsProps['user'];
|
105
|
+
showSocialActions: SocialActionsProps['showSocialActions'];
|
106
|
+
session: SocialActionsProps['session'];
|
107
|
+
}) {
|
108
|
+
const { locale } = useLocaleContext() || { locale: 'en' };
|
109
|
+
const t = useMemoizedFn((key, data = {}) => {
|
110
|
+
return translate(translations, key, locale, 'en', data);
|
111
|
+
});
|
112
|
+
|
113
|
+
const isLogin = useMemo(() => {
|
114
|
+
return !!session?.user?.did;
|
115
|
+
}, [session?.user?.did]);
|
116
|
+
|
117
|
+
const showFollow = useMemo(() => {
|
118
|
+
// boolean:直接使用原值;对象:取对应属性值
|
119
|
+
return typeof showSocialActions === 'boolean' ? !!showSocialActions : showSocialActions?.follow;
|
120
|
+
}, [showSocialActions]);
|
121
|
+
|
122
|
+
const { followed, followUser, unfollowUser } = useFollow({
|
123
|
+
user,
|
124
|
+
t,
|
125
|
+
isMySelf: false,
|
126
|
+
visible: !!showFollow,
|
127
|
+
});
|
128
|
+
const handleFollowAction = useMemoizedFn(() => {
|
129
|
+
if (!isLogin) {
|
130
|
+
session?.login(noop, {
|
131
|
+
openMode: 'redirect',
|
132
|
+
redirect: window.location.href,
|
133
|
+
});
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
if (followed) {
|
137
|
+
unfollowUser(user.did);
|
138
|
+
} else {
|
139
|
+
followUser(user.did);
|
140
|
+
}
|
141
|
+
});
|
142
|
+
|
143
|
+
if (!showFollow) {
|
144
|
+
return null;
|
145
|
+
}
|
146
|
+
|
147
|
+
return (
|
148
|
+
<ButtonWrapper
|
149
|
+
className="user-card__social-actions-follow"
|
150
|
+
variant="outlined"
|
151
|
+
color="inherit"
|
152
|
+
onClick={handleFollowAction}>
|
153
|
+
{followed ? (
|
154
|
+
<NotificationsOffIcon sx={{ fontSize: 14, mr: 0.5 }} />
|
155
|
+
) : (
|
156
|
+
<NotificationsIcon sx={{ fontSize: 14, mr: 0.5 }} />
|
157
|
+
)}
|
158
|
+
{followed ? t('unfollow') : t('follow')}
|
159
|
+
</ButtonWrapper>
|
160
|
+
);
|
161
|
+
}
|
162
|
+
|
163
|
+
// 社交操作组件
|
164
|
+
// 按钮的显示逻辑
|
165
|
+
// 通用逻辑: 1. user 和 session.user 不能是同一个用户, 2. 相关依赖支持,3. showSocialActions 为 true 或 为 object
|
166
|
+
// 其他逻辑: 1. 如果 session 中没有用户信息,点击后需要重定向到登录页面
|
167
|
+
function SocialActions({ showSocialActions, session, user }: SocialActionsProps) {
|
168
|
+
const isSameUser = useMemo(() => {
|
169
|
+
return session?.user?.did === user?.did;
|
170
|
+
}, [session?.user?.did, user?.did]);
|
171
|
+
|
172
|
+
const isSupportSocialActions = useMemo(() => {
|
173
|
+
return isSupportFollow();
|
174
|
+
}, []);
|
175
|
+
|
176
|
+
// 如果 session 中没有用户信息,或者 user 和 session.user 是同一个用户,则不显示社交操作
|
177
|
+
if (isSameUser || !isSupportSocialActions || !showSocialActions) {
|
178
|
+
return null;
|
179
|
+
}
|
180
|
+
|
181
|
+
return (
|
182
|
+
<Box className="user-card__social-actions" sx={{ display: 'flex', gap: 1 }}>
|
183
|
+
<Chat session={session} user={user} showSocialActions={showSocialActions} />
|
184
|
+
<Follow session={session} user={user} showSocialActions={showSocialActions} />
|
185
|
+
</Box>
|
186
|
+
);
|
187
|
+
}
|
188
|
+
|
189
|
+
export default SocialActions;
|
190
|
+
|
191
|
+
export const ButtonWrapper = styled(Button)`
|
192
|
+
color: ${({ theme }) => theme.palette.text.primary};
|
193
|
+
font-weight: 500;
|
194
|
+
border-color: ${({ theme }) => theme.palette.grey[300]};
|
195
|
+
line-height: 1.5;
|
196
|
+
`;
|
@@ -5,6 +5,7 @@ import { User, UserCardProps } from '../types';
|
|
5
5
|
import TooltipAvatar from './tooltip-avatar';
|
6
6
|
import { renderTopRight } from '../components';
|
7
7
|
import ShortenLabel from './shorten-label';
|
8
|
+
import SocialActions from '../Cards/social-actions';
|
8
9
|
|
9
10
|
interface MinimalContentProps extends UserCardProps {
|
10
11
|
user: User;
|
@@ -42,44 +43,55 @@ function MinimalContent({ ...props }: MinimalContentProps) {
|
|
42
43
|
<Box
|
43
44
|
sx={{
|
44
45
|
display: 'flex',
|
45
|
-
justifyContent: '
|
46
|
+
justifyContent: 'space-between',
|
46
47
|
alignItems: 'center',
|
47
48
|
gap: 1,
|
48
49
|
flex: 1,
|
49
50
|
minWidth: 0,
|
50
51
|
}}>
|
51
|
-
<
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
<
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
renderName(
|
72
|
-
|
73
|
-
|
74
|
-
{
|
75
|
-
|
76
|
-
|
77
|
-
|
52
|
+
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', gap: 1, flex: 1 }}>
|
53
|
+
<TooltipAvatar
|
54
|
+
user={user}
|
55
|
+
avatarSize={avatarSize}
|
56
|
+
shouldShowHoverCard={shouldShowHoverCard}
|
57
|
+
renderCardContent={renderCardContent}
|
58
|
+
avatarProps={avatarProps}
|
59
|
+
{...rest}
|
60
|
+
/>
|
61
|
+
<Box>
|
62
|
+
<Typography
|
63
|
+
variant="subtitle1"
|
64
|
+
className="user-card__full-name-label"
|
65
|
+
noWrap
|
66
|
+
sx={{
|
67
|
+
fontWeight: 500,
|
68
|
+
color: 'text.primary',
|
69
|
+
fontSize: 18,
|
70
|
+
lineHeight: 1.1,
|
71
|
+
}}>
|
72
|
+
{renderName ? (
|
73
|
+
renderName(user)
|
74
|
+
) : (
|
75
|
+
<ShortenLabel sx={{ fontWeight: 500 }} {...shortenLabelProps}>
|
76
|
+
{user.fullName || user.email || user.did}
|
77
|
+
</ShortenLabel>
|
78
|
+
)}
|
79
|
+
</Typography>
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
{showDid && user.did ? (
|
82
|
+
<DID
|
83
|
+
did={user.did}
|
84
|
+
size={14}
|
85
|
+
copyable
|
86
|
+
compact
|
87
|
+
locale="en"
|
88
|
+
sx={{ lineHeight: 1.5 }}
|
89
|
+
{...(didProps ?? {})}
|
90
|
+
/>
|
91
|
+
) : null}
|
92
|
+
</Box>
|
82
93
|
</Box>
|
94
|
+
<SocialActions showSocialActions={rest.showSocialActions} user={user!} session={rest.session} />
|
83
95
|
</Box>
|
84
96
|
{renderTopRight(renderTopRightContent, topRightMaxWidth)}
|
85
97
|
</Box>
|
@@ -5,6 +5,7 @@ export { default as DidControl } from './demo/didControl';
|
|
5
5
|
export { default as TopRightContent } from './demo/topRightContent';
|
6
6
|
export { default as CustomFooter } from './demo/customFooter';
|
7
7
|
export { default as DidOnlyAvatar } from './demo/did-only-avatar';
|
8
|
+
export { default as SocialActions } from './demo/socialActions';
|
8
9
|
|
9
10
|
export default {
|
10
11
|
title: 'Data Display/UserCard',
|
package/src/UserCard/index.tsx
CHANGED
@@ -6,6 +6,7 @@ import DetailedCard from './Cards';
|
|
6
6
|
import DialogContainer from './Container/dialog';
|
7
7
|
import CardContainer from './Container/card';
|
8
8
|
import Avatar from '../Avatar';
|
9
|
+
import SocialActions from './Cards/social-actions';
|
9
10
|
import { getUserByDid, isUserDid } from './utils';
|
10
11
|
|
11
12
|
// 创建仅显示名称首字母的头像
|
@@ -93,6 +94,9 @@ function UserCard(props: UserCardProps) {
|
|
93
94
|
infoType={props.popupInfoType || props.infoType}
|
94
95
|
didProps={props.popupDidProps || props.didProps}
|
95
96
|
showDid={props.popupShowDid || props.showDid}
|
97
|
+
showSocialActions={
|
98
|
+
props.popupShowSocialActions === undefined ? props.showSocialActions : props.popupShowSocialActions
|
99
|
+
}
|
96
100
|
/>
|
97
101
|
</DialogContainer>
|
98
102
|
);
|
@@ -124,3 +128,5 @@ function UserCard(props: UserCardProps) {
|
|
124
128
|
}
|
125
129
|
|
126
130
|
export default UserCard;
|
131
|
+
|
132
|
+
export { SocialActions };
|
package/src/UserCard/types.ts
CHANGED
@@ -3,6 +3,7 @@ import { SxProps, Theme, TooltipProps } from '@mui/material';
|
|
3
3
|
import { DIDProps } from '../DID';
|
4
4
|
import { AvatarProps } from '../Avatar';
|
5
5
|
import { ShortenLabelProps } from './Content/shorten-label';
|
6
|
+
import type { Session } from '../type';
|
6
7
|
|
7
8
|
type UserPublicInfo = {
|
8
9
|
avatar: string;
|
@@ -100,13 +101,17 @@ export enum CardType {
|
|
100
101
|
|
101
102
|
// 信息类型
|
102
103
|
export enum InfoType {
|
103
|
-
NameOnly = 'NameOnly', // 仅显示名称
|
104
104
|
Minimal = 'Minimal', // 极简模式,显示头像、名称和DID
|
105
105
|
Basic = 'Basic', // 基本信息模式
|
106
106
|
}
|
107
107
|
|
108
|
+
export type SocialActionProps = {
|
109
|
+
chat: boolean;
|
110
|
+
follow: boolean;
|
111
|
+
};
|
108
112
|
// 定义UserCard属性接口
|
109
113
|
export interface UserCardProps {
|
114
|
+
session?: Session;
|
110
115
|
user?: User;
|
111
116
|
did?: string;
|
112
117
|
cardType?: CardType;
|
@@ -146,6 +151,10 @@ export interface UserCardProps {
|
|
146
151
|
renderTopRightContent?: () => React.ReactNode;
|
147
152
|
topRightMaxWidth?: number;
|
148
153
|
|
154
|
+
// 社交按钮相关属性
|
155
|
+
showSocialActions?: SocialActionProps | boolean;
|
156
|
+
popupShowSocialActions?: SocialActionProps | boolean;
|
157
|
+
|
149
158
|
// 自定义内容渲染函数
|
150
159
|
renderCustomContent?: () => React.ReactNode;
|
151
160
|
|