@arcblock/ux 2.13.18 → 2.13.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/UserCard/Content/minimal.js +1 -1
- package/lib/UserCard/components.js +16 -6
- package/lib/UserCard/index.js +7 -2
- package/lib/UserCard/types.d.ts +1 -1
- package/lib/UserCard/utils.d.ts +1 -0
- package/lib/UserCard/utils.js +87 -0
- package/package.json +6 -6
- package/src/UserCard/Content/minimal.tsx +1 -1
- package/src/UserCard/components.tsx +14 -7
- package/src/UserCard/index.tsx +2 -1
- package/src/UserCard/types.ts +1 -1
- package/src/UserCard/utils.ts +94 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
-
import
|
3
|
+
import Box from '@mui/material/Box';
|
4
|
+
import MaterialAvatar from '@mui/material/Avatar';
|
4
5
|
import Avatar from '../Avatar';
|
5
6
|
import { createNameOnlyAvatar } from './utils';
|
6
7
|
|
@@ -12,16 +13,25 @@ export const renderAvatar = (user, avatarSize = 48, avatarProps = undefined, onA
|
|
12
13
|
// 如果用户没有头像,则显示名称首字母头像
|
13
14
|
if (!user.avatar) {
|
14
15
|
const avatarContent = createNameOnlyAvatar(user);
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
// 从 avatarProps 中提取 MUI 的 Avatar 支持的基本 props
|
17
|
+
// className, style 等基本 React 属性
|
18
|
+
const {
|
19
|
+
className,
|
20
|
+
style,
|
21
|
+
alt
|
22
|
+
} = avatarProps || {};
|
23
|
+
return /*#__PURE__*/_jsx(MaterialAvatar, {
|
19
24
|
onClick: onClick,
|
25
|
+
className: className,
|
26
|
+
style: style,
|
27
|
+
alt: alt,
|
20
28
|
sx: {
|
29
|
+
width: avatarSize,
|
30
|
+
height: avatarSize,
|
21
31
|
fontSize: avatarSize * 0.4,
|
22
32
|
cursor: shouldShowHoverCard || onAvatarClick ? 'pointer' : 'default'
|
23
33
|
},
|
24
|
-
|
34
|
+
variant: "circular",
|
25
35
|
children: avatarContent
|
26
36
|
});
|
27
37
|
}
|
package/lib/UserCard/index.js
CHANGED
@@ -46,7 +46,11 @@ function UserCard(props) {
|
|
46
46
|
} else if (props.did && isUserDid(props.did) && !props.user) {
|
47
47
|
getUserByDid(props.did).then(_user => {
|
48
48
|
if (isSubscribed) {
|
49
|
-
setUser(_user
|
49
|
+
setUser(_user || {
|
50
|
+
fullName: 'Anonymous',
|
51
|
+
did: props.did,
|
52
|
+
avatar: ''
|
53
|
+
});
|
50
54
|
}
|
51
55
|
});
|
52
56
|
}
|
@@ -76,7 +80,8 @@ function UserCard(props) {
|
|
76
80
|
avatarProps: props.popupAvatarProps,
|
77
81
|
shortenLabelProps: props.popupShortenLabelProps,
|
78
82
|
renderFields: props.popupRenderFields,
|
79
|
-
renderName: props.popupRenderName
|
83
|
+
renderName: props.popupRenderName,
|
84
|
+
infoType: props.popupInfoType || props.infoType
|
80
85
|
})
|
81
86
|
});
|
82
87
|
};
|
package/lib/UserCard/types.d.ts
CHANGED
@@ -7,7 +7,6 @@ type UserPublicInfo = {
|
|
7
7
|
avatar: string;
|
8
8
|
did: string;
|
9
9
|
fullName: string;
|
10
|
-
sourceAppPid: string | null;
|
11
10
|
};
|
12
11
|
export type UserMetadataLink = {
|
13
12
|
url: string;
|
@@ -95,6 +94,7 @@ export interface UserCardProps {
|
|
95
94
|
did?: string;
|
96
95
|
cardType?: CardType;
|
97
96
|
infoType?: InfoType;
|
97
|
+
popupInfoType?: InfoType;
|
98
98
|
avatarSize?: number;
|
99
99
|
showHoverCard?: boolean;
|
100
100
|
showDid?: boolean;
|
package/lib/UserCard/utils.d.ts
CHANGED
@@ -2,3 +2,4 @@ import { User } from './types';
|
|
2
2
|
export declare function createNameOnlyAvatar(user: User): string | null;
|
3
3
|
export declare function isUserDid(did: string): boolean;
|
4
4
|
export declare function getUserByDid(did: string): Promise<User | null>;
|
5
|
+
export declare function clearUserCache(did?: string): void;
|
package/lib/UserCard/utils.js
CHANGED
@@ -9,6 +9,53 @@ try {
|
|
9
9
|
client = null;
|
10
10
|
}
|
11
11
|
|
12
|
+
// 用户信息缓存键前缀
|
13
|
+
const USER_CACHE_PREFIX = 'ux_user_';
|
14
|
+
// 用户缓存的有效期(毫秒),默认60分钟
|
15
|
+
const USER_CACHE_EXPIRATION = 60 * 60 * 1000;
|
16
|
+
|
17
|
+
// 从sessionStorage获取用户信息
|
18
|
+
const getUserFromStorage = did => {
|
19
|
+
if (typeof sessionStorage === 'undefined') return null;
|
20
|
+
try {
|
21
|
+
const cacheKey = `${USER_CACHE_PREFIX}${did}`;
|
22
|
+
const cachedData = sessionStorage.getItem(cacheKey);
|
23
|
+
if (!cachedData) return null;
|
24
|
+
const parsedData = JSON.parse(cachedData);
|
25
|
+
const timestamp = parsedData.timestamp || 0;
|
26
|
+
const now = Date.now();
|
27
|
+
|
28
|
+
// 检查缓存是否过期
|
29
|
+
if (now - timestamp > USER_CACHE_EXPIRATION) {
|
30
|
+
// 缓存已过期,删除并返回null
|
31
|
+
sessionStorage.removeItem(cacheKey);
|
32
|
+
return null;
|
33
|
+
}
|
34
|
+
|
35
|
+
// 返回用户数据
|
36
|
+
return parsedData.user;
|
37
|
+
} catch (error) {
|
38
|
+
console.error(`Failed to load user cache for did ${did}:`, error);
|
39
|
+
return null;
|
40
|
+
}
|
41
|
+
};
|
42
|
+
|
43
|
+
// 将用户信息保存到sessionStorage
|
44
|
+
const saveUserToStorage = (did, user) => {
|
45
|
+
if (typeof sessionStorage === 'undefined') return;
|
46
|
+
try {
|
47
|
+
const cacheKey = `${USER_CACHE_PREFIX}${did}`;
|
48
|
+
// 创建包含用户数据和时间戳的缓存对象
|
49
|
+
const cacheData = {
|
50
|
+
user,
|
51
|
+
timestamp: Date.now()
|
52
|
+
};
|
53
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(cacheData));
|
54
|
+
} catch (error) {
|
55
|
+
console.error(`Failed to save user cache for did ${did}:`, error);
|
56
|
+
}
|
57
|
+
};
|
58
|
+
|
12
59
|
// 创建仅显示名称首字母的头像
|
13
60
|
// eslint-disable-next-line import/prefer-default-export
|
14
61
|
export function createNameOnlyAvatar(user) {
|
@@ -39,14 +86,54 @@ export function isUserDid(did) {
|
|
39
86
|
}
|
40
87
|
}
|
41
88
|
export async function getUserByDid(did) {
|
89
|
+
if (!did) return null;
|
90
|
+
|
91
|
+
// 先检查sessionStorage中是否有缓存
|
92
|
+
const storedUser = getUserFromStorage(did);
|
93
|
+
if (storedUser) {
|
94
|
+
return storedUser;
|
95
|
+
}
|
42
96
|
if (!client) return null;
|
43
97
|
try {
|
44
98
|
const user = await client.user.getUserPublicInfo({
|
45
99
|
did
|
46
100
|
});
|
101
|
+
// 将获取到的用户信息存入缓存
|
102
|
+
if (user) {
|
103
|
+
const userData = user;
|
104
|
+
saveUserToStorage(did, userData);
|
105
|
+
}
|
47
106
|
return user;
|
48
107
|
} catch (error) {
|
49
108
|
console.error('Failed to get user by did:', error);
|
50
109
|
return null;
|
51
110
|
}
|
111
|
+
}
|
112
|
+
|
113
|
+
// 清除缓存中特定用户的信息
|
114
|
+
export function clearUserCache(did) {
|
115
|
+
if (typeof sessionStorage === 'undefined') return;
|
116
|
+
if (did) {
|
117
|
+
// 清除指定用户缓存
|
118
|
+
try {
|
119
|
+
sessionStorage.removeItem(`${USER_CACHE_PREFIX}${did}`);
|
120
|
+
} catch (error) {
|
121
|
+
console.error(`Failed to remove cache for did ${did}:`, error);
|
122
|
+
}
|
123
|
+
} else {
|
124
|
+
// 清除所有用户缓存
|
125
|
+
try {
|
126
|
+
// 只清除以USER_CACHE_PREFIX开头的项
|
127
|
+
const keysToRemove = [];
|
128
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
129
|
+
const key = sessionStorage.key(i);
|
130
|
+
if (key && key.startsWith(USER_CACHE_PREFIX)) {
|
131
|
+
keysToRemove.push(key);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
135
|
+
} catch (error) {
|
136
|
+
console.error('Failed to clear all user caches:', error);
|
137
|
+
}
|
138
|
+
}
|
52
139
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "2.13.
|
3
|
+
"version": "2.13.19",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -71,14 +71,14 @@
|
|
71
71
|
"react": ">=18.2.0",
|
72
72
|
"react-router-dom": ">=6.22.3"
|
73
73
|
},
|
74
|
-
"gitHead": "
|
74
|
+
"gitHead": "64c12fb7646d2323f1be0bef7a3901261687b165",
|
75
75
|
"dependencies": {
|
76
76
|
"@arcblock/did-motif": "^1.1.13",
|
77
|
-
"@arcblock/icons": "^2.13.
|
78
|
-
"@arcblock/nft-display": "^2.13.
|
79
|
-
"@arcblock/react-hooks": "^2.13.
|
77
|
+
"@arcblock/icons": "^2.13.19",
|
78
|
+
"@arcblock/nft-display": "^2.13.19",
|
79
|
+
"@arcblock/react-hooks": "^2.13.19",
|
80
80
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
81
|
-
"@blocklet/theme": "^2.13.
|
81
|
+
"@blocklet/theme": "^2.13.19",
|
82
82
|
"@fontsource/roboto": "~5.1.1",
|
83
83
|
"@fontsource/ubuntu-mono": "^5.0.18",
|
84
84
|
"@iconify-icons/logos": "^1.2.36",
|
@@ -33,7 +33,7 @@ function MinimalContent(props: MinimalContentProps) {
|
|
33
33
|
|
34
34
|
return (
|
35
35
|
<Box display="flex" justifyContent="space-between" alignItems="center" className="user-card__avatar-content">
|
36
|
-
<Box display="flex" justifyContent="flex-start" alignItems="center" gap={
|
36
|
+
<Box display="flex" justifyContent="flex-start" alignItems="center" gap={1} flex={1} minWidth={0}>
|
37
37
|
<TooltipAvatar
|
38
38
|
user={user}
|
39
39
|
avatarSize={avatarSize}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import
|
2
|
+
import Box from '@mui/material/Box';
|
3
|
+
import MaterialAvatar from '@mui/material/Avatar';
|
3
4
|
import Avatar from '../Avatar';
|
4
5
|
import { User, UserCardProps } from './types';
|
5
6
|
import { createNameOnlyAvatar } from './utils';
|
@@ -18,19 +19,25 @@ export const renderAvatar = (
|
|
18
19
|
// 如果用户没有头像,则显示名称首字母头像
|
19
20
|
if (!user.avatar) {
|
20
21
|
const avatarContent = createNameOnlyAvatar(user);
|
22
|
+
// 从 avatarProps 中提取 MUI 的 Avatar 支持的基本 props
|
23
|
+
// className, style 等基本 React 属性
|
24
|
+
const { className, style, alt } = avatarProps || {};
|
25
|
+
|
21
26
|
return (
|
22
|
-
<
|
23
|
-
size={avatarSize}
|
24
|
-
did={user.did}
|
25
|
-
variant="circle"
|
27
|
+
<MaterialAvatar
|
26
28
|
onClick={onClick}
|
29
|
+
className={className}
|
30
|
+
style={style}
|
31
|
+
alt={alt}
|
27
32
|
sx={{
|
33
|
+
width: avatarSize,
|
34
|
+
height: avatarSize,
|
28
35
|
fontSize: avatarSize * 0.4,
|
29
36
|
cursor: shouldShowHoverCard || onAvatarClick ? 'pointer' : 'default',
|
30
37
|
}}
|
31
|
-
|
38
|
+
variant="circular">
|
32
39
|
{avatarContent}
|
33
|
-
</
|
40
|
+
</MaterialAvatar>
|
34
41
|
);
|
35
42
|
}
|
36
43
|
|
package/src/UserCard/index.tsx
CHANGED
@@ -47,7 +47,7 @@ function UserCard(props: UserCardProps) {
|
|
47
47
|
} else if (props.did && isUserDid(props.did) && !props.user) {
|
48
48
|
getUserByDid(props.did).then((_user) => {
|
49
49
|
if (isSubscribed) {
|
50
|
-
setUser(_user);
|
50
|
+
setUser(_user || { fullName: 'Anonymous', did: props.did as string, avatar: '' });
|
51
51
|
}
|
52
52
|
});
|
53
53
|
}
|
@@ -74,6 +74,7 @@ function UserCard(props: UserCardProps) {
|
|
74
74
|
shortenLabelProps={props.popupShortenLabelProps}
|
75
75
|
renderFields={props.popupRenderFields}
|
76
76
|
renderName={props.popupRenderName}
|
77
|
+
infoType={props.popupInfoType || props.infoType}
|
77
78
|
/>
|
78
79
|
</DialogContainer>
|
79
80
|
);
|
package/src/UserCard/types.ts
CHANGED
@@ -8,7 +8,6 @@ type UserPublicInfo = {
|
|
8
8
|
avatar: string;
|
9
9
|
did: string;
|
10
10
|
fullName: string;
|
11
|
-
sourceAppPid: string | null;
|
12
11
|
};
|
13
12
|
export type UserMetadataLink = {
|
14
13
|
url: string;
|
@@ -112,6 +111,7 @@ export interface UserCardProps {
|
|
112
111
|
did?: string;
|
113
112
|
cardType?: CardType;
|
114
113
|
infoType?: InfoType;
|
114
|
+
popupInfoType?: InfoType;
|
115
115
|
avatarSize?: number;
|
116
116
|
showHoverCard?: boolean;
|
117
117
|
showDid?: boolean;
|
package/src/UserCard/utils.ts
CHANGED
@@ -11,6 +11,57 @@ try {
|
|
11
11
|
client = null;
|
12
12
|
}
|
13
13
|
|
14
|
+
// 用户信息缓存键前缀
|
15
|
+
const USER_CACHE_PREFIX = 'ux_user_';
|
16
|
+
// 用户缓存的有效期(毫秒),默认60分钟
|
17
|
+
const USER_CACHE_EXPIRATION = 60 * 60 * 1000;
|
18
|
+
|
19
|
+
// 从sessionStorage获取用户信息
|
20
|
+
const getUserFromStorage = (did: string): User | null => {
|
21
|
+
if (typeof sessionStorage === 'undefined') return null;
|
22
|
+
|
23
|
+
try {
|
24
|
+
const cacheKey = `${USER_CACHE_PREFIX}${did}`;
|
25
|
+
const cachedData = sessionStorage.getItem(cacheKey);
|
26
|
+
|
27
|
+
if (!cachedData) return null;
|
28
|
+
|
29
|
+
const parsedData = JSON.parse(cachedData);
|
30
|
+
const timestamp = parsedData.timestamp || 0;
|
31
|
+
const now = Date.now();
|
32
|
+
|
33
|
+
// 检查缓存是否过期
|
34
|
+
if (now - timestamp > USER_CACHE_EXPIRATION) {
|
35
|
+
// 缓存已过期,删除并返回null
|
36
|
+
sessionStorage.removeItem(cacheKey);
|
37
|
+
return null;
|
38
|
+
}
|
39
|
+
|
40
|
+
// 返回用户数据
|
41
|
+
return parsedData.user;
|
42
|
+
} catch (error) {
|
43
|
+
console.error(`Failed to load user cache for did ${did}:`, error);
|
44
|
+
return null;
|
45
|
+
}
|
46
|
+
};
|
47
|
+
|
48
|
+
// 将用户信息保存到sessionStorage
|
49
|
+
const saveUserToStorage = (did: string, user: User): void => {
|
50
|
+
if (typeof sessionStorage === 'undefined') return;
|
51
|
+
|
52
|
+
try {
|
53
|
+
const cacheKey = `${USER_CACHE_PREFIX}${did}`;
|
54
|
+
// 创建包含用户数据和时间戳的缓存对象
|
55
|
+
const cacheData = {
|
56
|
+
user,
|
57
|
+
timestamp: Date.now(),
|
58
|
+
};
|
59
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(cacheData));
|
60
|
+
} catch (error) {
|
61
|
+
console.error(`Failed to save user cache for did ${did}:`, error);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
14
65
|
// 创建仅显示名称首字母的头像
|
15
66
|
// eslint-disable-next-line import/prefer-default-export
|
16
67
|
export function createNameOnlyAvatar(user: User) {
|
@@ -44,12 +95,55 @@ export function isUserDid(did: string) {
|
|
44
95
|
}
|
45
96
|
|
46
97
|
export async function getUserByDid(did: string): Promise<User | null> {
|
98
|
+
if (!did) return null;
|
99
|
+
|
100
|
+
// 先检查sessionStorage中是否有缓存
|
101
|
+
const storedUser = getUserFromStorage(did);
|
102
|
+
if (storedUser) {
|
103
|
+
return storedUser;
|
104
|
+
}
|
105
|
+
|
47
106
|
if (!client) return null;
|
107
|
+
|
48
108
|
try {
|
49
109
|
const user = await client.user.getUserPublicInfo({ did });
|
110
|
+
// 将获取到的用户信息存入缓存
|
111
|
+
if (user) {
|
112
|
+
const userData = user as User;
|
113
|
+
saveUserToStorage(did, userData);
|
114
|
+
}
|
50
115
|
return user as User;
|
51
116
|
} catch (error) {
|
52
117
|
console.error('Failed to get user by did:', error);
|
53
118
|
return null;
|
54
119
|
}
|
55
120
|
}
|
121
|
+
|
122
|
+
// 清除缓存中特定用户的信息
|
123
|
+
export function clearUserCache(did?: string): void {
|
124
|
+
if (typeof sessionStorage === 'undefined') return;
|
125
|
+
|
126
|
+
if (did) {
|
127
|
+
// 清除指定用户缓存
|
128
|
+
try {
|
129
|
+
sessionStorage.removeItem(`${USER_CACHE_PREFIX}${did}`);
|
130
|
+
} catch (error) {
|
131
|
+
console.error(`Failed to remove cache for did ${did}:`, error);
|
132
|
+
}
|
133
|
+
} else {
|
134
|
+
// 清除所有用户缓存
|
135
|
+
try {
|
136
|
+
// 只清除以USER_CACHE_PREFIX开头的项
|
137
|
+
const keysToRemove: string[] = [];
|
138
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
139
|
+
const key = sessionStorage.key(i);
|
140
|
+
if (key && key.startsWith(USER_CACHE_PREFIX)) {
|
141
|
+
keysToRemove.push(key);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
keysToRemove.forEach((key) => sessionStorage.removeItem(key));
|
145
|
+
} catch (error) {
|
146
|
+
console.error('Failed to clear all user caches:', error);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|