feat(flow): on-demand host handoff with reliable return and a back-tap tip

Keyboard
- Only jump to the app when the voice surface is shown (tab tap / opened
  there); typing tabs no longer leave the host on keyboard open.
- Wait up to 0.4 s for the arbiter to report the host app before leaving,
  and late-bind an id that arrives within 6 s of the jump.
- Empty arbiter callbacks no longer wipe an already captured host id;
  install the capture handler in every build configuration.

App
- Return to the previous app with up to four retries using iOS's real
  open result, and honor the skip-app-switch preference.
- Keep the pending host id across cold-start zombie reconciliation, and
  expire it after two minutes (legacy values without a timestamp stay valid).
- Show a light tip pointing at the system back control when we cannot
  return automatically ("点击返回,立即使用").

Tests: TTL behaviour and return retry policy.
This commit is contained in:
Rocky
2026-10-29 16:32:52 +08:00
parent 4dce67df84
commit e09ad34437
17 changed files with 454 additions and 63 deletions
@@ -19,7 +19,8 @@ typedef void (^OSGHostArbiterCaptureHandler)(NSString *_Nullable bundleId, NSStr
/// 钩子是否已成功安装(私有类或方法不存在时为 NO)。
@property (class, nonatomic, readonly) BOOL isInstalled;
/// 最近一次回调读到的宿主 bundle ID;回调读不到或已作废时为 nil。线程安全。
/// 最近一次回调读到的有效宿主 bundle ID;从未读到或已作废时为 nil。线程安全。
/// 读不到 ID 的空回调不会清掉它,只有 invalidateCapturedBundleId 会。
@property (class, nonatomic, readonly, nullable) NSString *lastCapturedBundleId;
/// 作废上一次的识别结果(键盘收起时调用,避免把上一个宿主当成当前宿主)。