【契约影响】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
82 lines
3.2 KiB
Swift
82 lines
3.2 KiB
Swift
//
|
||
// WechatShare.swift
|
||
// ylgamehall
|
||
//
|
||
// 微信分享 SharePlatform 实现,1:1 对齐 daoqi msext WechatShareManager
|
||
// `shareWithContent:completion:`(仅两个分支):
|
||
// - type == "2" → 截图分享(getImageWithFullScreenshot + JPEG 0.6 + sendImageData)
|
||
// - else → 链接分享(sendLinkURL + webpageUrl + title + desc)
|
||
//
|
||
// 缩略图:app icon(与原 `[self getAppIconImage]` 同源策略,不用 sharelogo)。
|
||
//
|
||
// 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),
|
||
scene: wxScene
|
||
)
|
||
} else {
|
||
// 链接分享(msext else 分支,含 type=="1" 与任何其它值)
|
||
try await WeChatManager.shared.shareLink(
|
||
.init(
|
||
url: content.webpageUrl,
|
||
title: content.title,
|
||
desc: content.desc,
|
||
thumbnailURL: nil
|
||
),
|
||
scene: wxScene
|
||
)
|
||
}
|
||
} catch {
|
||
// SDK 回包失败不向 H5 反馈(sharesuccess 已乐观发出,对齐原项目)
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 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 }
|
||
}
|
||
}
|