Fix toast progress bar jump due to end flow hack

If an underlying toast finished, an empty toast that automatically immediately hides was dispatched to end the flow ("end flow hack").

If this empty toast had the same tag, the code marked the top toast as hidden even though it was not hidden.

This meant that during render, the animation-delay for the top toast (which was already rendered) was added again, leading to a progress bar jump.

This is fixed by no longer using this "end flow hack" where a toast is dispatched but a dedicated function to end flows.
This commit is contained in:
ekzyis 2024-03-24 19:30:03 +01:00
parent 17071fa615
commit 0193ac97fe
1 changed files with 9 additions and 7 deletions

View File

@ -67,6 +67,10 @@ export const ToastProvider = ({ children }) => {
})) }))
}, []) }, [])
const endFlow = useCallback((flowId) => {
setToasts(toasts => toasts.filter(toast => toast.flowId !== flowId))
}, [])
const toaster = useMemo(() => ({ const toaster = useMemo(() => ({
success: (body, options) => { success: (body, options) => {
const toast = { const toast = {
@ -99,8 +103,9 @@ export const ToastProvider = ({ children }) => {
...options ...options
} }
return dispatchToast(toast) return dispatchToast(toast)
} },
}), [dispatchToast, removeToast]) endFlow
}), [dispatchToast, removeToast, endFlow])
// Only clear toasts with no cancel function on page navigation // Only clear toasts with no cancel function on page navigation
// since navigation should not interfere with being able to cancel an action. // 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() 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`, { toaster.warning(pendingMessage || `${t} pending`, {
progressBar: !!timeout, progressBar: !!timeout,
delay: timeout || TOAST_DEFAULT_DELAY_MS, delay: timeout || TOAST_DEFAULT_DELAY_MS,
@ -247,7 +249,7 @@ export const withToastFlow = (toaster) => flowFn => {
const ret = await onPending() const ret = await onPending()
if (!canceled) { if (!canceled) {
if (hideSuccess) { if (hideSuccess) {
endFlow() toaster.endFlow(flowId)
} else { } else {
toaster.success(`${t} successful`, { ...toastProps, flowId }) toaster.success(`${t} successful`, { ...toastProps, flowId })
} }
@ -259,7 +261,7 @@ export const withToastFlow = (toaster) => flowFn => {
if (canceled) return if (canceled) return
const reason = err?.message?.toString().toLowerCase() || 'unknown reason' const reason = err?.message?.toString().toLowerCase() || 'unknown reason'
if (hideError) { if (hideError) {
endFlow() toaster.endFlow(flowId)
} else { } else {
toaster.danger(`${t} failed: ${reason}`, { ...toastProps, flowId }) toaster.danger(`${t} failed: ${reason}`, { ...toastProps, flowId })
} }