// // SharePanel.swift // ylgamehall // // 原生分享面板:底部弹出三选一(微信好友 / QQ / 抖音)。 // // 与 msext SharePanel.m 等价行为: // - 半透明黑底覆盖全屏,点击空白区关闭 // - 内容视图从屏幕底部滑入,0.25s 动画 // - 三个圆形按钮 + label,等间距居中布局 // - 点击按钮后先 dismiss 再触发对应 SharePlatform.share // // Phase 4.B 阶段:UI 完整 + 调用 SharePlatform stub; // Phase 4.C/4.D 阶段:SharePlatform 升级为真实 URL Scheme 实现,本类不变。 // import UIKit import os.log @MainActor public final class SharePanel: UIView { private static let log = Logger(subsystem: "ylgamehall", category: "SharePanel") private static let panelHeight: CGFloat = 150 private static let buttonSize: CGFloat = 60 private static let animationDuration: TimeInterval = 0.25 private let content: ShareContent private let contentView = UIView() public init(content: ShareContent) { self.content = content super.init(frame: UIScreen.main.bounds) backgroundColor = UIColor(white: 0, alpha: 0) setupUI() } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) is not supported") } // MARK: - 公共入口 /// 弹出分享面板。fire-and-forget:sharesuccess 已在 FriendsShareHandler 立即触发, /// 用户取消(点空白)或选好平台后不再向 H5 回报结果。 public static func show(content: ShareContent) { guard let window = topWindow() else { return } let panel = SharePanel(content: content) window.addSubview(panel) panel.animateIn() } private static func topWindow() -> UIWindow? { UIApplication.shared.connectedScenes .compactMap { $0 as? UIWindowScene } .flatMap(\.windows) .first { $0.isKeyWindow } } // MARK: - UI 装配 private func setupUI() { // 半透明背景手势 let tap = UITapGestureRecognizer(target: self, action: #selector(handleBackgroundTap(_:))) addGestureRecognizer(tap) // 内容视图(屏幕底部,初始 Y 在屏幕外) let screen = UIScreen.main.bounds contentView.frame = CGRect(x: 0, y: screen.height, width: screen.width, height: Self.panelHeight) contentView.backgroundColor = .white let mask = CAShapeLayer() mask.path = UIBezierPath( roundedRect: contentView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10) ).cgPath contentView.layer.mask = mask addSubview(contentView) // 三个按钮 + label 等间距居中布局 let buttonsContainer = UIView(frame: CGRect(x: 0, y: 30, width: screen.width, height: 110)) contentView.addSubview(buttonsContainer) let buttons: [(title: String, platform: SharePlatform, imageName: String)] = [ ("微信", WechatShare.shared, "shareWechat"), ("QQ", QQShare.shared, "shareQQ"), ("抖音", DouyinShare.shared, "shareDouyin") ] let totalButtonsWidth = Self.buttonSize * CGFloat(buttons.count) let spacing = (screen.width - totalButtonsWidth) / CGFloat(buttons.count + 1) for (index, b) in buttons.enumerated() { let x = spacing + CGFloat(index) * (Self.buttonSize + spacing) let button = UIButton(type: .custom) button.frame = CGRect(x: x, y: 0, width: Self.buttonSize, height: Self.buttonSize) button.setImage(UIImage(named: b.imageName), for: .normal) button.imageView?.contentMode = .scaleAspectFit button.layer.cornerRadius = Self.buttonSize / 2 button.clipsToBounds = true button.alpha = b.platform.isInstalled ? 1.0 : 0.4 button.tag = index button.addTarget(self, action: #selector(handleButtonTap(_:)), for: .touchUpInside) buttonsContainer.addSubview(button) let label = UILabel(frame: CGRect(x: x, y: Self.buttonSize + 8, width: Self.buttonSize, height: 20)) label.text = b.title label.textAlignment = .center label.font = .systemFont(ofSize: 13) label.textColor = .darkGray buttonsContainer.addSubview(label) } } // MARK: - 动画 private func animateIn() { UIView.animate(withDuration: Self.animationDuration) { self.backgroundColor = UIColor(white: 0, alpha: 0.5) var frame = self.contentView.frame frame.origin.y = UIScreen.main.bounds.height - Self.panelHeight self.contentView.frame = frame } } private func dismiss(then action: (() -> Void)? = nil) { UIView.animate(withDuration: Self.animationDuration, animations: { self.backgroundColor = UIColor(white: 0, alpha: 0) var frame = self.contentView.frame frame.origin.y = UIScreen.main.bounds.height self.contentView.frame = frame }, completion: { _ in self.removeFromSuperview() action?() }) } // MARK: - 事件 @objc private func handleBackgroundTap(_ gesture: UITapGestureRecognizer) { let point = gesture.location(in: self) if !contentView.frame.contains(point) { dismiss() } } @objc private func handleButtonTap(_ sender: UIButton) { let platforms: [SharePlatform] = [WechatShare.shared, QQShare.shared, DouyinShare.shared] let platform = platforms[sender.tag] let scene: ShareScene = content.sharefriend == "2" ? .timeline : .friend let snapshotContent = content dismiss { [weak platform] in guard let platform else { return } Self.log.debug("share via \(platform.name, privacy: .public)") platform.share(snapshotContent, scene: scene) } } }