Fix incorrect callback referencing

This commit is contained in:
Alexander Zinchuk 2023-04-26 21:15:08 +04:00
parent 485d52cab3
commit 70847a933e
6 changed files with 56 additions and 39 deletions

View File

@ -62,10 +62,6 @@ const useDraft = (
} }
}, [chatId, threadId, isEditing, lastSyncTime, getHtml, saveDraft, clearDraft]); }, [chatId, threadId, isEditing, lastSyncTime, getHtml, saveDraft, clearDraft]);
const forceUpdateDraft = useCallback(() => {
updateDraft(undefined, true);
}, [updateDraft]);
const updateDraftRef = useStateRef(updateDraft); const updateDraftRef = useStateRef(updateDraft);
const runDebouncedForSaveDraft = useRunDebounced(DRAFT_DEBOUNCE, true, undefined, [chatId, threadId]); const runDebouncedForSaveDraft = useRunDebounced(DRAFT_DEBOUNCE, true, undefined, [chatId, threadId]);
@ -138,6 +134,10 @@ const useDraft = (
}); });
}, [chatIdRef, getHtml, runDebouncedForSaveDraft, threadIdRef, updateDraftRef]); }, [chatIdRef, getHtml, runDebouncedForSaveDraft, threadIdRef, updateDraftRef]);
function forceUpdateDraft() {
updateDraft(undefined, true);
}
useBackgroundMode(forceUpdateDraft); useBackgroundMode(forceUpdateDraft);
useBeforeUnload(forceUpdateDraft); useBeforeUnload(forceUpdateDraft);
}; };

View File

