mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import { askNatively, canAskNatively, type NativeQuestion } from './nativeDialogs';
|
|
|
|
/**
|
|
* Asks `question` through the system once each time `open` turns true, and
|
|
* hands the answer to `answer`. Returns whether the caller should draw its own
|
|
* HTML dialog instead: always in a browser or an app without the plugins, and
|
|
* when the system could not ask. A null question (one the system cannot show,
|
|
* such as one with a list under it) is always asked in HTML.
|
|
*/
|
|
export function useNativeQuestion(
|
|
open: boolean,
|
|
question: NativeQuestion | null,
|
|
answer: (yes: boolean) => void
|
|
): boolean {
|
|
const native = question !== null && canAskNatively();
|
|
const [failed, setFailed] = useState(false);
|
|
// A closed question forgets that the system failed it, so the next one is asked natively again.
|
|
const [wasOpen, setWasOpen] = useState(open);
|
|
if (open !== wasOpen) {
|
|
setWasOpen(open);
|
|
if (!open) setFailed(false);
|
|
}
|
|
// Asked once per opening, also when StrictMode runs the effect twice.
|
|
const asked = useRef(false);
|
|
const latest = useRef({ question, answer });
|
|
useEffect(() => {
|
|
latest.current = { question, answer };
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!open) {
|
|
asked.current = false;
|
|
return;
|
|
}
|
|
if (!native || asked.current || !latest.current.question) return;
|
|
asked.current = true;
|
|
void askNatively(latest.current.question).then((yes) => {
|
|
if (yes === null) setFailed(true);
|
|
else latest.current.answer(yes);
|
|
});
|
|
}, [open, native]);
|
|
|
|
return !native || failed;
|
|
}
|