diff --git a/src/ExtrinsicSubmissionStateView.tsx b/src/ExtrinsicSubmissionStateView.tsx new file mode 100644 index 00000000..2f37b9f2 --- /dev/null +++ b/src/ExtrinsicSubmissionStateView.tsx @@ -0,0 +1,22 @@ +import { useLogionChain } from './logion-chain/LogionChainContext'; +import ExtrinsicSubmissionResult from './ExtrinsicSubmissionResult'; + +export interface Props { + successMessage?: string; + slim?: boolean; +} + +export default function ExtrinsicSubmissionStateView(props: Props) { + const { extrinsicSubmissionState } = useLogionChain(); + + if(extrinsicSubmissionState.submitted) { + return (); + } else { + return null; + } +} diff --git a/src/loc/AcknowledgeButton.tsx b/src/loc/AcknowledgeButton.tsx index 1628b95b..241339e7 100644 --- a/src/loc/AcknowledgeButton.tsx +++ b/src/loc/AcknowledgeButton.tsx @@ -5,31 +5,22 @@ import Button, { Action } from "src/common/Button"; import Icon from "src/common/Icon"; import { LocItem, MetadataData, FileData, LinkData } from "./LocItem"; import Dialog from "src/common/Dialog"; -import ClientExtrinsicSubmitter, { Call, CallCallback } from "src/ClientExtrinsicSubmitter"; import EstimatedFees from "./fees/EstimatedFees"; import { useLocContext } from "./LocContext"; import Alert from "src/common/Alert"; -import { useLogionChain } from "src/logion-chain"; +import { useLogionChain, CallCallback } from "src/logion-chain"; import "./AcknowledgeButton.css"; +import ExtrinsicSubmissionStateView from "src/ExtrinsicSubmissionStateView"; export interface Props { locItem: LocItem; } -enum State { - INIT, - PREVIEW, - ACKNOWLEDGING, - ACKNOWLEDGED, - ERROR, -} - export default function AcknowledgeButton(props: Props) { - const [ state, setState ] = useState(State.INIT); + const [ showDialog, setShowDialog ] = useState(false); const [ fees, setFees ] = useState(); - const [ call, setCall ] = useState(); const { mutateLocState, locState } = useLocContext(); - const { signer } = useLogionChain(); + const { signer, submitCall, clearSubmissionState, extrinsicSubmissionState } = useLogionChain(); useEffect(() => { if(fees === undefined) { @@ -59,65 +50,61 @@ export default function AcknowledgeButton(props: Props) { }, [ fees, props.locItem, locState ]); const preview = useCallback(() => { - setState(State.PREVIEW); + setShowDialog(true); }, []); const close = useCallback(() => { - setState(State.INIT); - }, []); + setShowDialog(false); + clearSubmissionState(); + }, [ clearSubmissionState ]); - const acknowledge = useCallback(async () => { - setState(State.ACKNOWLEDGING); - const call = async (callback: CallCallback) => + const call = useMemo(() => { + return async (callback: CallCallback) => mutateLocState(async current => { - if(signer && current instanceof OpenLoc) { - if(props.locItem.type === "Document") { - return current.legalOfficer.acknowledgeFile({ - hash: props.locItem.as().hash, - signer, - callback, - }); - } else if(props.locItem.type === "Data") { - return current.legalOfficer.acknowledgeMetadata({ - nameHash: props.locItem.as().name.hash, - signer, - callback, - }); - } else if(props.locItem.type === "Linked LOC") { - return current.legalOfficer.acknowledgeLink({ - target: props.locItem.as().linkedLoc.id, - signer, - callback, - }); - } else { - throw new Error("Unexpected type"); - } + if(signer && current instanceof OpenLoc) { + if(props.locItem.type === "Document") { + return current.legalOfficer.acknowledgeFile({ + hash: props.locItem.as().hash, + signer, + callback, + }); + } else if(props.locItem.type === "Data") { + return current.legalOfficer.acknowledgeMetadata({ + nameHash: props.locItem.as().name.hash, + signer, + callback, + }); + } else if(props.locItem.type === "Linked LOC") { + return current.legalOfficer.acknowledgeLink({ + target: props.locItem.as().linkedLoc.id, + signer, + callback, + }); } else { - return current; + throw new Error("Unexpected type"); } - }); - setCall(() => call); - }, [ mutateLocState, signer, props.locItem ]); + } else { + return current; + } + }); + }, [ mutateLocState, props.locItem, signer ]); const actions = useMemo(() => { const actions: Action[] = []; - if(state === State.PREVIEW || state === State.ERROR) { + if(!extrinsicSubmissionState.submitted) { actions.push({ id: "cancel", buttonText: "Cancel", buttonVariant: "secondary", callback: close, }); - } - if(state === State.PREVIEW) { actions.push({ id: "proceed", buttonText: "Proceed", buttonVariant: "polkadot", - callback: acknowledge, + callback: () => submitCall(call), }); - } - if(state === State.ACKNOWLEDGED) { + } else if(extrinsicSubmissionState.callEnded) { actions.push({ id: "close", buttonText: "Close", @@ -126,7 +113,7 @@ export default function AcknowledgeButton(props: Props) { }); } return actions; - }, [ state, close, acknowledge ]); + }, [ close, submitCall, extrinsicSubmissionState, call ]); return ( <> @@ -137,7 +124,7 @@ export default function AcknowledgeButton(props: Props) { Acknowledge
- setState(State.ACKNOWLEDGED) } - onError={ () => setState(State.ERROR) } />
diff --git a/src/logion-chain/LogionChainContext.tsx b/src/logion-chain/LogionChainContext.tsx index 85cc9a26..5608d431 100644 --- a/src/logion-chain/LogionChainContext.tsx +++ b/src/logion-chain/LogionChainContext.tsx @@ -168,6 +168,7 @@ export interface LogionChainContextType { submitCall: (call: Call) => Promise; submitSignAndSubmit: (signAndSubmit: SignAndSubmit) => void; resetSubmissionState: () => void; + clearSubmissionState: () => void; } export interface FullLogionChainContextType extends LogionChainContextType { @@ -201,6 +202,7 @@ const initState = (): FullLogionChainContextType => ({ submitCall: () => Promise.reject(), submitSignAndSubmit: () => {}, resetSubmissionState: () => {}, + clearSubmissionState: () => {}, }); type ActionType = 'SET_SELECT_ADDRESS' @@ -230,6 +232,8 @@ type ActionType = 'SET_SELECT_ADDRESS' | 'SET_SUBMIT_SIGN_AND_SUBMIT' | 'SET_RESET_SUBMISSION_STATE' | 'RESET_SUBMISSION_STATE' + | 'SET_CLEAR_SUBMISSION_STATE' + | 'CLEAR_SUBMISSION_STATE' ; interface Action { @@ -258,6 +262,7 @@ interface Action { extrinsicSubmissionError?: unknown; submitSignAndSubmit?: (signAndSubmit: SignAndSubmit) => void; resetSubmissionState?: () => void; + clearSubmissionState?: () => void; } function buildAxiosFactory(authenticatedClient?: LogionClient): AxiosFactory { @@ -455,7 +460,7 @@ const reducer: Reducer = (state: FullLogionC case 'SET_SUBMISSION_ENDED': return { ...state, - extrinsicSubmissionState: state.extrinsicSubmissionState.end(action.error || null), + extrinsicSubmissionState: state.extrinsicSubmissionState.end(action.extrinsicSubmissionError || null), }; case 'SET_SUBMIT_SIGN_AND_SUBMIT': return { @@ -472,6 +477,16 @@ const reducer: Reducer = (state: FullLogionC ...state, extrinsicSubmissionState: state.extrinsicSubmissionState.resetAndKeepResult(), }; + case 'SET_CLEAR_SUBMISSION_STATE': + return { + ...state, + clearSubmissionState: action.clearSubmissionState!, + }; + case 'CLEAR_SUBMISSION_STATE': + return { + ...state, + extrinsicSubmissionState: new ExtrinsicSubmissionState(), + }; default: /* istanbul ignore next */ throw new Error(`Unknown type: ${action.type}`); @@ -836,6 +851,19 @@ const LogionChainContextProvider = (props: LogionChainContextProviderProps): JSX } }, [ state.resetSubmissionState, resetSubmissionState ]); + const clearSubmissionState = useCallback(() => { + dispatch({ type: 'CLEAR_SUBMISSION_STATE' }); + }, [ ]); + + useEffect(() => { + if(state.clearSubmissionState !== clearSubmissionState) { + dispatch({ + type: 'SET_CLEAR_SUBMISSION_STATE', + clearSubmissionState, + }); + } + }, [ state.clearSubmissionState, clearSubmissionState ]); + return {props.children} ; diff --git a/src/logion-chain/index.tsx b/src/logion-chain/index.tsx index fd02f584..9efd09b7 100644 --- a/src/logion-chain/index.tsx +++ b/src/logion-chain/index.tsx @@ -2,6 +2,7 @@ import { useLogionChain, LogionChainContextProvider, AxiosFactory, + CallCallback, } from './LogionChainContext'; export { @@ -10,4 +11,5 @@ export { }; export type { AxiosFactory, + CallCallback, };