fix(iOS): use UIKit UIActivityViewController directly instead of SwiftUI .sheet

SwiftUI multiple .sheet modifiers can conflict — replaced the pendingExportURL
sheet binding with a direct UIKit UIActivityViewController presentation from
the key window's root VC. This bypasses any SwiftUI sheet stack issues.

Also added copyLocalFile() for local file recording (FileManager.copyItem
instead of URLSession.download which fails on file:// URLs).
This commit is contained in:
yumoqing 2026-07-17 21:21:16 +08:00
parent 4aec892151
commit 04fb3acecc

View File

@ -178,10 +178,10 @@ final class PlayerBridge: ObservableObject {
#if os(iOS) #if os(iOS)
hlsRecorder.onRecordingSaved = { [weak self] url in hlsRecorder.onRecordingSaved = { [weak self] url in
NSLog("[MiniPlayer] onRecordingSaved called, setting pendingExportURL: %@", url.lastPathComponent) NSLog("[MiniPlayer] onRecordingSaved called: %@", url.lastPathComponent)
self?.showToast("Saved: \(url.lastPathComponent)") self?.showToast("Saved: \(url.lastPathComponent)")
self?.pendingExportURL = url // 直接用 UIKit present,不依赖 SwiftUI sheet binding
NSLog("[MiniPlayer] pendingExportURL set to: %@", url.lastPathComponent) self?.presentShareSheet(for: url)
} }
hlsRecorder.onError = { [weak self] msg in hlsRecorder.onError = { [weak self] msg in
self?.showToast(msg) self?.showToast(msg)
@ -190,6 +190,26 @@ final class PlayerBridge: ObservableObject {
} }
#if os(iOS) #if os(iOS)
/// 直接通过 UIKit present UIActivityViewController,绕过 SwiftUI sheet 可能的多 sheet 冲突
func presentShareSheet(for url: URL) {
guard let windowScene = UIApplication.shared.connectedScenes
.compactMap({ $0 as? UIWindowScene })
.first(where: { $0.activationState == .foregroundActive })
?? UIApplication.shared.connectedScenes.compactMap({ $0 as? UIWindowScene }).first
else { return }
var topVC = windowScene.keyWindow?.rootViewController
?? windowScene.windows.first(where: { !$0.isHidden && $0.bounds.size != .zero })?.rootViewController
while let presented = topVC?.presentedViewController { topVC = presented }
let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
activityVC.completionWithItemsHandler = { _, _, _, _ in
// 录制完成后可以删掉临时文件?不,用户可能需要再次分享
}
topVC?.present(activityVC, animated: true)
NSLog("[MiniPlayer] presentShareSheet: presented for %@", url.lastPathComponent)
}
/// 配置 AVAudioSession,支持后台音频和 PiP /// 配置 AVAudioSession,支持后台音频和 PiP
private func ensureAudioSession() { private func ensureAudioSession() {
let session = AVAudioSession.sharedInstance() let session = AVAudioSession.sharedInstance()