Commit Graph
4 Commits
Author SHA1 Message Date
joywayerandClaude Opus 4.7 aa80aec18c Phase 4.A:登录+分享 stub + QQ 改走 URL Scheme 不依 SDK
按用户约定调整 Phase 4 方向:微信继续走 SDK(等项目方提供),QQ 分享
改用 URL Scheme 直接调起 QQ app,**不依赖 SDK**。

调研 daoqi/msext/Class/Utils/QQShareManager.m 发现已有完整的 URL Scheme
fallback 路径:
  - line 14: __has_include(<TencentOpenAPI/QQApiInterface.h>) 条件编译
  - line 231 注释: "Fallback: 使用 URL Scheme (mqqapi://) - 无需 SDK,
    直接调起 (Legacy)"
  - mqqapi://share/to_fri / mqqapi://share/to_qzone / mqqopensdkfriend://share
    等 schema 实现见 line 733/786/789

新增 handler stub(让 H5 启动 / 业务期调登录 / 分享不报 "no handler"):
  - Source/Bridge/Handlers/AccreditLoginHandler.swift
    accreditlogin cb "Response from accreditlogin"
    完整实现需 Phase 4.B 微信 SDK + WeChatManager.authorize() + WeChatAuth.exchangeForUser
    + bridge.call("sharelogin", 7 字段含大写 Province) 反向 callback
  - Source/Bridge/Handlers/FriendsShareHandler.swift
    friendsSharetypeUrlToptitleDescript cb "sharefriend"
    完整实现需 ShareCenter 策略分发 + sharesuccess 反向 callback

WebContainer.registerBridgeHandlers 接入。

文档调整:
  - Plan §2.3 阻塞表:QQ OpenSDK 标"不需要",改 URL Scheme 路径
  - Plan §5 Phase 4 前置:去掉 QQ OpenSDK 一行
  - Plan §5 Phase 4.2:完整改写为 URL Scheme 方案,含 LSApplicationQueriesSchemes
    清单 + URL 构造样例 + "调起即 success" 乐观策略说明
  - Plan §8 进度追踪:4.2 QQ SDK Vendor 标"不需要"
  - Plan §6.4 里程碑加 3 行(前两轮 commit hash 补 + 本次)
  - CLAUDE.md 依赖管理段加 "不接入 QQ SDK" 约定(与"不引入 CocoaPods"
    并列的负面清单)
  - Verification-Checklist Phase 4 章节:E.19/E.20 stub + K/L 待 4.B/4.C
    完整后填充验证项

BuildProject 通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 19:19:23 +08:00
joywayerandClaude Opus 4.7 0602b9d4b6 Phase 3.A:srcIsloop 本地音频 + 3.B/3.C/3.D handler stub
3.A 本地音频完整落地(与 msext NewRootVC initJSdata 等价):

  Source/Audio/AudioPlayer.swift(@MainActor 状态机):
    - playOnce(url) 单次按钮音;buttonPlayers 数组保活池避免多次点击
      互相打断(duration + 0.5s 后清理)
    - loopBackground(url, type:) 循环背景音;numberOfLoops = -1 +
      backgroundType 记录用于同名停止
    - stopBackground(type:) 同名校验后才停止(msext 同款语义)

  Source/Bridge/Handlers/LocalAudioHandler.swift:
    - 注册 srcIsloop handler(@MainActor enum)
    - 入参 src + isloop,按 0/1/-1 分支调 AudioPlayer.shared 对应方法
    - audioFileURL 路径:{Caches}/{gamedir}/{gamestart}/assets/wav/{src}
      与 msext NewRootVC 路径约定 1:1(H5 zip 内 assets/wav 子目录)
    - audioFileURL 标 nonisolated 因 SandboxPaths 是 nonisolated 静态
    - cb 字面 "Response from srcIsloop" 严格保持

  Source/Bridge/Handlers/RemoteAudioHandler.swift(3.B/3.C/3.D stub):
    - prepareaudio + mediaTypeAudio 仅 cb 维持契约,无真实业务
    - 待 Phase 3.B(opencore-amr .a 接入)+ 3.C(七牛 SPM + token)+
      3.D(远端播放)完整后升级
    - 按 CLAUDE.md 原则 A:H5 调啥就得有人接,即使是 stub

