diff --git a/components/item-act.js b/components/item-act.js index e72928b3..61c5e044 100644 --- a/components/item-act.js +++ b/components/item-act.js @@ -55,7 +55,7 @@ export default function ItemAct ({ onClose, itemId, down, children }) { const [act, actUpdate] = useAct() - const onSubmit = useCallback(async ({ amount, hash, hmac }, { update }) => { + const onSubmit = useCallback(async ({ amount, hash, hmac }, { update, keepOpen }) => { if (!me) { const storageKey = `TIP-item:${itemId}` const existingAmount = Number(window.localStorage.getItem(storageKey) || '0') @@ -75,7 +75,7 @@ export default function ItemAct ({ onClose, itemId, down, children }) { // due to optimistic UX on zap undos if (!me || !me.privates.zapUndos) await strike() addCustomTip(Number(amount)) - onClose() + if (!keepOpen) onClose() }, [me, act, down, itemId, strike]) const onSubmitWithUndos = withToastFlow(toaster)( @@ -115,6 +115,7 @@ export default function ItemAct ({ onClose, itemId, down, children }) { return { skipToastFlow, flowId, + tag: itemId, type: 'zap', pendingMessage: `${down ? 'down' : ''}zapped ${sats} sats`, onPending: async () => { @@ -127,7 +128,7 @@ export default function ItemAct ({ onClose, itemId, down, children }) { undoUpdate = update() setTimeout(() => { if (canceled) return resolve() - onSubmit(values, { flowId, ...args, update: null }) + onSubmit(values, { flowId, ...args, update: null, keepOpen: true }) .then(resolve) .catch((err) => { undoUpdate() diff --git a/components/toast.js b/components/toast.js index 7a48f3ee..bb3d1cfe 100644 --- a/components/toast.js +++ b/components/toast.js @@ -67,6 +67,10 @@ export const ToastProvider = ({ children }) => { })) }, []) + const endFlow = useCallback((flowId) => { + setToasts(toasts => toasts.filter(toast => toast.flowId !== flowId)) + }, []) + const toaster = useMemo(() => ({ success: (body, options) => { const toast = { @@ -99,8 +103,9 @@ export const ToastProvider = ({ children }) => { ...options } return dispatchToast(toast) - } - }), [dispatchToast, removeToast]) + }, + endFlow + }), [dispatchToast, removeToast, endFlow]) // Only clear toasts with no cancel function on page navigation // since navigation should not interfere with being able to cancel an action. @@ -213,9 +218,6 @@ export const withToastFlow = (toaster) => flowFn => { if (skipToastFlow) return onPending() - // XXX HACK this ends the flow by using flow toast which immediately closes itself - const endFlow = () => toaster.warning('', { ...toastProps, delay: 0, autohide: true, flowId }) - toaster.warning(pendingMessage || `${t} pending`, { progressBar: !!timeout, delay: timeout || TOAST_DEFAULT_DELAY_MS, @@ -247,7 +249,7 @@ export const withToastFlow = (toaster) => flowFn => { const ret = await onPending() if (!canceled) { if (hideSuccess) { - endFlow() + toaster.endFlow(flowId) } else { toaster.success(`${t} successful`, { ...toastProps, flowId }) } @@ -259,7 +261,7 @@ export const withToastFlow = (toaster) => flowFn => { if (canceled) return const reason = err?.message?.toString().toLowerCase() || 'unknown reason' if (hideError) { - endFlow() + toaster.endFlow(flowId) } else { toaster.danger(`${t} failed: ${reason}`, { ...toastProps, flowId }) }