UNPKG

@blocklet/ui-react

Version:

Some useful front-end web components that can be used in Blocklets.

445 lines (444 loc) 14.4 kB
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 };