@blocklet/ui-react
Version:
Some useful front-end web components that can be used in Blocklets.
89 lines (77 loc) • 2.73 kB
JavaScript
import { BLOCKLET_SERVICE_PATH_PREFIX } from '@arcblock/did-connect-react/lib/constant';
import { useEffect, useMemo, useRef, useState } from 'react';
import { joinURL } from 'ufo';
const parseDidToSet = (did) => {
if (typeof did === 'string') {
return new Set(did.split(';;'));
}
return new Set(did);
};
function useComponentInstalled({ did, onInstalled, onError }) {
const didKeys = Array.isArray(did) ? did.join(';;') : did;
const [installStatus, setInstallStatus] = useState({});
const onInstalledRef = useRef({ onInstalled, onError });
onInstalledRef.current = { onInstalled, onError };
const { optionalComponents, componentMountPoints } = window.blocklet;
const optComponents = useMemo(() => {
if (!optionalComponents || !optionalComponents.length) {
return [];
}
const didSet = parseDidToSet(didKeys);
const components = optionalComponents.filter((c) => didSet.has(c.meta.did));
(components ? onInstalledRef.current.onError : onInstalledRef.current.onInstalled)?.(components);
return components;
}, [didKeys, optionalComponents]);
const definedInBlockletYML = useMemo(() => {
if (optComponents.length) {
return true;
}
const didSet = parseDidToSet(didKeys);
return (componentMountPoints || []).find((item) => didSet.has(item.did));
}, [optComponents, componentMountPoints, didKeys]);
optComponents.forEach((item) => {
item.storeUrl = joinURL(item.meta.homepage, 'blocklets', item.meta.did);
item.installUrl = joinURL(
window.blocklet.appUrl,
BLOCKLET_SERVICE_PATH_PREFIX,
`/admin/components?install-component=${item.meta.did}`
);
});
useEffect(() => {
const handle = (event) => {
if (event.origin !== window.blocklet.appUrl) {
return;
}
if (event.data?.kind === 'component-installer' && event.data?.blocklet?.children) {
let hasChild = false;
const didSet = parseDidToSet(didKeys);
event.data?.blocklet?.children.forEach((item) => {
if (didSet.has(item.meta?.did)) {
hasChild = true;
setInstallStatus((value) => {
return {
...value,
[item.meta?.did]: item.status || 'waiting',
};
});
}
});
if (!hasChild) {
setInstallStatus({});
}
}
};
window.addEventListener('message', handle);
return () => {
window.removeEventListener('message', handle);
};
}, [didKeys]);
return {
optComponents,
installed: !optComponents.length && definedInBlockletYML,
installStatus,
setInstallStatus,
definedInBlockletYML,
};
}
export default useComponentInstalled;