WebContainerViewController.registerBridgeHandlers 接入:
  - LocalAudioHandler.register(完整实现)
  - RemoteAudioHandler.register(stub)

Plan §5 Phase 3.1 勾选;3.2 真机验证留待 H5 提供音频文件后做。

Verification-Checklist.md 新增 Phase 3 章节:
  - H. 本地音频(E.14-E.16 srcIsloop 三个 isloop 值)
  - I. prepareaudio / mediaTypeAudio stub(E.17 E.18)

BuildProject 通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 19:11:34 +08:00
joywayerandClaude Opus 4.7 d38ff0f8c4 Phase 2.A:大厅 8 个简单 handler 落地 + BridgeData 加 nonisolated
闭合 Phase 1.17 联调最后一公里(解决 Xcode 日志 4 个 "no handler registered"
+ 提前落地 4 个无外部依赖的简单 handler)。

新增 7 个 handler 模块(Source/Bridge/Handlers/):
  - ClipboardHandler.swift           §3.1 [13][14]剪贴板 UIPasteboard.general
  - ShakeHandler.swift               §3.1 [7][8][9]摇一摇 + §3.2 [5]shakeEnd 反向
                                       canShake / canVoice 状态 + motionEnded 转发钩子
  - VoicePlayingHandler.swift        §3.1 [6]actor VoiceCenter.shared 开关位
  - DeviceInfoHandler.swift          §3.1 [21]+ §3.2 [1]getphoneInfo 大写 I 入、
                                       getphoneinfo 小写 i 出反向 callback
                                       DeviceInfoSnapshot 6 字段(IDFA 用 idfv 兜底,
                                       CLAUDE.md 不接 ATT/IDFA)
  - BrowserHandler.swift             §3.1 [16]UIApplication.open async(Task @MainActor
                                       异步打开,闭包先 cb 不等 open 完成)
  - OpenSaomaHandler.swift           §3.1 [22]空 stub(契约要求注册)
  - StartLocationHandler.swift       §3.1 [20]Phase 5 完整实现,Phase 2 stub

扩展 VibratorHandler.swift:
  - §3.1 [10]vibrator(原有)+ [11]repeatvibrator(msext RootVC.m:1820 沿用:
    实际单次 vibrate 不真循环)+ [12]canclevibrator

BridgeProtocol.swift BridgeData 加 nonisolated:
  - 项目默认 SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor 让 BridgeData 跨 actor
    访问被拦;asString / asDouble / asInt / asBool / asArray / asObject /
    subscript 全部标 nonisolated(纯值类型本就该是 isolation-free)
  - 影响所有 @Sendable async handler 闭包内的 data?.asXxx 访问

WebContainerViewController 接入:
  - 加 private let shakeHandler = ShakeHandler() 持有
  - registerBridgeHandlers() 注册 8 个 handler 模块
  - 加 canBecomeFirstResponder = true + viewDidAppear becomeFirstResponder
  - 加 motionEnded(_:with:) 转发到 shakeHandler.handleMotionEnded
    (motion 检测必需 first responder,否则不触发)

BuildProject 通过。重装 app 后 H5 启动应不再报 "no handler registered" 错误。

Plan §5 Phase 2.A 全部勾选(含 startlocation bonus stub + BridgeData
nonisolated 重构)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 18:38:00 +08:00
joywayerandClaude Opus 4.7 6c943e2924 Phase 1.15:VibratorHandler 单次振动 handler
新增 ylgamehall/Source/Bridge/Handlers/VibratorHandler.swift:
- 无状态 public enum VibratorHandler,static func register(on:)
- 入参忽略(参考原 msext RootVC.m:1816-1818:time 参数实际不读取)
- 副作用:AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
- responseCallback:.string("vibrator"),与契约 §3.1 [10]一致
- 模拟器无振动硬件、调用静默忽略;真机才能感知

WebContainerViewController.viewDidLoad 新增 registerBridgeHandlers()
单一聚合点,Phase 2+ 在此追加更多 handler,便于发现 / 调试。

repeatvibrator / canclevibrator 严格守住 Plan §5 Phase 2.2 范围,不
提前实现。

BuildProject 通过

Plan 进度已勾选(§5 Phase 1.15 + §8)

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