Files
youle_app_ios_v2/ylgamehall/Source/Bridge/Handlers/FriendsShareHandler.swift
T
joywayerandClaude Opus 4.7 2ad4563d16 Phase 4.B:SharePlatform 框架 + SharePanel 三选一 UI + ShareCenter 分发
按 msext gameController.m:575-597 / SharePanel.m 模式落地分享框架。

新增 Source/Share/:
  - SharePlatform.swift:
    * SharePlatform 协议(name / isInstalled / share async → ShareResult)
    * ShareContent struct(nonisolated Sendable,6 字段 sharefriend/sharetype/
      type/webpageUrl/title/desc)
    * ShareResult enum (success / cancelled / notInstalled / failed)
    * ShareScene enum (friend / timeline)
  - SharePanel.swift:
    * @MainActor UIView,半透明黑底覆盖全屏 + 底部圆角内容视图滑入
    * 三按钮(微信绿 / QQ 蓝 / 抖音黑)+ label 等间距居中布局
    * 已安装平台按钮高亮,未装置灰
    * 点击空白区 dismiss + completion(.cancelled)
    * 点击按钮 dismiss + 触发对应 SharePlatform.share + completion(result)
    * 0.25s 滑入/滑出动画
    * 与 msext SharePanel.m 等价行为
  - ShareCenter.swift:
    * sharefriend == "1" → SharePanel.show 三选一
    * sharefriend == "2" → WechatShare.share scene: .timeline 朋友圈
    * 与 msext gameController.m:585 行为 1:1
  - WechatShare.swift:stub(Phase 4.E 等微信 SDK 接入)
  - QQShare.swift:stub + canOpenURL("mqqapi://") 检测(Phase 4.C 升级
    URL Scheme 真实调起)
  - DouyinShare.swift:stub + canOpenURL("snssdk1128://") 检测(Phase 4.D 升级
    URL Scheme + Photos)

FriendsShareHandler 升级:
  - 入参解析为 ShareContent
  - 调 ShareCenter.dispatch
  - completion 内根据 result 触发 sharesuccess 反向 callback:
    * success / cancelled → bridge.call("sharesuccess", {success:"2", type:sharefriend})
    * notInstalled / failed → 不发(H5 业务期 timeout 后自行 fallback,msext 乐观策略)

ShareContent 标 nonisolated 解 Swift 6 actor 隔离(项目默认 MainActor isolation
让 struct 跨 actor 受限)。

BuildProject 通过

Plan §5 Phase 4.2 勾选

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 20:02:34 +08:00

65 lines
2.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// FriendsShareHandler.swift
// ylgamehall
//
// H5 → Native handlerfriendsSharetypeUrlToptitleDescript — 分享
// 契约:docs/H5-Native-Contract.md §3.1 2 + §3.2 11sharesuccess
//
// 完整流程(与 msext gameController.m:575-597 等价):
// 1. 入参解析 ShareContent
// 2. ShareCenter.dispatch
// - sharefriend == "1" → SharePanel 三选一(微信好友 / QQ / 抖音)
// - sharefriend == "2" → 直接 WechatShare 朋友圈
// 3. 分享完成 → bridge.call("sharesuccess", { success: "2", type: <sharefriend 原值> })
//
// 各平台 SDK 依赖:
// - 微信:Phase 4.E 接入项目方 SDK(当前 WechatShare 是 stub
// - QQ + 抖音:不依赖 SDK,走 URL SchemePhase 4.C/4.D 真实落地,当前 stub
//
import Foundation
@MainActor
public enum FriendsShareHandler {
public static func register(on bridge: any BridgeProtocol) {
// 【2】friendsSharetypeUrlToptitleDescript
// 入参:sharefriend / sharetype / type / webpageUrl / title / description
// cb: "sharefriend"msext 字面,沿用)
// 反向 callbacksharesuccess({ success: "2", type: sharefriend 原值 })
bridge.register("friendsSharetypeUrlToptitleDescript") { [weak bridge] data, callback in
callback?(.string("sharefriend"))
guard let obj = data?.asObject else { return }
let content = ShareContent(
sharefriend: obj["sharefriend"]?.asString ?? "1",
sharetype: obj["sharetype"]?.asString ?? "",
type: obj["type"]?.asString ?? "1",
webpageUrl: obj["webpageUrl"]?.asString ?? "",
title: obj["title"]?.asString ?? "",
desc: obj["description"]?.asString ?? ""
)
let sharefriend = content.sharefriend
await MainActor.run {
ShareCenter.dispatch(content) { result in
// success / cancelled / notInstalled / failed — msext 行为:
// 只要不是明确失败就发 sharesuccess(乐观策略,URL Scheme 无返回)
switch result {
case .success, .cancelled:
bridge?.call("sharesuccess",
data: .object([
"success": .string("2"),
"type": .string(sharefriend)
]),
callback: nil)
case .notInstalled, .failed:
// 不发 sharesuccessH5 业务期 timeout 后自行 fallback
break
}
}
}
}
}
}