@blocklet/ui-react
Version:
Some useful front-end web components that can be used in Blocklets.
445 lines (444 loc) • 14.4 kB
JavaScript
import { jsx as e, jsxs as f, Fragment as D } from "react/jsx-runtime";
import { use as fe } from "react";
import { Box as a, Typography as pe, CircularProgress as me, Divider as he } from "@mui/material";
import { useMemoizedFn as y, useCreation as d, useRequest as Y } from "ahooks";
import xe from "p-wait-for";
import { SessionContext as ge } from "@arcblock/did-connect/lib/Session";
import ve from "@arcblock/ux/lib/Tabs";
import M from "@arcblock/ux/lib/Empty";
import be from "@arcblock/ux/lib/Button";
import we from "@arcblock/ux/lib/Result";
import { useConfirm as ye } from "@arcblock/ux/lib/Dialog";
import { translate as Ce } from "@arcblock/ux/lib/Locale/util";
import { useLocaleContext as ke } from "@arcblock/ux/lib/Locale/context";
import { ErrorFallback as Pe } from "@arcblock/ux/lib/ErrorBoundary";
import { styled as oe } from "@arcblock/ux/lib/Theme";
import Se from "lodash/cloneDeep";
import { joinURL as C, getQuery as De, withoutTrailingSlash as Z, withQuery as $ } from "ufo";
import { PROFILE_URL as k } from "@arcblock/ux/lib/Util/constant";
import Me from "../../Footer/index.js";
import ee from "../../Header/index.js";
import { translations as Te } from "../libs/locales.js";
import re from "./user-info/user-basic-info.js";
import "@mui/icons-material";
import "@iconify/react";
import "@arcblock/ux/lib/DID";
import "@iconify-icons/material-symbols/schedule-outline-rounded";
import "@iconify-icons/material-symbols/more-time-rounded";
import "@iconify-icons/material-symbols/captive-portal-rounded";
import "@iconify-icons/material-symbols/settings-input-antenna-rounded";
import "@arcblock/ux/lib/RelativeTime";
import "@arcblock/ux/lib/UserCard/Content/shorten-label";
import "./user-info/switch-role.js";
import { formatBlockletInfo as We, getLink as T, getLocalizedNavigation as ze } from "../../blocklets.js";
import Ae from "./passport.js";
import Ue from "./settings.js";
import { client as te } from "../../libs/client.js";
import Le from "../../hooks/use-mobile.js";
import { ConfigUserSpaceProvider as Be } from "../../contexts/config-user-space.js";
import Fe from "./storage/index.js";
import Re from "./nft.js";
const W = C(k, "/nfts"), z = C(k, "/settings"), A = C(k, "/did-spaces"), ie = oe(a)(({ theme: v }) => ({
flex: 1,
boxSizing: "border-box",
padding: "0 16px",
width: "100%",
maxWidth: 1600,
margin: "0 auto",
display: "flex",
alignItems: "stretch",
gap: 2.5,
flexDirection: "column",
[v.breakpoints.up("md")]: {
flexDirection: "row"
}
})), U = oe(a)(({ theme: v }) => ({
overflow: "hidden",
flex: "revert",
[v.breakpoints.up("md")]: {
flex: 1
},
"@media (min-width: 850px) and (max-width: 1050px)": {
"& .user-center-tabs": {
maxWidth: "500px"
}
}
}));
function Sr({
children: v,
notLoginContent: L = null,
currentTab: h,
contentProps: B = {},
disableAutoRedirect: F = !1,
hideFooter: ne = !1,
headerProps: se = {},
footerProps: ae = {},
userDid: P = void 0,
stickySidebar: R = !1,
embed: I = !1,
onlyProfile: w = !1
// 只显示 profile 页面,用于 ArcSphere 只需要显示 Profile 的内容
}) {
const { locale: x } = ke(), l = Le({ key: "md" }), g = y((r, o = {}) => Ce(Te, r, x, "en", o)), t = fe(ge)?.session, p = d(() => {
if (P)
return P;
const r = window.location.href, o = De(r);
return o?.did ? Array.isArray(o.did) ? o.did[0] : o.did : t?.user?.did;
}, [t?.user?.did, P]), i = d(() => t?.user ? p === t?.user?.did : !1, [p, t?.user?.did]), n = Y(
// eslint-disable-next-line consistent-return
async () => {
if (await xe(() => t?.initialized), i)
return t.user;
if (p)
return te.user.getUserPublicInfo({ did: p });
},
{
refreshDeps: [p, i, t?.initialized, t?.user]
}
), j = y(() => i ? t.refresh() : n.refresh()), m = Y(
async () => n.data && h ? await te.user.getUserPrivacyConfig({ did: p }) : null,
{
refreshDeps: [p, n.data, h],
loadingDelay: 300
}
), { confirmHolder: H } = ye({
fullScreen: l,
sx: {
".MuiDialog-paper": {
borderRadius: 1,
maxWidth: 1200
},
".ux-dialog_title": {
fontWeight: 600
},
".ux-dialog_closeButton": {
p: 1
},
".MuiDialogActions-root": {
display: {
xs: "none",
md: "flex"
}
}
}
}), N = d(() => {
const r = Se(window.blocklet);
try {
return We(r);
} catch (o) {
return console.error("Failed to format blocklet info", o, r), r;
}
}, []), _ = d(() => {
const r = {
label: g("common.nft"),
protected: !1,
isPrivate: !1,
// true: 隐私数据,仅自己可见
value: W,
url: T(W, x)
};
let o = [r];
return i && (o = [
r,
{
label: g("common.setting"),
protected: !0,
isPrivate: !0,
value: z,
url: T(z, x)
},
{
label: g("storageManagement"),
protected: !0,
isPrivate: !0,
value: A,
url: T(A, x)
}
]), o;
}, [i, x]), c = d(() => {
const r = N?.navigation?.userCenter || [];
return (ze(r, x) || []).concat(_).map((u) => {
const X = u.value ?? u._rawLink ?? u.link ?? u.url;
return {
value: X,
label: u.title || u.label,
url: u.link || u.url,
protected: m?.data?.[X] ?? !1,
isPrivate: u.isPrivate || u.private || (u?._rawLink?.includes("/customer") ?? !1)
// FIXME: HACK: 隐藏 /customer 菜单, 需要一个通用的解决方案,在嵌入的时候就决定是否是私有的
// icon: x.icon,
};
}).filter((u) => i || !u.isPrivate);
}, [N, n.data, m?.data, x, _, i]), s = d(() => c.find((r) => Z(r.value) === Z(h)), [c]), le = y((r) => {
const o = c.find((b) => b.value === r);
o && (window.location.href = $(o.url, {
did: i ? void 0 : p
}));
}), E = d(() => /* @__PURE__ */ e(
Ue,
{
user: n.data,
settings: { userCenterTabs: c },
onSave: async (r) => r === "privacy" ? (await m.runAsync(), m.data) : (r === "profile" && await t.refresh(), null),
isMobile: l
}
), [n.data, c, m.data, m.runAsync]), O = d(() => s && s?.value === z, [s]), q = d(() => s && s?.value === C(k, "/profile") || s?.value === W, [s]), de = d(() => s && s?.value === A, [s]), ce = t.useOAuth(), ue = t.usePasskey(), Q = y(() => {
t?.user?.sourceProvider === "passkey" ? ue.switchPassport(t.user) : ["google", "apple", "email", "github"].includes(t?.user?.sourceProvider ?? "") ? ce.switchOAuthPassport(t.user) : t && t.switchPassport();
}), S = d(() => q ? /* @__PURE__ */ f(
a,
{
sx: {
display: "flex",
flexDirection: "column",
gap: 2.5
},
children: [
i ? /* @__PURE__ */ f(a, { sx: { border: "1px solid", borderColor: "divider", borderRadius: 1.5, p: 2 }, children: [
/* @__PURE__ */ e(
pe,
{
sx: {
color: "text.primary",
fontWeight: 600,
mb: 2.5
},
children: g("passport")
}
),
/* @__PURE__ */ e(Ae, { user: n.data })
] }) : null,
/* @__PURE__ */ e(Re, { user: n.data })
]
}
) : O && i ? E : de && i ? /* @__PURE__ */ e(Be, { children: /* @__PURE__ */ e(Fe, {}) }) : null, [O, q, n, i, R, E]), G = d(() => /* @__PURE__ */ e(
a,
{
sx: {
display: {
xs: i ? "none" : "block",
md: "block"
},
py: 3
},
children: /* @__PURE__ */ e(M, { children: g("emptyContent") })
}
), [i, x]), J = d(() => !m.data || m.loading ? /* @__PURE__ */ e(
a,
{
sx: {
height: "100%",
minWidth: "160px",
minHeight: "160px",
display: "flex",
justifyContent: "center",
alignItems: "center",
flex: 1
},
children: /* @__PURE__ */ e(me, {})
}
) : (
// eslint-disable-next-line react/jsx-no-useless-fragment
/* @__PURE__ */ e(a, { sx: { flex: 1 }, children: s?.protected && !i ? /* @__PURE__ */ e(a, { children: /* @__PURE__ */ e(M, { children: g("underProtected") }) }) : (
// eslint-disable-next-line react/jsx-no-useless-fragment
/* @__PURE__ */ e(D, { children: v ? /* @__PURE__ */ e(a, { ...B, children: v }) : /* @__PURE__ */ e(D, { children: S }) })
) })
), [m, s, i, v, B, S, x]), K = d(() => {
if (n.loading || t.loading)
return null;
if (n.error) {
if (n.error?.response?.status === 404)
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(we, { status: 404, description: g("noUserFound") }) });
const b = {
message: n.error.response?.data?.error || n.error.message || "error occurred"
};
return /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ e(Pe, { error: b }) });
}
return !p && !n.data ? L || /* @__PURE__ */ e(a, { sx: { width: "100%" }, children: /* @__PURE__ */ f(
a,
{
sx: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
gap: 1
},
children: [
/* @__PURE__ */ e(M, { children: g("viewAfterLogin") }),
/* @__PURE__ */ e(be, { size: "small", variant: "contained", onClick: () => t.login(), children: g("loginNow") })
]
}
) }) : I ? /* @__PURE__ */ f(U, { children: [
c.length > 0 && h ? /* @__PURE__ */ e(
a,
{
sx: {
display: l ? "block" : "flex",
height: "100%",
overflow: "auto",
padding: "1px"
},
children: J
}
) : null,
c.length === 0 && G
] }) : w ? /* @__PURE__ */ e(U, { display: "flex", flexDirection: l ? "column" : "row", children: /* @__PURE__ */ e(
re,
{
isMobile: l,
order: l ? 1 : "unset",
isMyself: i,
switchPassport: Q,
switchProfile: t.switchProfile,
user: n.data,
showFullDid: !1,
onlyProfile: w,
refreshProfile: j,
sx: {
padding: l ? "16px 0 0 0" : "40px 24px 24px 40px",
...l ? {} : { width: 320, maxWidth: 320, flexShrink: 0 },
boxSizing: "content-box"
}
}
) }) : /* @__PURE__ */ f(U, { display: "flex", flexDirection: l ? "column" : "row", children: [
/* @__PURE__ */ f(
a,
{
className: "user-center-tabs",
sx: {
flex: "1",
order: l ? 2 : "unset"
},
children: [
c.length > 0 && h ? /* @__PURE__ */ f(
a,
{
sx: {
display: "flex",
flexDirection: "column",
height: "100%",
overflow: "auto",
padding: "1px"
},
children: [
/* @__PURE__ */ e(
ve,
{
orientation: "horizontal",
variant: "line",
tabs: c,
current: s?.value ?? h,
onChange: le,
sx: {
mb: 2,
".MuiTabs-flexContainer": {
gap: 3,
".MuiButtonBase-root": {
padding: l ? "16px 4px" : "40px 4px 32px 4px",
fontSize: 16
},
".MuiTab-root": {
display: "block",
textAlign: "left",
alignItems: "flex-start",
justifyContent: "flex-start",
fontWeight: 400
}
},
".MuiTabs-root": {
"&:after": {
content: '""',
display: "block",
width: "100%",
height: "1px",
backgroundColor: "divider"
}
}
}
}
),
J
]
}
) : null,
c.length === 0 && G
]
}
),
!l && /* @__PURE__ */ e(he, { orientation: "vertical", sx: { ml: 5 } }),
/* @__PURE__ */ e(
re,
{
isMobile: l,
order: l ? 1 : "unset",
isMyself: i,
switchPassport: Q,
switchProfile: t.switchProfile,
user: n.data,
refreshProfile: j,
showFullDid: !1,
sx: {
padding: l ? "16px 0 0 0" : "40px 24px 24px 40px",
...l ? {} : { width: 320, maxWidth: 320, flexShrink: 0 },
boxSizing: "content-box"
}
}
)
] });
}, [
n,
c,
i,
s,
m,
h,
R,
S
]), V = d(() => i ? !1 : s?.isPrivate, [i, s]);
if (d(() => w ? !1 : !F && !h && c?.length > 0 || !s || V, [F, h, c, s, V, w])) {
const r = c[0]?.url, o = c.find((b) => b.value === r);
return r && !o?.isPrivate && window.location.replace(
$(r, {
did: i ? void 0 : p
})
), null;
}
return I || w ? /* @__PURE__ */ f(D, { children: [
/* @__PURE__ */ e(ee, { style: { display: "none" } }),
/* @__PURE__ */ f(ie, { children: [
K,
H
] })
] }) : /* @__PURE__ */ f(
a,
{
sx: {
minHeight: "100vh",
display: "flex",
flexDirection: "column"
},
children: [
/* @__PURE__ */ e(ee, { bordered: !0, ...se, maxWidth: "100%" }),
/* @__PURE__ */ f(ie, { children: [
K,
H
] }),
ne ? null : /* @__PURE__ */ e(
Me,
{
bordered: !0,
...ae,
sx: {
".MuiContainer-root": {
maxWidth: 1600
}
}
}
)
]
}
);
}
export {
Sr as default
};