diff --git a/docs/Development-Plan.md b/docs/Development-Plan.md index 499ded2..2d043ee 100644 --- a/docs/Development-Plan.md +++ b/docs/Development-Plan.md @@ -307,8 +307,11 @@ Contract Design Plan(本文档) - `webView(_:didFinish:)` 内 `UIView.animate(withDuration: 0.3)` splash.alpha = 0 → completion 内 `splash.removeFromSuperview()` - 期间 webView 已渲染好 H5 大厅,无白屏闪烁;splash 出 view 层级避免空持有 - BuildProject 通过 -- [ ] **1.15** 实现 `Source/Bridge/Handlers/VibratorHandler.swift` - - `register(_ bridge)` 注册 `vibrator` handler → `AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)` + responseCallback `"vibrator"` +- [x] **1.15** 实现 `Source/Bridge/Handlers/VibratorHandler.swift` + - 无状态 `public enum VibratorHandler`,`static func register(on bridge: any BridgeProtocol)` + - 入参忽略(参考 msext `RootVC.m:1816-1818`:`time` 参数实际不读取) + - 副作用:`AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)`;responseCallback:`.string("vibrator")` + - `WebContainerViewController.viewDidLoad` 新增 `registerBridgeHandlers()` 单一聚合点,Phase 2+ 在此追加。BuildProject 通过 - [ ] **1.16** `SceneDelegate` → `WebContainerViewController` 作 rootViewController - 替换 M0 占位 `RootViewController` - [ ] **1.17** 把渠道目录里临时填入的 demo 值 + 一个 demo H5 跑通 / 真机验证完整 1.10-1.16 链路 @@ -804,7 +807,7 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin - [x] 1.14.c LobbyZipUpgrader 加 progress 回调(URLSessionDownloadDelegate,0.0…1.0) - [x] 1.14.d WebContainerViewController(SplashOverlay + 16:9 letterbox + 启动流水线 + 三种 alert) - [x] 1.14.e WebView didFinish 后 0.3s 淡出 splash + removeFromSuperview -- [ ] 1.15 VibratorHandler +- [x] 1.15 VibratorHandler(单次振动,AudioServicesPlaySystemSound + responseCallback "vibrator") - [ ] 1.16 SceneDelegate → WebContainerViewController - [ ] 1.17 Demo H5 联调 + 真机验证升级路径 diff --git a/ylgamehall/Source/Bridge/Handlers/VibratorHandler.swift b/ylgamehall/Source/Bridge/Handlers/VibratorHandler.swift new file mode 100644 index 0000000..f995507 --- /dev/null +++ b/ylgamehall/Source/Bridge/Handlers/VibratorHandler.swift @@ -0,0 +1,32 @@ +// +// VibratorHandler.swift +// ylgamehall +// +// H5 → Native handler「vibrator」(契约 §3.1 [10]:单次振动)。 +// Phase 1.15 仅实现这一项作为最小垂直闭环验证标的; +// `repeatvibrator` / `canclevibrator` 放到 Phase 2.2 一并补齐。 +// + +import AudioToolbox + +/// 单次振动 handler 注册器。 +/// +/// 设计为无状态 enum:震动调用是无状态的 C API,不需要持有任何资源; +/// 同时避免误把 handler 注册器实例化保留,造成"注册多份"。 +public enum VibratorHandler { + + /// 在 `bridge` 上注册 `vibrator` handler。 + /// + /// 契约(`docs/H5-Native-Contract.md` §3.1 [10]): + /// - 入参:被忽略(参考原 msext `RootVC.m:1816-1818` 入参 `time` 实际不读取) + /// - 副作用:`AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)` + /// - responseCallback:字符串 `"vibrator"` + /// + /// 模拟器无振动硬件,调用会被静默忽略(不抛异常),真机才能感知。 + public static func register(on bridge: any BridgeProtocol) { + bridge.register("vibrator") { _, callback in + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) + callback?(.string("vibrator")) + } + } +} diff --git a/ylgamehall/Source/WebView/WebContainerViewController.swift b/ylgamehall/Source/WebView/WebContainerViewController.swift index a23ab3c..455aee5 100644 --- a/ylgamehall/Source/WebView/WebContainerViewController.swift +++ b/ylgamehall/Source/WebView/WebContainerViewController.swift @@ -40,12 +40,19 @@ public final class WebContainerViewController: UIViewController { setupSplash() bridgedWebView.webView.navigationDelegate = self + registerBridgeHandlers() Task { @MainActor in await runBootPipeline() } } + /// 注册所有 H5 → Native handler。Phase 1.15 仅 `vibrator`; + /// 后续 Phase 2+ 在此追加更多 handler(保持单一聚合点便于发现 / 调试)。 + private func registerBridgeHandlers() { + VibratorHandler.register(on: bridgedWebView.bridge) + } + public override var supportedInterfaceOrientations: UIInterfaceOrientationMask { .landscape } public override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .landscapeRight } public override var prefersStatusBarHidden: Bool { false }