// // FriendsShareHandler.swift // ylgamehall // // H5 → Native handler:friendsSharetypeUrlToptitleDescript — 分享 // 契约:docs/H5-Native-Contract.md §3.1 [2] + §3.2 [11]sharesuccess // // **页面 mode 区分**(与原 msext 两个 ViewController 各注册一份且行为不同对齐): // - `.lobby` 对应 NewRootVC.m:直发微信,3 type 分支(链接 / 截图 / 远端图) // - `.subGame` 对应 gameController.m 活路径:SharePanel 三选一 + 朋友圈兜底 // // 公共流程(无论 mode): // 1. responseCallback("sharefriend") // 2. 立即 bridge.call("sharesuccess", { success:"2", type: }) // (**有意为之**:调用分享接口即视为成功;URL Scheme / 剪贴板路径本就无返回) // 3. 按 mode 异步 fire-and-forget 拉起 UI // // 各平台 SDK 依赖: // - 微信:通过 WeChatManager(已接入 1.8.2 SDK) // - QQ + 抖音:不依赖 SDK,走 URL Scheme + 剪贴板(CLAUDE.md ADR-006) // import Foundation @MainActor public enum FriendsShareHandler { /// 注册时机的页面 mode。 public enum Mode: Sendable { /// 大厅页:H5 在 WebContainer 调 friendsShare 时直发微信 case lobby /// 子游戏页:H5 在 SubGame 调 friendsShare 时弹 SharePanel 或朋友圈兜底 case subGame } public static func register(on bridge: any BridgeProtocol, mode: Mode) { // 【2】friendsSharetypeUrlToptitleDescript // 入参:sharefriend / sharetype / type / webpageUrl / title / description // cb: "sharefriend"(msext 字面,沿用) // 反向 callback:sharesuccess({ success: "2", type: sharefriend 原值 }) bridge.register("friendsSharetypeUrlToptitleDescript") { [weak bridge] data, callback in // 1. responseCallback —— msext 字面 "sharefriend" callback?(.string("sharefriend")) guard let obj = data?.asObject else { return } let content = ShareContent( // 缺失默认空串 → ShareCenter default 分支兜底(与原 msext [nil intValue]==0 等价) sharefriend: obj["sharefriend"]?.asString ?? "", sharetype: obj["sharetype"]?.asString ?? "", type: obj["type"]?.asString ?? "", webpageUrl: obj["webpageUrl"]?.asString ?? "", title: obj["title"]?.asString ?? "", desc: obj["description"]?.asString ?? "" ) await MainActor.run { // 2. 立即触发 sharesuccess —— 有意为之:调用即视为成功 bridge?.call( "sharesuccess", data: .object([ "success": .string("2"), "type": .string(content.sharefriend) ]), callback: nil ) // 3. fire-and-forget 拉起真实分享 UI(按页面 mode 选路径) switch mode { case .lobby: ShareCenter.dispatchLobby(content) case .subGame: ShareCenter.dispatchSubGame(content) } } } } }