@arcblock/ux 3.0.33 → 3.0.34
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/Avatar/index.d.ts +3 -0
- package/lib/Avatar/index.js +26 -24
- package/lib/DIDConnect/auth-apps/auth-apps-info.js +20 -47
- package/lib/Img/index.d.ts +9 -1
- package/lib/Img/index.js +83 -72
- package/lib/UserCard/components.js +15 -14
- package/lib/UserCard/index.js +41 -31
- package/package.json +7 -7
- package/src/Avatar/index.jsx +3 -0
- package/src/DIDConnect/auth-apps/auth-apps-info.tsx +2 -37
- package/src/Img/index.jsx +47 -9
- package/src/UserCard/components.tsx +1 -0
- package/src/UserCard/index.tsx +23 -6
package/lib/Avatar/index.d.ts
CHANGED
@@ -21,6 +21,7 @@ export type AvatarProps = {
|
|
21
21
|
shape?: "" | "rectangle" | "square" | "hexagon" | "circle";
|
22
22
|
blockiesPadding?: true | false;
|
23
23
|
responsive?: false | true;
|
24
|
+
useProxyFallback?: boolean;
|
24
25
|
} & Omit<import('../Img').ImgProps, "size" | "src">;
|
25
26
|
export { Avatar as AvatarProps };
|
26
27
|
/**
|
@@ -34,6 +35,7 @@ export { Avatar as AvatarProps };
|
|
34
35
|
* shape?: '' | 'rectangle' | 'square' | 'hexagon' | 'circle';
|
35
36
|
* blockiesPadding?: true | false;
|
36
37
|
* responsive?: false | true;
|
38
|
+
* useProxyFallback?: boolean;
|
37
39
|
* } & Omit<import('../Img').ImgProps, 'size' | 'src'>} AvatarProps
|
38
40
|
*/
|
39
41
|
/**
|
@@ -51,6 +53,7 @@ declare namespace Avatar {
|
|
51
53
|
let shape: PropTypes.Requireable<string>;
|
52
54
|
let blockiesPadding: PropTypes.Requireable<boolean>;
|
53
55
|
let responsive: PropTypes.Requireable<boolean>;
|
56
|
+
let useProxyFallback: PropTypes.Requireable<boolean>;
|
54
57
|
}
|
55
58
|
export { propTypes_1 as propTypes };
|
56
59
|
}
|
package/lib/Avatar/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { jsx as o } from "react/jsx-runtime";
|
2
|
-
import { useState as
|
3
|
-
import
|
2
|
+
import { useState as I, useMemo as P } from "react";
|
3
|
+
import a from "prop-types";
|
4
4
|
import { ErrorBoundary as z } from "react-error-boundary";
|
5
5
|
import { Shape as D } from "@arcblock/did-motif";
|
6
6
|
import { Box as u } from "@mui/material";
|
@@ -13,12 +13,12 @@ import { DID_PREFIX as f } from "../Util/constant.js";
|
|
13
13
|
function d({ ...s }) {
|
14
14
|
const r = Object.assign({}, s);
|
15
15
|
n(r.did) && (r.did = ""), n(r.size) && (r.size = 36), n(r.variant) && (r.variant = "default"), n(r.animation) && (r.animation = !1), n(r.shape) && (r.shape = ""), n(r.blockiesPadding) && (r.blockiesPadding = !0), n(r.responsive) && (r.responsive = !1);
|
16
|
-
const [
|
16
|
+
const [l, h] = I(!1), g = E(r, d, []), { did: i = "", size: e, src: p, variant: b, animation: v, shape: x, blockiesPadding: y, responsive: k, ...t } = g, c = P(() => R(i) ? T.createIcon({
|
17
17
|
seed: i.replace(f, "").toLowerCase(),
|
18
18
|
size: 8,
|
19
19
|
scale: 16
|
20
20
|
}).toDataURL() : null, [i]);
|
21
|
-
if (p && !
|
21
|
+
if (p && !l)
|
22
22
|
return /* @__PURE__ */ o(
|
23
23
|
m,
|
24
24
|
{
|
@@ -26,8 +26,9 @@ function d({ ...s }) {
|
|
26
26
|
src: p,
|
27
27
|
alt: i,
|
28
28
|
onError: () => h(!0),
|
29
|
-
...
|
30
|
-
className: `avatar-img--${b} ${
|
29
|
+
...t,
|
30
|
+
className: `avatar-img--${b} ${t?.className || ""}`,
|
31
|
+
useProxyFallback: !0,
|
31
32
|
sx: {
|
32
33
|
"& .avatar-img--rounded": {
|
33
34
|
borderRadius: "4px",
|
@@ -37,17 +38,17 @@ function d({ ...s }) {
|
|
37
38
|
borderRadius: "100%",
|
38
39
|
overflow: "hidden"
|
39
40
|
},
|
40
|
-
...
|
41
|
+
...t.sx
|
41
42
|
}
|
42
43
|
}
|
43
44
|
);
|
44
|
-
if (
|
45
|
+
if (c) {
|
45
46
|
if (y) {
|
46
|
-
const
|
47
|
+
const w = e > 24 ? 4 : 2;
|
47
48
|
return /* @__PURE__ */ o(
|
48
49
|
u,
|
49
50
|
{
|
50
|
-
...
|
51
|
+
...t,
|
51
52
|
sx: {
|
52
53
|
display: "flex",
|
53
54
|
alignItems: "center",
|
@@ -63,13 +64,13 @@ function d({ ...s }) {
|
|
63
64
|
borderRadius: `${Math.min(10, Math.floor(0.1 * e + 2))}px`,
|
64
65
|
background: "#ddd"
|
65
66
|
},
|
66
|
-
...
|
67
|
+
...t.sx
|
67
68
|
},
|
68
|
-
children: /* @__PURE__ */ o("div", { className: "blocky-icon-inner", children: /* @__PURE__ */ o(m, { width: e * 0.7 -
|
69
|
+
children: /* @__PURE__ */ o("div", { className: "blocky-icon-inner", children: /* @__PURE__ */ o(m, { width: e * 0.7 - w * 2, src: c, alt: i }) })
|
69
70
|
}
|
70
71
|
);
|
71
72
|
}
|
72
|
-
return /* @__PURE__ */ o(m, { ...
|
73
|
+
return /* @__PURE__ */ o(m, { ...t, width: e, src: c, alt: i, style: { marginRight: 4 } });
|
73
74
|
}
|
74
75
|
if (i)
|
75
76
|
return /* @__PURE__ */ o(
|
@@ -79,25 +80,26 @@ function d({ ...s }) {
|
|
79
80
|
size: e,
|
80
81
|
animation: v,
|
81
82
|
shape: D[(x || "").toUpperCase()],
|
82
|
-
responsive:
|
83
|
-
...
|
83
|
+
responsive: k,
|
84
|
+
...t
|
84
85
|
}
|
85
86
|
);
|
86
87
|
throw new Error(`Invalid DID: ${i}`);
|
87
88
|
}
|
88
89
|
d.propTypes = {
|
89
|
-
did:
|
90
|
-
size:
|
91
|
-
variant:
|
90
|
+
did: a.string,
|
91
|
+
size: a.number,
|
92
|
+
variant: a.oneOf(["circle", "rounded", "default"]),
|
92
93
|
// animation 仅对 did motif 有效
|
93
|
-
animation:
|
94
|
+
animation: a.bool,
|
94
95
|
// shape 仅对 did motif 有效, 明确指定 motif shape, 而非由 did role type 自动推断 shape
|
95
|
-
shape:
|
96
|
-
blockiesPadding:
|
97
|
-
responsive:
|
96
|
+
shape: a.oneOf(["", "rectangle", "square", "hexagon", "circle"]),
|
97
|
+
blockiesPadding: a.bool,
|
98
|
+
responsive: a.bool,
|
99
|
+
useProxyFallback: a.bool
|
98
100
|
};
|
99
101
|
function $(s) {
|
100
|
-
const r = s.size || 36,
|
102
|
+
const r = s.size || 36, l = { rounded: "4px", circle: "100%" }[s.variant] || 0;
|
101
103
|
return /* @__PURE__ */ o(
|
102
104
|
z,
|
103
105
|
{
|
@@ -108,7 +110,7 @@ function $(s) {
|
|
108
110
|
width: r,
|
109
111
|
height: r,
|
110
112
|
bgcolor: "grey.300",
|
111
|
-
borderRadius:
|
113
|
+
borderRadius: l
|
112
114
|
}
|
113
115
|
}
|
114
116
|
),
|
@@ -1,21 +1,12 @@
|
|
1
|
-
import { jsxs as
|
2
|
-
import { Box as
|
1
|
+
import { jsxs as r, jsx as t } from "react/jsx-runtime";
|
2
|
+
import { Box as e, Typography as l } from "@mui/material";
|
3
3
|
import i from "../../Img/index.js";
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
try {
|
8
|
-
return new URL(e).protocol !== "https:" ? (console.warn("Image URL must use HTTPS protocol:", e), "") : `${s}/proxy?url=${e}`;
|
9
|
-
} catch (t) {
|
10
|
-
return console.warn("Invalid image URL format:", e, t), "";
|
11
|
-
}
|
12
|
-
};
|
13
|
-
function g({
|
14
|
-
requestAppInfo: e,
|
15
|
-
currentAppInfo: t
|
4
|
+
function m({
|
5
|
+
requestAppInfo: a,
|
6
|
+
currentAppInfo: o
|
16
7
|
}) {
|
17
|
-
return /* @__PURE__ */
|
18
|
-
|
8
|
+
return /* @__PURE__ */ r(
|
9
|
+
e,
|
19
10
|
{
|
20
11
|
sx: {
|
21
12
|
textAlign: "center",
|
@@ -25,8 +16,8 @@ function g({
|
|
25
16
|
gap: 2
|
26
17
|
},
|
27
18
|
children: [
|
28
|
-
/* @__PURE__ */
|
29
|
-
|
19
|
+
/* @__PURE__ */ r(
|
20
|
+
e,
|
30
21
|
{
|
31
22
|
sx: {
|
32
23
|
display: "flex",
|
@@ -34,18 +25,9 @@ function g({
|
|
34
25
|
justifyContent: "center"
|
35
26
|
},
|
36
27
|
children: [
|
37
|
-
/* @__PURE__ */ o
|
38
|
-
|
39
|
-
|
40
|
-
src: t.appLogo,
|
41
|
-
alt: "Server",
|
42
|
-
width: 48,
|
43
|
-
height: 48,
|
44
|
-
fallback: l(t.appLogo)
|
45
|
-
}
|
46
|
-
),
|
47
|
-
/* @__PURE__ */ a(
|
48
|
-
r,
|
28
|
+
/* @__PURE__ */ t(i, { src: o.appLogo, alt: "Server", width: 48, height: 48, useProxyFallback: !0 }),
|
29
|
+
/* @__PURE__ */ r(
|
30
|
+
e,
|
49
31
|
{
|
50
32
|
sx: {
|
51
33
|
mx: 2,
|
@@ -60,27 +42,18 @@ function g({
|
|
60
42
|
}
|
61
43
|
},
|
62
44
|
children: [
|
63
|
-
/* @__PURE__ */
|
64
|
-
/* @__PURE__ */
|
65
|
-
/* @__PURE__ */
|
45
|
+
/* @__PURE__ */ t(e, { className: "dot" }),
|
46
|
+
/* @__PURE__ */ t(e, { className: "dot" }),
|
47
|
+
/* @__PURE__ */ t(e, { className: "dot" })
|
66
48
|
]
|
67
49
|
}
|
68
50
|
),
|
69
|
-
/* @__PURE__ */
|
70
|
-
i,
|
71
|
-
{
|
72
|
-
src: e.appLogo,
|
73
|
-
alt: e.appName,
|
74
|
-
width: 48,
|
75
|
-
height: 48,
|
76
|
-
fallback: l(e.appLogo)
|
77
|
-
}
|
78
|
-
)
|
51
|
+
/* @__PURE__ */ t(i, { src: a.appLogo, alt: a.appName, width: 48, height: 48, useProxyFallback: !0 })
|
79
52
|
]
|
80
53
|
}
|
81
54
|
),
|
82
|
-
/* @__PURE__ */
|
83
|
-
|
55
|
+
/* @__PURE__ */ r(
|
56
|
+
l,
|
84
57
|
{
|
85
58
|
sx: {
|
86
59
|
mb: 1,
|
@@ -89,7 +62,7 @@ function g({
|
|
89
62
|
children: [
|
90
63
|
"Authorize",
|
91
64
|
" ",
|
92
|
-
/* @__PURE__ */
|
65
|
+
/* @__PURE__ */ t(e, { component: "span", sx: { color: "primary.main" }, children: a.appName })
|
93
66
|
]
|
94
67
|
}
|
95
68
|
)
|
@@ -98,5 +71,5 @@ function g({
|
|
98
71
|
);
|
99
72
|
}
|
100
73
|
export {
|
101
|
-
|
74
|
+
m as default
|
102
75
|
};
|
package/lib/Img/index.d.ts
CHANGED
@@ -19,6 +19,13 @@ export type ImgExProps = {
|
|
19
19
|
lazy?: boolean | undefined;
|
20
20
|
placeholder?: string | undefined;
|
21
21
|
fallback?: string | undefined;
|
22
|
+
/**
|
23
|
+
* - 是否使用代理 fallback, 用于解决 CSP 的问题
|
24
|
+
*/
|
25
|
+
/**
|
26
|
+
* - 是否使用代理 fallback, 用于解决 CSP 的问题
|
27
|
+
*/
|
28
|
+
useProxyFallback?: boolean | undefined;
|
22
29
|
className?: string | undefined;
|
23
30
|
onError?: Function | undefined;
|
24
31
|
onSuccess?: Function | undefined;
|
@@ -29,7 +36,7 @@ export type ImgProps = ImgExProps & import('@mui/material').BoxProps;
|
|
29
36
|
* @param {ImgProps} props
|
30
37
|
* @returns {React.ReactComponentElement}
|
31
38
|
*/
|
32
|
-
declare function Img({ lazy, width, height, repeat, ratio, alt, size, position, src, placeholder, fallback, style, className, onError, onSuccess, ...rest }: ImgProps): import('react').ReactComponentElement<any, Pick<any, string | number | symbol>>;
|
39
|
+
declare function Img({ lazy, width, height, repeat, ratio, alt, size, position, src, useProxyFallback, placeholder, fallback, style, className, onError, onSuccess, ...rest }: ImgProps): import('react').ReactComponentElement<any, Pick<any, string | number | symbol>>;
|
33
40
|
declare namespace Img {
|
34
41
|
namespace propTypes {
|
35
42
|
let src: PropTypes.Validator<string>;
|
@@ -47,5 +54,6 @@ declare namespace Img {
|
|
47
54
|
let className: PropTypes.Requireable<string>;
|
48
55
|
let onError: PropTypes.Requireable<(...args: any[]) => any>;
|
49
56
|
let onSuccess: PropTypes.Requireable<(...args: any[]) => any>;
|
57
|
+
let useProxyFallback: PropTypes.Requireable<boolean>;
|
50
58
|
}
|
51
59
|
}
|
package/lib/Img/index.js
CHANGED
@@ -1,91 +1,101 @@
|
|
1
|
-
import { jsx as
|
2
|
-
import { useState as
|
1
|
+
import { jsx as s, jsxs as F } from "react/jsx-runtime";
|
2
|
+
import { useState as R, useMemo as d, useEffect as w } from "react";
|
3
3
|
import e from "prop-types";
|
4
|
-
import { useInView as
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import { Icon as
|
8
|
-
import { Box as
|
9
|
-
import
|
10
|
-
import { mergeSx as
|
11
|
-
|
12
|
-
|
4
|
+
import { useInView as V } from "react-intersection-observer";
|
5
|
+
import W from "@iconify-icons/material-symbols/warning-rounded";
|
6
|
+
import X from "@iconify-icons/material-symbols/image-rounded";
|
7
|
+
import { Icon as k } from "@iconify/react";
|
8
|
+
import { Box as B } from "@mui/material";
|
9
|
+
import $ from "lodash/noop";
|
10
|
+
import { mergeSx as q } from "../Util/style.js";
|
11
|
+
import { BLOCKLET_SERVICE_PATH_PREFIX as A } from "../Util/constant.js";
|
12
|
+
const D = (r) => {
|
13
|
+
if (!r) return "";
|
14
|
+
try {
|
15
|
+
return new URL(r).protocol !== "https:" ? (console.warn("Image URL must use HTTPS protocol:", r), "") : `${A}/proxy?url=${encodeURIComponent(r)}`;
|
16
|
+
} catch (t) {
|
17
|
+
return console.warn("Invalid image URL format:", r, t), "";
|
18
|
+
}
|
19
|
+
}, K = "Img", v = {
|
20
|
+
root: `${K}-root`
|
13
21
|
};
|
14
|
-
function
|
15
|
-
lazy:
|
16
|
-
width:
|
17
|
-
height:
|
18
|
-
repeat:
|
19
|
-
ratio:
|
20
|
-
alt:
|
21
|
-
size:
|
22
|
-
position:
|
23
|
-
src:
|
24
|
-
|
25
|
-
fallback
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
function M({
|
23
|
+
lazy: r = !0,
|
24
|
+
width: t = null,
|
25
|
+
height: f = null,
|
26
|
+
repeat: E = "no-repeat",
|
27
|
+
ratio: N = 1,
|
28
|
+
alt: P = null,
|
29
|
+
size: p = "cover",
|
30
|
+
position: I = "top center",
|
31
|
+
src: n,
|
32
|
+
useProxyFallback: b = !1,
|
33
|
+
// 是否使用代理 fallback, 用于解决 CSP 的问题
|
34
|
+
placeholder: c = null,
|
35
|
+
fallback: m = null,
|
36
|
+
style: T = null,
|
37
|
+
className: j = "",
|
38
|
+
onError: h = $,
|
39
|
+
onSuccess: L = $,
|
40
|
+
...y
|
31
41
|
}) {
|
32
|
-
const [
|
42
|
+
const [U, x] = r ? V({ threshold: 0, triggerOnce: !0 }) : [null, !0], [o, g] = R("init"), [l, S] = R(!1), a = d(() => m || (b && n ? D(n) : m), [n, b, m]), u = d(() => {
|
33
43
|
switch (o) {
|
34
44
|
case "init":
|
35
45
|
case "loading":
|
36
|
-
return
|
46
|
+
return c;
|
37
47
|
case "error":
|
38
|
-
return
|
48
|
+
return l ? null : a;
|
39
49
|
case "loaded":
|
40
|
-
return
|
50
|
+
return n;
|
41
51
|
default:
|
42
52
|
return null;
|
43
53
|
}
|
44
|
-
}, [
|
54
|
+
}, [c, a, n, o, l]), _ = t && f ? 100 * f / t : N * 100, C = d(
|
45
55
|
() => ({
|
46
|
-
backgroundImage:
|
47
|
-
backgroundPosition:
|
48
|
-
backgroundSize:
|
49
|
-
backgroundRepeat:
|
50
|
-
paddingTop: `${
|
56
|
+
backgroundImage: u ? `url(${u})` : "",
|
57
|
+
backgroundPosition: I,
|
58
|
+
backgroundSize: p,
|
59
|
+
backgroundRepeat: E,
|
60
|
+
paddingTop: `${_}%`
|
51
61
|
}),
|
52
62
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
53
|
-
[
|
54
|
-
),
|
55
|
-
...
|
63
|
+
[u, I, p, o]
|
64
|
+
), H = {
|
65
|
+
...T,
|
56
66
|
display: "inline-block",
|
57
|
-
width:
|
67
|
+
width: t ? `${t}px` : "100%"
|
58
68
|
};
|
59
|
-
function
|
60
|
-
const
|
61
|
-
|
62
|
-
|
63
|
-
},
|
64
|
-
|
69
|
+
function O() {
|
70
|
+
const i = new Image();
|
71
|
+
i.src = n, g("loading"), S(!1), i.onload = () => {
|
72
|
+
g("loaded"), L();
|
73
|
+
}, i.onerror = () => {
|
74
|
+
g("error");
|
65
75
|
};
|
66
76
|
}
|
67
|
-
return
|
68
|
-
|
69
|
-
}, [
|
70
|
-
if (o === "error" &&
|
71
|
-
const
|
72
|
-
|
73
|
-
},
|
74
|
-
|
77
|
+
return w(() => {
|
78
|
+
x && O();
|
79
|
+
}, [x]), w(() => {
|
80
|
+
if (o === "error" && a && !l) {
|
81
|
+
const i = new Image();
|
82
|
+
i.src = a, i.onload = () => {
|
83
|
+
}, i.onerror = (z) => {
|
84
|
+
S(!0), o === "error" && h(z);
|
75
85
|
};
|
76
86
|
}
|
77
|
-
}, [o,
|
78
|
-
/* @__PURE__ */
|
79
|
-
|
87
|
+
}, [o, a, l, h]), // paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
88
|
+
/* @__PURE__ */ s(
|
89
|
+
B,
|
80
90
|
{
|
81
91
|
"data-id": "2",
|
82
|
-
ref:
|
83
|
-
style:
|
92
|
+
ref: U,
|
93
|
+
style: H,
|
84
94
|
className: "arcblock_ux_img-wrapper",
|
85
|
-
...
|
86
|
-
sx:
|
95
|
+
...y,
|
96
|
+
sx: q(
|
87
97
|
{
|
88
|
-
[`& .${
|
98
|
+
[`& .${v.root}`]: {
|
89
99
|
position: "relative",
|
90
100
|
overflow: "hidden",
|
91
101
|
"& .image--state, & .image--img": {
|
@@ -117,17 +127,17 @@ function O({
|
|
117
127
|
}
|
118
128
|
}
|
119
129
|
},
|
120
|
-
|
130
|
+
y.sx
|
121
131
|
),
|
122
|
-
children: /* @__PURE__ */
|
123
|
-
(
|
124
|
-
!
|
125
|
-
o === "loaded" && /* @__PURE__ */
|
132
|
+
children: /* @__PURE__ */ F("div", { className: `image ${j} ${v.root}`, style: C, children: [
|
133
|
+
(l || !a && o === "error") && /* @__PURE__ */ s("div", { className: "image--state", title: "Image load error", children: /* @__PURE__ */ s(k, { icon: W, className: "image--icon" }) }),
|
134
|
+
!c && o === "loading" && /* @__PURE__ */ s("div", { className: "image--state", title: "loading image", children: /* @__PURE__ */ s(k, { icon: X, className: "image--icon" }) }),
|
135
|
+
o === "loaded" && /* @__PURE__ */ s("img", { className: "image--img", src: n, alt: P })
|
126
136
|
] })
|
127
137
|
}
|
128
138
|
);
|
129
139
|
}
|
130
|
-
|
140
|
+
M.propTypes = {
|
131
141
|
src: e.string.isRequired,
|
132
142
|
alt: e.string,
|
133
143
|
size: e.string,
|
@@ -142,8 +152,9 @@ O.propTypes = {
|
|
142
152
|
fallback: e.string,
|
143
153
|
className: e.string,
|
144
154
|
onError: e.func,
|
145
|
-
onSuccess: e.func
|
155
|
+
onSuccess: e.func,
|
156
|
+
useProxyFallback: e.bool
|
146
157
|
};
|
147
158
|
export {
|
148
|
-
|
159
|
+
M as default
|
149
160
|
};
|
@@ -1,17 +1,17 @@
|
|
1
1
|
import { jsx as a } from "react/jsx-runtime";
|
2
|
-
import { Box as
|
3
|
-
import
|
4
|
-
import { createNameOnlyAvatar as
|
5
|
-
const N = (r, t = 48,
|
6
|
-
const
|
2
|
+
import { Box as o, Avatar as f } from "@mui/material";
|
3
|
+
import u from "../Avatar/index.js";
|
4
|
+
import { createNameOnlyAvatar as x } from "./utils.js";
|
5
|
+
const N = (r, t = 48, c = void 0, e = void 0, l = !1) => {
|
6
|
+
const n = (i) => {
|
7
7
|
e?.(r, i);
|
8
8
|
};
|
9
9
|
if (!r.avatar) {
|
10
|
-
const i =
|
10
|
+
const i = x(r), { className: s, style: d, alt: m } = c || {};
|
11
11
|
return /* @__PURE__ */ a(
|
12
12
|
f,
|
13
13
|
{
|
14
|
-
onClick:
|
14
|
+
onClick: n,
|
15
15
|
className: s,
|
16
16
|
style: d,
|
17
17
|
alt: m,
|
@@ -19,7 +19,7 @@ const N = (r, t = 48, n = void 0, e = void 0, c = !1) => {
|
|
19
19
|
width: t,
|
20
20
|
height: t,
|
21
21
|
fontSize: t * 0.4,
|
22
|
-
cursor:
|
22
|
+
cursor: l || e ? "pointer" : "default"
|
23
23
|
},
|
24
24
|
variant: "circular",
|
25
25
|
children: i
|
@@ -27,30 +27,31 @@ const N = (r, t = 48, n = void 0, e = void 0, c = !1) => {
|
|
27
27
|
);
|
28
28
|
}
|
29
29
|
return /* @__PURE__ */ a(
|
30
|
-
|
30
|
+
o,
|
31
31
|
{
|
32
32
|
className: "user-card__avatar",
|
33
33
|
sx: {
|
34
34
|
display: "flex"
|
35
35
|
},
|
36
36
|
children: /* @__PURE__ */ a(
|
37
|
-
|
37
|
+
u,
|
38
38
|
{
|
39
39
|
size: t,
|
40
40
|
did: r.did,
|
41
41
|
variant: "circle",
|
42
|
+
useProxyFallback: !0,
|
42
43
|
style: {
|
43
|
-
cursor:
|
44
|
+
cursor: l || e ? "pointer" : "default"
|
44
45
|
},
|
45
|
-
onClick:
|
46
|
+
onClick: n,
|
46
47
|
src: r.avatar,
|
47
48
|
alt: r.fullName || "",
|
48
|
-
...
|
49
|
+
...c || {}
|
49
50
|
}
|
50
51
|
)
|
51
52
|
}
|
52
53
|
);
|
53
|
-
}, _ = (r, t = 120) => r ? /* @__PURE__ */ a(
|
54
|
+
}, _ = (r, t = 120) => r ? /* @__PURE__ */ a(o, { sx: { maxWidth: t }, className: "user-card__top-right-content", children: r() }) : null;
|
54
55
|
export {
|
55
56
|
N as renderAvatar,
|
56
57
|
_ as renderTopRight
|
package/lib/UserCard/index.js
CHANGED
@@ -1,34 +1,44 @@
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
2
|
-
import { useRef as
|
3
|
-
import { CardType as
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import
|
8
|
-
import
|
9
|
-
import { isUserDid as
|
2
|
+
import { useRef as v, useState as C, useEffect as y, useMemo as P } from "react";
|
3
|
+
import { CardType as o } from "./types.js";
|
4
|
+
import A from "./Cards/avatar-only.js";
|
5
|
+
import m from "./Cards/index.js";
|
6
|
+
import D from "./Container/dialog.js";
|
7
|
+
import S from "./Container/card.js";
|
8
|
+
import w from "../Avatar/index.js";
|
9
|
+
import { isUserDid as x, getUserByDid as U } from "./utils.js";
|
10
10
|
function L(e) {
|
11
11
|
if (!e) return null;
|
12
12
|
let r = "";
|
13
13
|
return e.fullName ? r = e.fullName.charAt(0).toUpperCase() : e.email ? r = e.email.split("@")[0].charAt(0).toUpperCase() : r = e.did ? e.did.charAt(0).toUpperCase() : "?", r;
|
14
14
|
}
|
15
|
-
function
|
16
|
-
const { cardType: r =
|
17
|
-
|
18
|
-
let
|
19
|
-
return e.user ?
|
20
|
-
|
15
|
+
function B(e) {
|
16
|
+
const { cardType: r = o.Detailed, showHoverCard: l } = e, u = l !== void 0 ? l : r === o.AvatarOnly, c = v(null), [i, f] = C(() => e.user || null);
|
17
|
+
y(() => {
|
18
|
+
let a = !0;
|
19
|
+
return e.user ? f(e.user) : e.did && x(e.did) && !e.user && U(e.did).then((d) => {
|
20
|
+
a && f(d || { fullName: "Anonymous", did: e.did, avatar: "" });
|
21
21
|
}), () => {
|
22
|
-
|
22
|
+
a = !1;
|
23
23
|
};
|
24
|
-
}, [e.did, e.user])
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
}, [e.did, e.user]);
|
25
|
+
const n = P(() => {
|
26
|
+
if (!i)
|
27
|
+
return null;
|
28
|
+
const { avatar: a = "", ...d } = i, h = a.split("?")[1];
|
29
|
+
return a && !h ? {
|
30
|
+
...d,
|
31
|
+
avatar: `${a}?imageFilter=resize&w=48&h=48`
|
32
|
+
} : i;
|
33
|
+
}, [i]);
|
34
|
+
if (!n)
|
35
|
+
return /* @__PURE__ */ t(w, { did: e.did, size: e.avatarSize, useProxyFallback: !0, ...e.avatarProps });
|
36
|
+
const s = () => /* @__PURE__ */ t(D, { sx: e.popupSx, children: /* @__PURE__ */ t(
|
37
|
+
m,
|
28
38
|
{
|
29
39
|
...e,
|
30
40
|
shouldShowHoverCard: !1,
|
31
|
-
user:
|
41
|
+
user: n,
|
32
42
|
avatarProps: e.popupAvatarProps,
|
33
43
|
shortenLabelProps: e.popupShortenLabelProps || e.shortenLabelProps,
|
34
44
|
renderFields: e.popupRenderFields,
|
@@ -38,25 +48,25 @@ function g(e) {
|
|
38
48
|
showDid: e.popupShowDid || e.showDid
|
39
49
|
}
|
40
50
|
) });
|
41
|
-
return r ===
|
42
|
-
|
51
|
+
return r === o.AvatarOnly ? /* @__PURE__ */ t(
|
52
|
+
A,
|
43
53
|
{
|
44
54
|
...e,
|
45
|
-
shouldShowHoverCard:
|
46
|
-
renderCardContent:
|
47
|
-
user:
|
55
|
+
shouldShowHoverCard: u,
|
56
|
+
renderCardContent: s,
|
57
|
+
user: n
|
48
58
|
}
|
49
|
-
) : /* @__PURE__ */ t(
|
50
|
-
|
59
|
+
) : /* @__PURE__ */ t(S, { containerRef: c, cardType: r, sx: e.sx, children: /* @__PURE__ */ t(
|
60
|
+
m,
|
51
61
|
{
|
52
62
|
...e,
|
53
|
-
shouldShowHoverCard:
|
54
|
-
renderCardContent:
|
55
|
-
user:
|
63
|
+
shouldShowHoverCard: u,
|
64
|
+
renderCardContent: s,
|
65
|
+
user: n
|
56
66
|
}
|
57
67
|
) });
|
58
68
|
}
|
59
69
|
export {
|
60
70
|
L as createNameOnlyAvatar,
|
61
|
-
|
71
|
+
B as default
|
62
72
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.34",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -60,16 +60,16 @@
|
|
60
60
|
"react": "^19.0.0",
|
61
61
|
"react-router-dom": "^6.22.3"
|
62
62
|
},
|
63
|
-
"gitHead": "
|
63
|
+
"gitHead": "e2822eb021fb9aebfcf80f71dd4da4ca76b2372b",
|
64
64
|
"dependencies": {
|
65
|
-
"@arcblock/bridge": "3.0.
|
65
|
+
"@arcblock/bridge": "3.0.34",
|
66
66
|
"@arcblock/did": "^1.21.0",
|
67
67
|
"@arcblock/did-motif": "^1.1.14",
|
68
|
-
"@arcblock/icons": "3.0.
|
69
|
-
"@arcblock/nft-display": "3.0.
|
70
|
-
"@arcblock/react-hooks": "3.0.
|
68
|
+
"@arcblock/icons": "3.0.34",
|
69
|
+
"@arcblock/nft-display": "3.0.34",
|
70
|
+
"@arcblock/react-hooks": "3.0.34",
|
71
71
|
"@blocklet/js-sdk": "^1.16.46",
|
72
|
-
"@blocklet/theme": "3.0.
|
72
|
+
"@blocklet/theme": "3.0.34",
|
73
73
|
"@fontsource/roboto": "~5.1.1",
|
74
74
|
"@fontsource/ubuntu-mono": "^5.2.6",
|
75
75
|
"@iconify-icons/logos": "^1.2.36",
|
package/src/Avatar/index.jsx
CHANGED
@@ -23,6 +23,7 @@ import { DID_PREFIX } from '../Util/constant';
|
|
23
23
|
* shape?: '' | 'rectangle' | 'square' | 'hexagon' | 'circle';
|
24
24
|
* blockiesPadding?: true | false;
|
25
25
|
* responsive?: false | true;
|
26
|
+
* useProxyFallback?: boolean;
|
26
27
|
* } & Omit<import('../Img').ImgProps, 'size' | 'src'>} AvatarProps
|
27
28
|
*/
|
28
29
|
|
@@ -84,6 +85,7 @@ function Avatar({ ...rawProps }) {
|
|
84
85
|
{...rest}
|
85
86
|
// HACK: 这个 className 是传递给子元素的,所以下面的 sx 需要通过子元素选择器来写样式
|
86
87
|
className={`avatar-img--${variant} ${rest?.className || ''}`}
|
88
|
+
useProxyFallback
|
87
89
|
sx={{
|
88
90
|
'& .avatar-img--rounded': {
|
89
91
|
borderRadius: '4px',
|
@@ -159,6 +161,7 @@ Avatar.propTypes = {
|
|
159
161
|
shape: PropTypes.oneOf(['', 'rectangle', 'square', 'hexagon', 'circle']),
|
160
162
|
blockiesPadding: PropTypes.bool,
|
161
163
|
responsive: PropTypes.bool,
|
164
|
+
useProxyFallback: PropTypes.bool,
|
162
165
|
};
|
163
166
|
|
164
167
|
/**
|
@@ -1,28 +1,5 @@
|
|
1
1
|
import { Box, Typography } from '@mui/material';
|
2
2
|
import Img from '../../Img';
|
3
|
-
import { BLOCKLET_SERVICE_PATH_PREFIX } from '../../Util/constant';
|
4
|
-
|
5
|
-
const getProxyImageUrl = (url: string) => {
|
6
|
-
if (!url) return '';
|
7
|
-
|
8
|
-
try {
|
9
|
-
// 检查是否是一个有效的URL
|
10
|
-
const urlObj = new URL(url);
|
11
|
-
|
12
|
-
// 检查协议是否是https
|
13
|
-
if (urlObj.protocol !== 'https:') {
|
14
|
-
console.warn('Image URL must use HTTPS protocol:', url);
|
15
|
-
return '';
|
16
|
-
}
|
17
|
-
|
18
|
-
// 返回代理URL
|
19
|
-
return `${BLOCKLET_SERVICE_PATH_PREFIX}/proxy?url=${url}`;
|
20
|
-
} catch (error) {
|
21
|
-
// URL construction failed, indicating invalid URL format
|
22
|
-
console.warn('Invalid image URL format:', url, error);
|
23
|
-
return '';
|
24
|
-
}
|
25
|
-
};
|
26
3
|
|
27
4
|
export type RequestAppInfo = {
|
28
5
|
appLogo: string;
|
@@ -59,13 +36,7 @@ export default function AuthAppsInfo({
|
|
59
36
|
justifyContent: 'center',
|
60
37
|
}}>
|
61
38
|
{/* FIXME: @zhanghan 增加 hover 的效果 */}
|
62
|
-
<Img
|
63
|
-
src={currentAppInfo.appLogo}
|
64
|
-
alt="Server"
|
65
|
-
width={48}
|
66
|
-
height={48}
|
67
|
-
fallback={getProxyImageUrl(currentAppInfo.appLogo)}
|
68
|
-
/>
|
39
|
+
<Img src={currentAppInfo.appLogo} alt="Server" width={48} height={48} useProxyFallback />
|
69
40
|
|
70
41
|
<Box
|
71
42
|
sx={{
|
@@ -86,13 +57,7 @@ export default function AuthAppsInfo({
|
|
86
57
|
</Box>
|
87
58
|
|
88
59
|
{/* FIXME: @zhanghan 增加 hover 的效果 */}
|
89
|
-
<Img
|
90
|
-
src={requestAppInfo.appLogo}
|
91
|
-
alt={requestAppInfo.appName}
|
92
|
-
width={48}
|
93
|
-
height={48}
|
94
|
-
fallback={getProxyImageUrl(requestAppInfo.appLogo)}
|
95
|
-
/>
|
60
|
+
<Img src={requestAppInfo.appLogo} alt={requestAppInfo.appName} width={48} height={48} useProxyFallback />
|
96
61
|
</Box>
|
97
62
|
|
98
63
|
<Typography
|
package/src/Img/index.jsx
CHANGED
@@ -7,6 +7,29 @@ import { Icon } from '@iconify/react';
|
|
7
7
|
import { Box } from '@mui/material';
|
8
8
|
import noop from 'lodash/noop';
|
9
9
|
import { mergeSx } from '../Util/style';
|
10
|
+
import { BLOCKLET_SERVICE_PATH_PREFIX } from '../Util/constant';
|
11
|
+
|
12
|
+
const getProxyImageUrl = (url) => {
|
13
|
+
if (!url) return '';
|
14
|
+
|
15
|
+
try {
|
16
|
+
// 检查是否是一个有效的URL
|
17
|
+
const urlObj = new URL(url);
|
18
|
+
|
19
|
+
// 检查协议是否是https
|
20
|
+
if (urlObj.protocol !== 'https:') {
|
21
|
+
console.warn('Image URL must use HTTPS protocol:', url);
|
22
|
+
return '';
|
23
|
+
}
|
24
|
+
|
25
|
+
// 返回代理URL
|
26
|
+
return `${BLOCKLET_SERVICE_PATH_PREFIX}/proxy?url=${encodeURIComponent(url)}`;
|
27
|
+
} catch (error) {
|
28
|
+
// URL construction failed, indicating invalid URL format
|
29
|
+
console.warn('Invalid image URL format:', url, error);
|
30
|
+
return '';
|
31
|
+
}
|
32
|
+
};
|
10
33
|
|
11
34
|
/**
|
12
35
|
* @typedef {Object} ImgExProps
|
@@ -22,6 +45,7 @@ import { mergeSx } from '../Util/style';
|
|
22
45
|
* @property {boolean} [lazy=true]
|
23
46
|
* @property {string} [placeholder]
|
24
47
|
* @property {string} [fallback]
|
48
|
+
* @property {boolean} [useProxyFallback=false] - 是否使用代理 fallback, 用于解决 CSP 的问题
|
25
49
|
* @property {string} [className='']
|
26
50
|
* @property {function} [onError=() => {}]
|
27
51
|
* @property {function} [onSuccess=() => {}]
|
@@ -52,6 +76,7 @@ function Img({
|
|
52
76
|
size = 'cover',
|
53
77
|
position = 'top center',
|
54
78
|
src,
|
79
|
+
useProxyFallback = false, // 是否使用代理 fallback, 用于解决 CSP 的问题
|
55
80
|
placeholder = null,
|
56
81
|
fallback = null,
|
57
82
|
style = null,
|
@@ -66,19 +91,29 @@ function Img({
|
|
66
91
|
const [imgState, setImgState] = useState('init');
|
67
92
|
const [fallbackError, setFallbackError] = useState(false);
|
68
93
|
|
94
|
+
const fallbackSrc = useMemo(() => {
|
95
|
+
if (fallback) {
|
96
|
+
return fallback;
|
97
|
+
}
|
98
|
+
if (useProxyFallback && src) {
|
99
|
+
return getProxyImageUrl(src);
|
100
|
+
}
|
101
|
+
return fallback;
|
102
|
+
}, [src, useProxyFallback, fallback]);
|
103
|
+
|
69
104
|
const actualSrc = useMemo(() => {
|
70
105
|
switch (imgState) {
|
71
106
|
case 'init':
|
72
107
|
case 'loading':
|
73
108
|
return placeholder;
|
74
109
|
case 'error':
|
75
|
-
return fallbackError ? null :
|
110
|
+
return fallbackError ? null : fallbackSrc;
|
76
111
|
case 'loaded':
|
77
112
|
return src;
|
78
113
|
default:
|
79
114
|
return null;
|
80
115
|
}
|
81
|
-
}, [placeholder,
|
116
|
+
}, [placeholder, fallbackSrc, src, imgState, fallbackError]);
|
82
117
|
|
83
118
|
const actualRatio = width && height ? (100 * height) / width : ratio * 100;
|
84
119
|
|
@@ -112,9 +147,8 @@ function Img({
|
|
112
147
|
setImgState('loaded');
|
113
148
|
onSuccess();
|
114
149
|
};
|
115
|
-
img.onerror = (
|
150
|
+
img.onerror = () => {
|
116
151
|
setImgState('error');
|
117
|
-
onError(err);
|
118
152
|
};
|
119
153
|
}
|
120
154
|
|
@@ -125,18 +159,21 @@ function Img({
|
|
125
159
|
|
126
160
|
// 处理 fallback 加载
|
127
161
|
useEffect(() => {
|
128
|
-
if (imgState === 'error' &&
|
162
|
+
if (imgState === 'error' && fallbackSrc && !fallbackError) {
|
129
163
|
const fallbackImg = new Image();
|
130
|
-
fallbackImg.src =
|
164
|
+
fallbackImg.src = fallbackSrc;
|
131
165
|
fallbackImg.onload = () => {
|
132
166
|
// fallback 加载成功,保持在 error 状态但显示 fallback
|
133
167
|
};
|
134
|
-
fallbackImg.onerror = () => {
|
168
|
+
fallbackImg.onerror = (err) => {
|
135
169
|
// fallback 也加载失败
|
136
170
|
setFallbackError(true);
|
171
|
+
if (imgState === 'error') {
|
172
|
+
onError(err);
|
173
|
+
}
|
137
174
|
};
|
138
175
|
}
|
139
|
-
}, [imgState,
|
176
|
+
}, [imgState, fallbackSrc, fallbackError, onError]);
|
140
177
|
|
141
178
|
return (
|
142
179
|
// paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
@@ -183,7 +220,7 @@ function Img({
|
|
183
220
|
rest.sx
|
184
221
|
)}>
|
185
222
|
<div className={`image ${className} ${classes.root}`} style={mergedStyle}>
|
186
|
-
{(fallbackError || (!
|
223
|
+
{(fallbackError || (!fallbackSrc && imgState === 'error')) && (
|
187
224
|
<div className="image--state" title="Image load error">
|
188
225
|
<Icon icon={WarningRoundedIcon} className="image--icon" />
|
189
226
|
</div>
|
@@ -215,6 +252,7 @@ Img.propTypes = {
|
|
215
252
|
className: PropTypes.string,
|
216
253
|
onError: PropTypes.func,
|
217
254
|
onSuccess: PropTypes.func,
|
255
|
+
useProxyFallback: PropTypes.bool,
|
218
256
|
};
|
219
257
|
|
220
258
|
export default Img;
|
package/src/UserCard/index.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
2
2
|
import type { User } from './types';
|
3
3
|
import { UserCardProps, CardType } from './types';
|
4
4
|
import AvatarOnlyCard from './Cards/avatar-only';
|
@@ -55,9 +55,26 @@ function UserCard(props: UserCardProps) {
|
|
55
55
|
};
|
56
56
|
}, [props.did, props.user]);
|
57
57
|
|
58
|
+
// 补全 avatar 的 imageFilter 信息,以提高性能
|
59
|
+
const userInfo = useMemo(() => {
|
60
|
+
if (!user) {
|
61
|
+
return null;
|
62
|
+
}
|
63
|
+
|
64
|
+
const { avatar = '', ...rest } = user;
|
65
|
+
const avatarParam = avatar.split('?')[1];
|
66
|
+
if (avatar && !avatarParam) {
|
67
|
+
return {
|
68
|
+
...rest,
|
69
|
+
avatar: `${avatar}?imageFilter=resize&w=48&h=48`,
|
70
|
+
};
|
71
|
+
}
|
72
|
+
return user;
|
73
|
+
}, [user]);
|
74
|
+
|
58
75
|
// 如果不存在,则使用 did 渲染头像
|
59
|
-
if (!
|
60
|
-
return <Avatar did={props.did} size={props.avatarSize} {...props.avatarProps} />;
|
76
|
+
if (!userInfo) {
|
77
|
+
return <Avatar did={props.did} size={props.avatarSize} useProxyFallback {...props.avatarProps} />;
|
61
78
|
}
|
62
79
|
|
63
80
|
// user 存在,则使用 user 渲染头像
|
@@ -68,7 +85,7 @@ function UserCard(props: UserCardProps) {
|
|
68
85
|
<DetailedCard
|
69
86
|
{...props}
|
70
87
|
shouldShowHoverCard={false}
|
71
|
-
user={
|
88
|
+
user={userInfo!}
|
72
89
|
avatarProps={props.popupAvatarProps}
|
73
90
|
shortenLabelProps={props.popupShortenLabelProps || props.shortenLabelProps}
|
74
91
|
renderFields={props.popupRenderFields}
|
@@ -88,7 +105,7 @@ function UserCard(props: UserCardProps) {
|
|
88
105
|
{...props}
|
89
106
|
shouldShowHoverCard={shouldShowHoverCard}
|
90
107
|
renderCardContent={renderCardContent}
|
91
|
-
user={
|
108
|
+
user={userInfo!}
|
92
109
|
/>
|
93
110
|
);
|
94
111
|
}
|
@@ -100,7 +117,7 @@ function UserCard(props: UserCardProps) {
|
|
100
117
|
{...props}
|
101
118
|
shouldShowHoverCard={shouldShowHoverCard}
|
102
119
|
renderCardContent={renderCardContent}
|
103
|
-
user={
|
120
|
+
user={userInfo!}
|
104
121
|
/>
|
105
122
|
</CardContainer>
|
106
123
|
);
|