| 1 | import { useCommittedCommand } from "../lib/useCommittedCommand"; |
| 2 | import type { Translator } from "../lib/i18n"; |
| 3 | import type { createSessionSurfaceFence } from "./sessionTarget"; |
| 4 | |
| 5 | const loadDeliveryContinue = () => import("../lib/deliveryContinue"); |
| 6 | |
| 7 | export type DeliveryContinueCommandsInput = { |
| 8 | surfaceFence: ReturnType<typeof createSessionSurfaceFence>; |
| 9 | ready: boolean; |
| 10 | goal: string | undefined; |
| 11 | t: Translator; |
| 12 | ports: { |
| 13 | resumeGoal(tabId: string): Promise<boolean>; |
| 14 | recoverDelivery(tabId: string, prompt: string): Promise<void>; |
| 15 | }; |
| 16 | }; |
| 17 | |
| 18 | /** |
| 19 | * Owns the delivery "continue checks" chain: the recovery-prompt send and the |
| 20 | * continue command that captures the committed surface ownership at click |
| 21 | * time, so a mid-flight tab switch or session replacement can never deliver |
| 22 | * the continuation into a session that no longer owns the UI. The delivery |
| 23 | * owner chunk stays lazy behind the command. |
| 24 | */ |
| 25 | export function useDeliveryContinueCommands(input: DeliveryContinueCommandsInput) { |
| 26 | const { surfaceFence, t, ports } = input; |
| 27 | |
| 28 | const sendDeliveryRecovery = useCommittedCommand((tabId: string) => |
| 29 | ports.recoverDelivery(tabId, t("notice.deliveryIncompleteContinuePrompt"))); |
| 30 | |
| 31 | const handleDeliveryContinue = useCommittedCommand(() => { |
| 32 | const ownership = surfaceFence.capture(); |
| 33 | return loadDeliveryContinue().then(({ continueDelivery }) => continueDelivery({ |
| 34 | tabId: ownership?.tabId, |
| 35 | ready: input.ready, |
| 36 | goal: input.goal, |
| 37 | uiOwnership: ownership, |
| 38 | ownsUI: surfaceFence.ownsUnknown, |
| 39 | resumeGoal: ports.resumeGoal, |
| 40 | send: sendDeliveryRecovery, |
| 41 | })); |
| 42 | }); |
| 43 | |
| 44 | return { handleDeliveryContinue }; |
| 45 | } |
| 46 |