forked from akai/readest
94ede10f6e
On Android, long-press selects text via selectionchange while the finger is still on the screen. The quick action handler was gated by androidTouchEndRef and silently returned, so no popup ever opened. After the user lifted, nothing re-ran the gated action. Track the gated action in a small DeferredActionState ref and flush it from the native touchend handler, so instant copy/dictionary/wikipedia/ search/translate/tts now fire on the first long-press release.
36 lines
1022 B
TypeScript
36 lines
1022 B
TypeScript
// Tiny helper for actions that need to wait for an asynchronous "ready" signal
|
|
// before running. Used by the Annotator on Android: a long-press selects text
|
|
// while the finger is still down, but the quick action (translate/dictionary/
|
|
// tts/etc.) must not fire until the user lifts (touchend), or the popup it
|
|
// opens would be dismissed by the in-progress touch.
|
|
|
|
export interface DeferredActionState {
|
|
pending: (() => void) | null;
|
|
}
|
|
|
|
export const createDeferredActionState = (): DeferredActionState => ({ pending: null });
|
|
|
|
export const runOrDeferAction = (
|
|
state: DeferredActionState,
|
|
shouldDefer: boolean,
|
|
action: () => void,
|
|
): void => {
|
|
if (shouldDefer) {
|
|
state.pending = action;
|
|
return;
|
|
}
|
|
state.pending = null;
|
|
action();
|
|
};
|
|
|
|
export const flushDeferredAction = (state: DeferredActionState): void => {
|
|
const fn = state.pending;
|
|
if (!fn) return;
|
|
state.pending = null;
|
|
fn();
|
|
};
|
|
|
|
export const cancelDeferredAction = (state: DeferredActionState): void => {
|
|
state.pending = null;
|
|
};
|