Files
youle_app_ios_v2/ylgamehall/Source/Share/WechatShare.swift
T
2026-06-30 17:40:54 +08:00

198 lines
7.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.
//
// WechatShare.swift
// ylgamehall
//
// 微信分享 SharePlatform 实现:剪贴板 + 引导框 + `weixin://` URL Scheme
// 与 QQShare / DouyinShare 同款交互模式,**不依赖微信 OpenSDK 的分享 API**。
//
// 设计取舍:
// - 微信 OpenSDK 的 sendReq 走"专有剪贴板 plist + AppID 后台白名单",与
// QQ / 抖音的"明文 URL Scheme"开放策略不同;为统一三方分享交互体验、
// 减少 SDK 协议变更带来的不稳定,分享路径改走剪贴板 + 手动粘贴。
// - 微信 OpenSDK 二进制依然保留(WeChatSDK.register / WeChatAuth.authorize
// 用于登录),仅去掉分享 SDK 调用与 WeChatManager 中的分享桥接。
// - scene 参数(friend / timeline)保留以满足 SharePlatform 协议契约,但
// 剪贴板路径下用户进微信后自行决定粘贴到对话框还是朋友圈,文案统一不分。
//
// 两条对外入口对应两个 ViewController 同名 handler 的差异(仅剪贴板内容分支不同):
//
// • share() — 子游戏路径(gameController.m),2 type 分支:
// - type == "2" → 截图:UIPasteboard.image
// - else → 链接:UIPasteboard.string
//
// • shareLobby() — 大厅路径(NewRootVC.m),3 type 分支:
// - type == "1" → 链接
// - type == "2" → 截图
// - 其他 → 远端图(下载 → UIPasteboard.image
//
// fire-and-forgetH5 端 sharesuccess 已在 FriendsShareHandler 立即触发,
// 此处不再回传结果。
//
import Foundation
import UIKit
import os.log
@MainActor
public final class WechatShare: SharePlatform {
public static let shared = WechatShare()
private static let log = Logger(subsystem: "ylgamehall", category: "WechatShare")
private static let wechatScheme = "weixin://"
public let name = "WeChat"
public var isInstalled: Bool {
guard let url = URL(string: Self.wechatScheme) else { return false }
return UIApplication.shared.canOpenURL(url)
}
public init() {}
// MARK: - 子游戏路径(gameController.m
public func share(_ content: ShareContent, scene: ShareScene) {
guard isInstalled else { return }
if content.type == "2" {
shareScreenshot()
} else {
shareLink(content)
}
}
// MARK: - 大厅路径(NewRootVC.m
public func shareLobby(_ content: ShareContent, scene: ShareScene) {
guard isInstalled else { return }
switch content.type {
case "1":
shareLink(content)
case "2":
shareScreenshot()
default:
shareRemoteImage(content)
}
}
// MARK: - 截图分享
/// 截图 → UIPasteboard.image → 弹引导框(不自动拉起微信,等用户点"立即打开")。
private func shareScreenshot() {
do {
let shot = try ImageProvider.captureScreenshot()
UIPasteboard.general.image = shot
Self.log.debug("WechatShare 截图已复制到剪贴板")
} catch {
Self.log.error("WechatShare 截图失败 \(error.localizedDescription, privacy: .public)")
return
}
let message = """
✅ 图片已复制到剪贴板
🎯 分享到好友、群聊或朋友圈步骤:
1️⃣ 打开微信,选择好友、群聊或朋友圈
2️⃣ 在输入框长按粘贴图片
3️⃣ 点击发送即可分享
"""
showGuidanceAlert(title: "微信分享准备完成", message: message)
}
// MARK: - 链接分享
/// title + desc + url 拼字符串 → UIPasteboard.string → 弹引导框。
/// 三字段均空时用兜底文案"来自进贤聚友棋牌的精彩内容分享"(与 DouyinShare 同款策略)。
private func shareLink(_ content: ShareContent) {
var parts: [String] = []
if !content.title.isEmpty { parts.append(content.title) }
if !content.desc.isEmpty { parts.append(content.desc) }
if !content.webpageUrl.isEmpty { parts.append(content.webpageUrl) }
let shareText = parts.isEmpty
? "来自进贤聚友棋牌的精彩内容分享"
: parts.joined(separator: "\n")
UIPasteboard.general.string = shareText
Self.log.debug("WechatShare 链接已复制到剪贴板")
let message = """
✅ 内容已复制到剪贴板
🎯 分享到好友、群聊或朋友圈步骤:
1️⃣ 打开微信,选择好友、群聊或朋友圈
2️⃣ 在输入框长按粘贴内容
3️⃣ 点击发送即可分享
"""
showGuidanceAlert(title: "微信分享准备完成", message: message)
}
// MARK: - 远端图分享(大厅 shareLobby 的"其他"分支)
/// 下载远端图 → UIPasteboard.image → 弹引导框。对齐 msext NewRootVC.m:526-534
/// "公众号二维码分享"分支:原 SDK 路径直发 NSData,剪贴板路径写入解码后的
/// UIImage 让用户在微信里长按粘贴。
private func shareRemoteImage(_ content: ShareContent) {
guard let url = URL(string: content.webpageUrl) else {
Self.log.error("WechatShare 远端图 URL 解析失败")
return
}
Task { @MainActor in
do {
let (data, _) = try await URLSession.shared.data(from: url)
guard let image = UIImage(data: data) else {
Self.log.error("WechatShare 远端图解码失败")
return
}
UIPasteboard.general.image = image
Self.log.debug("WechatShare 远端图已复制到剪贴板")
} catch {
Self.log.error("WechatShare 远端图下载失败 \(error.localizedDescription, privacy: .public)")
return
}
let message = """
✅ 图片已复制到剪贴板
🎯 分享到好友、群聊或朋友圈步骤:
1️⃣ 打开微信,选择好友、群聊或朋友圈
2️⃣ 在输入框长按粘贴图片
3️⃣ 点击发送即可分享
"""
showGuidanceAlert(title: "微信分享准备完成", message: message)
}
}
// MARK: - 引导弹窗
/// 弹"立即打开微信 / 稍后分享"二选一 Alert,与 QQShare / DouyinShare 同款 UX。
private func showGuidanceAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "立即打开微信", style: .default) { _ in
if let url = URL(string: Self.wechatScheme),
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
})
alert.addAction(UIAlertAction(title: "稍后分享", style: .cancel))
guard let topVC = Self.topViewController() else { return }
topVC.present(alert, animated: true)
}
private static func topViewController() -> UIViewController? {
let scene = UIApplication.shared.connectedScenes
.compactMap { $0 as? UIWindowScene }
.first(where: { $0.activationState == .foregroundActive })
?? UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first
guard var top = scene?.windows.first(where: \.isKeyWindow)?.rootViewController
?? scene?.windows.first?.rootViewController else { return nil }
while let presented = top.presentedViewController { top = presented }
if let nav = top as? UINavigationController, let visible = nav.visibleViewController {
return visible
}
return top
}
}