ReviewOS

also looking at this

craft-native/craft

fix(ios): settle a Siri shortcut removal whose completion never comes

#227
Merged glennmichael123 wants to merge fix/ios-siri-removal-deadline into main
7 files +503 -94
packages/ios/fixtures/zig-slice/page.mmodified+37-8
Changes to packages/ios/fixtures/zig-slice/page.m
@@ -64,10 +64,19 @@ const char craft_slice_page[] =
6464 " if (sentSpeechEnd || !e.detail || typeof e.detail !== 'object') { return; }\n"
6565 " sentSpeechEnd = true;\n"
6666 " bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:72});\n"
67 " // Genuinely last: this backgrounds the app, and every chain that needs\n"
68 " // a foreground process has now closed.\n"
69 " bridge.postMessage({t:'mobile', a:'openSettings', i:102});\n"
67 " speechEnded = true;\n"
68 " openSettingsWhenDone();\n"
7069 "});\n"
70 "// Genuinely last: opening Settings backgrounds the app, and a suspended\n"
71 "// app runs neither a framework completion nor a main-queue deadline. So\n"
72 "// this waits for the Siri removal to settle first, by its completion or\n"
73 "// by its 15 s deadline (#211). Before, the removal was often still waiting\n"
74 "// when the app was backgrounded here, and a suspended app never heard it.\n"
75 "function openSettingsWhenDone() {\n"
76 " if (postedSettings || !speechEnded || !siriSettled) { return; }\n"
77 " postedSettings = true;\n"
78 " bridge.postMessage({t:'mobile', a:'openSettings', i:102});\n"
79 "}\n"
7180 "var sentEvent = false;\n"
7281 "var sentRoundTrip = false, sentHandOff = false, sentTierZero = false, sentSecure = false, sentDb = false, sentNotif = false;\n"
7382 "var bridge = window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.craft;\n"
@@ -84,6 +93,8 @@ const char craft_slice_page[] =
8493 "var sentShot = false, sentDeepLink = false;\n"
8594 "var sentOcr = false, sentClassify = false, sentDetect = false;\n"
8695 "var sentAuth = false, sentSiriAdd = false, sentSiriDel = false;\n"
96 "var sentSiriTimeout = false, sentSiriOdd = false, siriSettled = false;\n"
97 "var speechEnded = false, postedSettings = false;\n"
8798 "var sentPdfOpen = false, sentPdfClose = false;\n"
8899 "var sentDownload = false, sentWatch = false, sentSettings = false;\n"
89100 "var sentBtStart = false, sentBtStop = false;\n"
@@ -91,6 +102,19 @@ const char craft_slice_page[] =
91102 "var sentLocationFresh = false, sentLocationCached = false, sentLocationTimeout = false;\n"
92103 "var sentSpeechStart = false, sentSpeechErr = false, sentSpeechEnd = false;\n"
93104 "window.__craftBridgeError = function (ctx) {\n"
105 " // A registration that failed never posts the removal, and a removal\n"
106 " // that was refused or timed out still settles it, so neither can hold\n"
107 " // openSettings back for ever.\n"
108 " if (ctx && ctx.id === 96) { siriSettled = true; openSettingsWhenDone(); }\n"
109 " if (ctx && ctx.id === 97) {\n"
110 " siriSettled = true;\n"
111 " if (ctx.code === 'TIMEOUT') {\n"
112 " if (!sentSiriTimeout) { sentSiriTimeout = true; bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:84}); }\n"
113 " } else if (!sentSiriOdd) {\n"
114 " sentSiriOdd = true; bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:86});\n"
115 " }\n"
116 " openSettingsWhenDone();\n"
117 " }\n"
94118 " // The message crossed Zig's escaping with a backslash, quote, and\n"
95119 " // newline intact; anything mangled and this equality fails, i=7 never\n"
96120 " // fires, and the harness reports the error route broken.\n"
@@ -318,11 +342,16 @@ const char craft_slice_page[] =
318342 " // removeSiriShortcut answers from inside Foundation's completion\n"
319343 " // handler, a void(^)(void) that carries nothing at all — so this reply\n"
320344 " // arriving proves the block fired and its parked payload was delivered\n"
321 " // under the request id captured back at dispatch.\n"
322 " if (!sentSiriDel && action === 'removeSiriShortcut' && payload\n"
323 " && payload.removed === true && payload.action === 'sliceAct') {\n"
324 " sentSiriDel = true;\n"
325 " bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:38});\n"
345 " // under the request id captured back at dispatch. Anything else it\n"
346 " // resolves with is odd (i=86); its deadline arrives as an error (i=84).\n"
347 " if (action === 'removeSiriShortcut' && id === 97) {\n"
348 " siriSettled = true;\n"
349 " if (payload && payload.removed === true && payload.action === 'sliceAct') {\n"
350 " if (!sentSiriDel) { sentSiriDel = true; bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:38}); }\n"
351 " } else if (!sentSiriOdd) {\n"
352 " sentSiriOdd = true; bridge.postMessage({t:'mobile', a:'getDeviceInfo', i:86});\n"
353 " }\n"
354 " openSettingsWhenDone();\n"
326355 " }\n"
327356 " if (!sentOcr && action === 'recognizeText' && Array.isArray(payload)) {\n"
328357 " var joined = payload.map(function (r) { return r.text; }).join(' ').toUpperCase();\n"