Commit Graph
6 Commits
Author SHA1 Message Date
joywayer 0636aadbec 4.B 修复:friendsShare 路由跑偏(sharefriend/type 字段兼容 number)
【契约影响】docs/H5-Native-Contract.md §3.1[2]

H5 实际传:{"sharefriend":1, "sharetype":0, "type":2, ...}(number 而非
契约描述的 string "1"/"2")。先前用 obj["sharefriend"]?.asString 只匹配
.string case,遇到 number 全部 fallback 到 "",导致:

- sharefriend = "" → ShareCenter.dispatchSubGame default 分支 →
  WechatShare.share(scene: .timeline) → **错走朋友圈**
- type = "" → WechatShare.share else 分支 → **错走链接分享**

实际 H5 意图:sharefriend=1 (好友/弹 SharePanel) + type=2 (截图分享)。
看到的现象:H5 想截图分享给好友,实际成了链接分享到朋友圈。

修复:sharefriend / sharetype / type 改用 asLooseString(number → 整数
字符串,与 commit b058990 修 mediaTypeAudio.user 同款)。对齐原 msext
ObjC 行为:[NSNumber intValue] 与 [NSString intValue] 都得到整数,所以
不论 H5 传 string 还是 number 都能识别。

webpageUrl / title / description 三项 H5 始终传 string,保持 asString
不变。
2026-06-24 09:16:27 +08:00
joywayer a1332ed942 4.B FriendsShareHandler 加调试日志:原始 JSON + 解析字段 + 分发 mode
H5 调用分享接口时,按以下顺序输出到 Console(subsystem=ylgamehall,
category=FriendsShare):

  ← H5 friendsShare mode=lobby raw={"sharefriend":"1",...}
  friendsShare parsed:
    sharefriend = "1"  (1=好友/SharePanel, 2/其他=朋友圈)
    sharetype   = "1"  (1/2=微信, 3=闲聊;新外壳忽略)
    type        = "1"  (1=链接, 2=截图, 其他=远端图)
    webpageUrl  = "https://..."
    title       = "..."
    description = "..."
  → H5 sharesuccess fired: success="2", type="1"
  dispatch → lobby (直发微信 3 type 分支)

raw 字段直接 JSONSerialization 序列化整个 BridgeData,含 H5 传入的所有
键(不限于上面解析的 6 项),便于排查 H5 端偷偷加字段或类型漂移。
2026-06-24 09:07:36 +08:00
joywayer 5d4bdc2e29 4.B 分享按页面 mode 拆分:大厅直发微信 3 分支 / 子游戏 SharePanel
【契约影响】docs/H5-Native-Contract.md §3.1[2]

原 msext 把 friendsSharetypeUrlToptitleDescript 同名 handler 在两个 VC
各注册一份且**行为完全不同**:

- NewRootVC.m(大厅):直发微信,3 type 分支
    type==1 sendLinkURL(sharelogo 缩略图)
    type==2 sendImageData(截图 40% 缩放为 thumb)
    其他    NSData fromURL → sendImageData(公众号二维码场景)
- gameController.m(子游戏,活路径,早 return):
    sharefriend==1 SharePanel 三选一
    其他           WechatShareManager 朋友圈兜底(2 分支:截图/链接)

先前新外壳两个 VC 都注册同一份 handler 走"子游戏"逻辑,导致大厅页:
1. 强行弹 SharePanel 多一步操作
2. 丢失"远端图"分支(公众号二维码被错当链接发)

按页面 mode 拆开:

- FriendsShareHandler 加 Mode { lobby, subGame } 参数
- ShareCenter 拆 dispatchLobby(直发微信)/ dispatchSubGame(SharePanel)
- WechatShare 加 shareLobby() 实现完整 3 type 分支:
    type==1 → shareLink + mediaTagName "游戏下载链接" + appIcon thumb
              (原 msext 用 sharelogo.png,按用户决定 fallback 到 app icon)
    type==2 → shareImage + mediaTagName "游戏截图分享" + 截图 0.4x thumb
              + messageExt = H5 description
    其他    → URLSession 下载 NSData 直发 + 远端图 0.4x thumb
              + mediaTagName/messageExt 固定字面"公众号二维码分享"
- WebContainerViewController 注册 .lobby;SubGameViewController .subGame

附带修 sharefriend 默认值:之前 ?? "1"(弹面板)与原 msext nil→[intValue]
==0→朋友圈微信不一致。改成 ?? "",由 ShareCenter default 分支兜底走
朋友圈微信,与原项目完全等价。
2026-06-24 08:19:21 +08:00
joywayer 9bd5a81e6c 4.B 分享逻辑对齐 daoqi msext:调用即触发 sharesuccess
【契约影响】docs/H5-Native-Contract.md §3.1[2]/§3.2[11]

H5 端 sharesuccess 时机改为"调用 friendsShare handler 即立刻发",与
原 msext 行为等价(live path 完全不等 SDK / URL Scheme 回包)。用户
明示有意为之:URL Scheme + 剪贴板路径本就没有可靠回包,乐观策略避免
H5 业务卡住。

3 平台分支严格 1:1 对齐 daoqi msext:

WechatShare(对齐 WechatShareManager shareWithContent)
  - type=="2" → 截图 JPEG 0.6 + sendImageData + app icon thumb
  - else      → 链接分享 sendLinkURL + app icon thumb
  - 移除原"远端图"分支(原项目无此分支)
  - 新增 appIconImage helper(读 Info.plist CFBundleIcons,对齐
    [self getAppIconImage])

QQShare(对齐 QQShareManager shareWithContent + simpleShareToQQFriend)
  - type=="2" → 截图 → UIPasteboard.image → 4 URL Scheme fallback
  - else      → mqqapi://share/to_{fri,qzone}?req_type=1&url=...
                &title=...&description=...(webpageUrl 空时 req_type=0)
  - 不依赖 QQ SDK(CLAUDE.md ADR-006)

DouyinShare(对齐 DouyinShareManager shareWithContent)
  - type=="2" → 截图 → UIPasteboard.image → "立即打开抖音"引导框
  - else      → title+"\n\n"+desc → UIPasteboard.string → 引导框
                双侧空时兜底 "来自进贤聚友棋牌的精彩内容分享"
  - 放弃之前的"存相册 + 自动拉起"激进路径,回到原项目"用户主动点"路径

架构调整:
- SharePlatform.share 改 sync fire-and-forget(去 ShareResult 返回)
- ShareCenter.dispatch / SharePanel.show 去 completion 参数
- FriendsShareHandler:解析后先发 responseCallback("sharefriend")
  与 sharesuccess({success:"2", type:<sharefriend>}),再异步 dispatch
2026-06-24 07:34:03 +08:00
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
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