@ -1,6 +1,7 @@
import { useEffect } from '../lib/teact/teact'; import { useEffect } from '../lib/teact/teact';
import { createCallbackManager } from '../util/callbacks'; import { createCallbackManager } from '../util/callbacks';
import { useLastCallback } from './useLastCallback';
const blurCallbacks = createCallbackManager(); const blurCallbacks = createCallbackManager();
const focusCallbacks = createCallbackManager(); const focusCallbacks = createCallbackManager();
@ -26,33 +27,26 @@ export default function useBackgroundMode(
onFocus?: AnyToVoidFunction, onFocus?: AnyToVoidFunction,
isDisabled = false, isDisabled = false,
) { ) {
const lastOnBlur = useLastCallback(onBlur);
const lastOnFocus = useLastCallback(onFocus);
useEffect(() => { useEffect(() => {
if (isDisabled) { if (isDisabled) {
return undefined; return undefined;
} }
if (!isFocused) { if (!isFocused) {
onBlur?.(); lastOnBlur();
} }
if (onBlur) { blurCallbacks.addCallback(lastOnBlur);
blurCallbacks.addCallback(onBlur); focusCallbacks.addCallback(lastOnFocus);
}
if (onFocus) {
focusCallbacks.addCallback(onFocus);
}
return () => { return () => {
if (onFocus) { focusCallbacks.removeCallback(lastOnFocus);
focusCallbacks.removeCallback(onFocus); blurCallbacks.removeCallback(lastOnBlur);
}
if (onBlur) {
blurCallbacks.removeCallback(onBlur);
}
}; };
}, [isDisabled, onBlur, onFocus]); }, [isDisabled, lastOnBlur, lastOnFocus]);
} }
export function isBackgroundModeActive() { export function isBackgroundModeActive() {

View File

@ -2,8 +2,10 @@ import { useEffect } from '../lib/teact/teact';
import { onBeforeUnload } from '../util/schedulers'; import { onBeforeUnload } from '../util/schedulers';
import { useLastCallback } from './useLastCallback';
export default function useBeforeUnload(callback: AnyToVoidFunction) { export default function useBeforeUnload(callback: AnyToVoidFunction) {
useEffect(() => { const lastCallback = useLastCallback(callback);
return onBeforeUnload(callback);
}, [callback]); useEffect(() => onBeforeUnload(lastCallback), [lastCallback]);
} }

View File

@ -1,6 +1,9 @@
import { useEffect } from '../lib/teact/teact'; import { useEffect } from '../lib/teact/teact';
import { createCallbackManager } from '../util/callbacks'; import { createCallbackManager } from '../util/callbacks';
import { useLastCallback } from './useLastCallback';
// Make sure to end even if end callback was not called (which was some hardly-reproducible bug) // Make sure to end even if end callback was not called (which was some hardly-reproducible bug)
const AUTO_END_TIMEOUT = 1000; const AUTO_END_TIMEOUT = 1000;
@ -11,27 +14,30 @@ let timeout: number | undefined;
let isAnimating = false; let isAnimating = false;
const useHeavyAnimationCheck = ( const useHeavyAnimationCheck = (
handleAnimationStart: AnyToVoidFunction, onStart?: AnyToVoidFunction,
handleAnimationEnd: AnyToVoidFunction, onEnd?: AnyToVoidFunction,
isDisabled = false, isDisabled = false,
) => { ) => {
const lastOnStart = useLastCallback(onStart);
const lastOnEnd = useLastCallback(onEnd);
useEffect(() => { useEffect(() => {
if (isDisabled) { if (isDisabled) {
return undefined; return undefined;
} }
if (isAnimating) { if (isAnimating) {
handleAnimationStart(); lastOnStart();
} }
startCallbacks.addCallback(handleAnimationStart); startCallbacks.addCallback(lastOnStart);
endCallbacks.addCallback(handleAnimationEnd); endCallbacks.addCallback(lastOnEnd);
return () => { return () => {
endCallbacks.removeCallback(handleAnimationEnd); endCallbacks.removeCallback(lastOnEnd);
startCallbacks.removeCallback(handleAnimationStart); startCallbacks.removeCallback(lastOnStart);
}; };
}, [isDisabled, handleAnimationEnd, handleAnimationStart]); }, [isDisabled, lastOnEnd, lastOnStart]);
}; };
export function isHeavyAnimating() { export function isHeavyAnimating() {

View File

@ -0,0 +1,9 @@
import { useCallback } from '../lib/teact/teact';
import { useStateRef } from './useStateRef';
export function useLastCallback<T extends AnyFunction>(callback?: T) {
const ref = useStateRef(callback);
return useCallback((...args: Parameters<T>) => ref.current?.(...args), [ref]) as T;
}

View File

@ -1,6 +1,9 @@
import { useEffect } from '../lib/teact/teact'; import { useEffect } from '../lib/teact/teact';
import { createCallbackManager } from '../util/callbacks'; import { createCallbackManager } from '../util/callbacks';
import { useLastCallback } from './useLastCallback';
const startCallbacks = createCallbackManager(); const startCallbacks = createCallbackManager();
const endCallbacks = createCallbackManager(); const endCallbacks = createCallbackManager();
@ -8,27 +11,30 @@ let timeout: number | undefined;
let isActive = false; let isActive = false;
const usePriorityPlaybackCheck = ( const usePriorityPlaybackCheck = (
handleAnimationStart: AnyToVoidFunction, onStart?: AnyToVoidFunction,
handleAnimationEnd: AnyToVoidFunction, onEnd?: AnyToVoidFunction,
isDisabled = false, isDisabled = false,
) => { ) => {
const lastOnStart = useLastCallback(onStart);
const lastOnEnd = useLastCallback(onEnd);
useEffect(() => { useEffect(() => {
if (isDisabled) { if (isDisabled) {
return undefined; return undefined;
} }
if (isActive) { if (isActive) {
handleAnimationStart(); lastOnStart();
} }
startCallbacks.addCallback(handleAnimationStart); startCallbacks.addCallback(lastOnStart);
endCallbacks.addCallback(handleAnimationEnd); endCallbacks.addCallback(lastOnEnd);
return () => { return () => {
endCallbacks.removeCallback(handleAnimationEnd); endCallbacks.removeCallback(lastOnEnd);
startCallbacks.removeCallback(handleAnimationStart); startCallbacks.removeCallback(lastOnStart);
}; };
}, [isDisabled, handleAnimationEnd, handleAnimationStart]); }, [isDisabled, lastOnStart, lastOnEnd]);
}; };
export function isPriorityPlaybackActive() { export function isPriorityPlaybackActive() {