【契约影响】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 分支兜底走
朋友圈微信,与原项目完全等价。
163 lines
7.2 KiB
Swift
163 lines
7.2 KiB
Swift
//
|
||
// WechatShare.swift
|
||
// ylgamehall
|
||
//
|
||
// 微信分享 SharePlatform 实现 + 大厅专用 shareLobby() 路径。
|
||
//
|
||
// 两条路径对应原 msext 两个 ViewController 中同名 handler 的差异行为:
|
||
//
|
||
// • share() — 对齐 daoqi msext `WechatShareManager.shareWithContent:`
|
||
// (子游戏 gameController.m 活路径)2 type 分支:
|
||
// - type == "2" → 截图分享(thumb = app icon)
|
||
// - else → 链接分享(thumb = app icon)
|
||
//
|
||
// • shareLobby() — 对齐 daoqi msext `NewRootVC.m:471-534` 3 type 分支:
|
||
// - type == "1" → 链接分享(thumb = app icon;原 msext
|
||
// 用 sharelogo.png,按用户决定 fallback 到 app icon)
|
||
// - type == "2" → 截图分享(thumb = 截图 40% 缩放)
|
||
// - 其他 → 远端图分享(NSData 直发 + thumb = 远端图 40% 缩放)
|
||
//
|
||
// fire-and-forget:H5 端的 sharesuccess 已在 FriendsShareHandler 立即触发,
|
||
// 此处不再回传结果(与原 dispatch_after 1s completion(YES) 实质等价)。
|
||
//
|
||
|
||
import Foundation
|
||
import UIKit
|
||
|
||
@MainActor
|
||
public final class WechatShare: SharePlatform {
|
||
|
||
public static let shared = WechatShare()
|
||
|
||
public let name = "WeChat"
|
||
|
||
public var isInstalled: Bool {
|
||
WXApi.isWXAppInstalled()
|
||
}
|
||
|
||
public init() {}
|
||
|
||
public func share(_ content: ShareContent, scene: ShareScene) {
|
||
guard WXApi.isWXAppInstalled() else { return }
|
||
|
||
let wxScene: WeChatManager.ShareScene = (scene == .timeline) ? .timeline : .session
|
||
let thumb = Self.appIconImage()
|
||
|
||
Task { @MainActor in
|
||
do {
|
||
if content.type == "2" {
|
||
// 截图分享(msext WechatShareManager isScreenshotShare 分支)
|
||
let shot = try ImageProvider.captureScreenshot()
|
||
guard let imageData = shot.jpegData(compressionQuality: 0.6) else { return }
|
||
try await WeChatManager.shared.shareImage(
|
||
.init(
|
||
imageData: imageData,
|
||
thumb: thumb,
|
||
messageExt: content.desc,
|
||
mediaTagName: "\(Self.appTagPrefix)游戏截图分享"
|
||
),
|
||
scene: wxScene
|
||
)
|
||
} else {
|
||
// 链接分享(msext else 分支,含 type=="1" 与任何其它值)
|
||
try await WeChatManager.shared.shareLink(
|
||
.init(
|
||
url: content.webpageUrl,
|
||
title: content.title,
|
||
desc: content.desc,
|
||
thumb: thumb,
|
||
mediaTagName: "\(Self.appTagPrefix)游戏分享"
|
||
),
|
||
scene: wxScene
|
||
)
|
||
}
|
||
} catch {
|
||
// SDK 回包失败不向 H5 反馈(sharesuccess 已乐观发出,对齐原项目)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - 大厅路径(NewRootVC.m)
|
||
|
||
/// 大厅页 H5 调 friendsShare 的微信分享路径,对齐 msext NewRootVC.m
|
||
/// :471-534 完整 3 分支结构。直发微信无 SharePanel。
|
||
public func shareLobby(_ content: ShareContent, scene: ShareScene) {
|
||
guard WXApi.isWXAppInstalled() else { return }
|
||
|
||
let wxScene: WeChatManager.ShareScene = (scene == .timeline) ? .timeline : .session
|
||
let appIcon = Self.appIconImage()
|
||
|
||
Task { @MainActor in
|
||
do {
|
||
switch content.type {
|
||
case "1":
|
||
// 链接分享:原 msext 用 sharelogo.png;用户决定 fallback 到 app icon
|
||
try await WeChatManager.shared.shareLink(
|
||
.init(
|
||
url: content.webpageUrl,
|
||
title: content.title,
|
||
desc: content.desc,
|
||
thumb: appIcon,
|
||
mediaTagName: "\(Self.appTagPrefix)游戏下载链接"
|
||
),
|
||
scene: wxScene
|
||
)
|
||
case "2":
|
||
// 截图分享:thumb = 截图 40% 缩放(对齐 msext imageByScalingAndCroppingForSize:0.4x)
|
||
let shot = try ImageProvider.captureScreenshot()
|
||
guard let imageData = shot.jpegData(compressionQuality: 0.6) else { return }
|
||
try await WeChatManager.shared.shareImage(
|
||
.init(
|
||
imageData: imageData,
|
||
thumb: ImageProvider.scaledThumb(shot, scale: 0.4),
|
||
messageExt: content.desc,
|
||
mediaTagName: "\(Self.appTagPrefix)游戏截图分享"
|
||
),
|
||
scene: wxScene
|
||
)
|
||
default:
|
||
// 远端图分享(type == "" / "3" / 其他):下载 NSData 直发 +
|
||
// thumb = 远端图 40% 缩放。messageExt/mediaTagName 都是固定
|
||
// 字面(msext NewRootVC.m:530 字面,非 H5 desc)
|
||
guard let url = URL(string: content.webpageUrl) else { return }
|
||
let (data, _) = try await URLSession.shared.data(from: url)
|
||
guard let image = UIImage(data: data) else { return }
|
||
try await WeChatManager.shared.shareImage(
|
||
.init(
|
||
imageData: data,
|
||
thumb: ImageProvider.scaledThumb(image, scale: 0.4),
|
||
messageExt: "\(Self.appTagPrefix)公众号二维码分享",
|
||
mediaTagName: "\(Self.appTagPrefix)公众号二维码分享"
|
||
),
|
||
scene: wxScene
|
||
)
|
||
}
|
||
} catch {
|
||
// 与子游戏路径同样吞掉错误(sharesuccess 已乐观发出)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - 共享常量 / 工具
|
||
|
||
/// msext WechatShareManager 字面常量 "进贤聚友棋牌"(与 daoqi
|
||
/// SGDefineInfo.h gamehallname 同源),用于 WXMediaMessage.mediaTagName 拼接。
|
||
private static let appTagPrefix = "进贤聚友棋牌"
|
||
|
||
/// app icon 缩略图。读 Info.plist `CFBundleIcons` → `CFBundlePrimaryIcon`
|
||
/// → `CFBundleIconFiles` 的最后一个(最高分辨率),与原 msext
|
||
/// WechatShareManager `getAppIconImage` 等价。失败兜底返回 1x1 透明图。
|
||
private static func appIconImage() -> UIImage {
|
||
if let icons = Bundle.main.object(forInfoDictionaryKey: "CFBundleIcons") as? [String: Any],
|
||
let primary = icons["CFBundlePrimaryIcon"] as? [String: Any],
|
||
let files = primary["CFBundleIconFiles"] as? [String],
|
||
let last = files.last,
|
||
let icon = UIImage(named: last) {
|
||
return icon
|
||
}
|
||
if let icon = UIImage(named: "AppIcon") { return icon }
|
||
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1))
|
||
return renderer.image { _ in }
|
||
}
|
||
}
|