按 msext gameController.m:637-678 字面行为,WechatShare 按 content.type 分发: - type=1 → shareLink(已有) - type=2 → captureScreenshot → JPEG 0.6 + thumb 0.4x → shareImage - type=其它 → downloadRemote(URL) → JPEG 0.9 + thumb 0.4x → shareImage 新增: - ImageProvider.scaledThumb(_:scale:):等价 msext FuncPublic imageByScalingAndCroppingForSize 0.4x 缩放;微信 SDK setThumbImage: 内部再压到 32KB - WeChatManager.ShareImage 结构 + shareImage(_:scene:) 异步包装 (WXImageObject + WXMediaMessage.setThumbImage,FIFO 串行复用 sharePending) 契约:与 type=1 一致,调成功 → sharesuccess 反向 callback(success/cancelled 都发);errCode=-2 → cancelled;其它 errCode → failed。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
76 lines
2.7 KiB
Swift
76 lines
2.7 KiB
Swift
//
|
||
// ImageProvider.swift
|
||
// ylgamehall
|
||
//
|
||
// 分享场景的图片源 helper:
|
||
// - captureScreenshot() 截当前 keyWindow(与 msext FuncPublic
|
||
// getImageWithFullScreenshot 等价)
|
||
// - downloadRemote(_:) URLSession 异步下载远端图片 URL
|
||
//
|
||
// Phase 4.F 截图 / 远端图分享共用。
|
||
//
|
||
|
||
import UIKit
|
||
|
||
public enum ImageProviderError: Error, Sendable {
|
||
case noKeyWindow
|
||
case downloadFailed(any Error)
|
||
case decodeFailed
|
||
case badURL(String)
|
||
}
|
||
|
||
@MainActor
|
||
public enum ImageProvider {
|
||
|
||
/// 截当前 keyWindow(与 msext `getImageWithFullScreenshot` 等价)。
|
||
/// 返回包含状态栏 + 大厅 letterbox 黑边 + WebView 内容的完整快照。
|
||
public static func captureScreenshot() throws -> UIImage {
|
||
guard let window = UIApplication.shared.connectedScenes
|
||
.compactMap({ $0 as? UIWindowScene })
|
||
.flatMap(\.windows)
|
||
.first(where: { $0.isKeyWindow })
|
||
else {
|
||
throw ImageProviderError.noKeyWindow
|
||
}
|
||
|
||
let renderer = UIGraphicsImageRenderer(bounds: window.bounds)
|
||
return renderer.image { _ in
|
||
window.drawHierarchy(in: window.bounds, afterScreenUpdates: false)
|
||
}
|
||
}
|
||
|
||
/// 等比缩放图片用作微信分享的缩略图源。默认 0.4x 与 msext
|
||
/// `imageByScalingAndCroppingForSize:CGSizeMake(w*0.4, h*0.4)` 等价
|
||
/// (gameController.m:656 / 677 字面常量)。微信 SDK `setThumbImage:`
|
||
/// 内部会再压缩至 32KB,外层只需把图像尺寸压低,避免传 4K 截图过 SDK 时
|
||
/// 内部 JPEG 编码出超大缩略图。
|
||
public static func scaledThumb(_ image: UIImage, scale: CGFloat = 0.4) -> UIImage {
|
||
let target = CGSize(
|
||
width: max(1, image.size.width * scale),
|
||
height: max(1, image.size.height * scale)
|
||
)
|
||
let renderer = UIGraphicsImageRenderer(size: target)
|
||
return renderer.image { _ in
|
||
image.draw(in: CGRect(origin: .zero, size: target))
|
||
}
|
||
}
|
||
|
||
/// 下载远端 URL → UIImage。仅简单 URLSession 同步路径,无重试 / 缓存。
|
||
public static func downloadRemote(_ urlString: String) async throws -> UIImage {
|
||
guard let url = URL(string: urlString) else {
|
||
throw ImageProviderError.badURL(urlString)
|
||
}
|
||
do {
|
||
let (data, _) = try await URLSession.shared.data(from: url)
|
||
guard let image = UIImage(data: data) else {
|
||
throw ImageProviderError.decodeFailed
|
||
}
|
||
return image
|
||
} catch let err as ImageProviderError {
|
||
throw err
|
||
} catch {
|
||
throw ImageProviderError.downloadFailed(error)
|
||
}
|
||
}
|
||
}
|