import React, { useState, useEffect } from 'react'; import { MediaTransport } from './transport'; import { MemberId } from '@joystream/types/members'; import { useMyMembership } from '@polkadot/joy-utils/MyMembershipContext'; import { useTransportContext } from './TransportContext'; import { withMembershipRequired } from '@polkadot/joy-utils/MyAccount'; type InitialPropsWithMembership = A & { myAddress?: string; myMemberId?: MemberId; } type ResolverProps = InitialPropsWithMembership & { transport: MediaTransport; } type BaseProps = { component: React.ComponentType; unresolvedView?: React.ReactElement; resolveProps?: (props: ResolverProps) => Promise; /** * Array of property names that can trigger re-render of the view, * if values of such properties changed. */ triggers?: (keyof A)[]; /** Set `true` if only members should have access to this component. `false` by default. */ membersOnly?: boolean; } function serializeTrigger (val: any): any { if (['number', 'boolean', 'string'].includes(typeof val)) { return val; } else if (typeof val === 'object' && typeof val.toString === 'function') { return val.toString(); } else { return undefined; } } export function MediaView (baseProps: BaseProps) { function InnerView (initialProps: A & B) { const { component: Component, resolveProps, triggers = [], unresolvedView = null } = baseProps; const transport = useTransportContext(); const { myAddress, myMemberId } = useMyMembership(); const resolverProps = { ...initialProps, transport, myAddress, myMemberId }; const [resolvedProps, setResolvedProps] = useState({} as B); const [propsResolved, setPropsResolved] = useState(false); const initialDeps = triggers.map(propName => serializeTrigger(initialProps[propName])); const rerenderDeps = [...initialDeps, myAddress]; useEffect(() => { async function doResolveProps () { if (typeof resolveProps !== 'function') return; console.log('Resolving props of media view'); // Transport session allows us to cache loaded channels, entites and classes // during the render of this view: transport.openSession(); setResolvedProps(await resolveProps(resolverProps)); transport.closeSession(); setPropsResolved(true); } if (!transport) { console.error('Transport is not defined'); } else { doResolveProps(); } }, rerenderDeps); console.log('Rerender deps of Media View:', rerenderDeps); const renderResolving = () => { return unresolvedView ||
; }; return propsResolved ? : renderResolving(); } const { membersOnly = false } = baseProps; return membersOnly ? withMembershipRequired(InnerView) : InnerView; }