|
|
|
@ -13,32 +13,19 @@ import { useEffect, useRef } from "react"; |
|
|
|
* Pages register themselves with useHardwareBackHandler(). Sheets and modals |
|
|
|
* also register — the last one wins, matching the visual stacking order. |
|
|
|
*/ |
|
|
|
const backHandlerStack: Array<() => boolean | Promise<boolean>> = []; |
|
|
|
const backHandlerStack: Array<() => void | boolean | Promise<void | boolean>> = []; |
|
|
|
|
|
|
|
/** |
|
|
|
* Register a hardware-back handler. When the user presses the hardware back |
|
|
|
* button (Android), Flutter calls window.__habibHandleHardwareBack(). The |
|
|
|
* root handler walks the stack from top to bottom and calls the first handler. |
|
|
|
* button (Android), Flutter calls window.__habibHandleHardwareBackSync() or |
|
|
|
* window.__habibHandleHardwareBack(). |
|
|
|
* |
|
|
|
* @param handler - Return true if you handled the back (e.g. closed a sheet, |
|
|
|
* flushed answers and navigated). Return false if you didn't handle it |
|
|
|
* (Flutter should close the WebView). |
|
|
|
* @param enabled - When false, the handler is not registered. Useful for |
|
|
|
* conditionally enabling back handling. |
|
|
|
* |
|
|
|
* @example |
|
|
|
* // In questions-list (root): back = close service
|
|
|
|
* useHardwareBackHandler(() => false); |
|
|
|
* |
|
|
|
* // In question-detail: back = flush + navigate
|
|
|
|
* useHardwareBackHandler(async () => { |
|
|
|
* await flushAnswers({ force: true }); |
|
|
|
* router.replace(questionsListHref); |
|
|
|
* return true; |
|
|
|
* }); |
|
|
|
* @param handler - Return true (or void) if you handled the back (e.g. closed a sheet). |
|
|
|
* Return false if you didn't handle it (Flutter should close the WebView). |
|
|
|
* @param enabled - When false, the handler is not registered. |
|
|
|
*/ |
|
|
|
export function useHardwareBackHandler( |
|
|
|
handler: () => boolean | Promise<boolean>, |
|
|
|
handler: () => void | boolean | Promise<void | boolean>, |
|
|
|
enabled = true, |
|
|
|
) { |
|
|
|
const handlerRef = useRef(handler); |
|
|
|
@ -76,7 +63,7 @@ export function handleHardwareBackSync(): boolean { |
|
|
|
// Promise was initiated by invoking the handler; it is handled in JS!
|
|
|
|
return true; |
|
|
|
} |
|
|
|
return Boolean(result); |
|
|
|
return result === undefined ? true : Boolean(result); |
|
|
|
} catch (error) { |
|
|
|
console.warn("[HardwareBackSync] Handler threw:", error); |
|
|
|
return false; |
|
|
|
@ -97,7 +84,7 @@ export async function handleHardwareBack(): Promise<{ handled: boolean }> { |
|
|
|
const handler = backHandlerStack[backHandlerStack.length - 1]; |
|
|
|
try { |
|
|
|
const result = await handler(); |
|
|
|
return { handled: Boolean(result) }; |
|
|
|
return { handled: result === undefined ? true : Boolean(result) }; |
|
|
|
} catch (error) { |
|
|
|
console.warn("[HardwareBack] Handler threw:", error); |
|
|
|
return { handled: false }; |
|
|
|
|