fix(iOS): show recorder errors as full-screen overlay instead of fleeting toast
- Added recorderErrorMessage @Published var for persistent error display - Recording errors now shown as overlay with error details + Dismiss button - presentShareSheet now logs errors and sets recorderErrorMessage on failure - Errors like 'No window scene' or 'No view controller' visible on screen
This commit is contained in:
parent
04fb3acecc
commit
f73bc4532e
@ -440,6 +440,30 @@ struct PlayerContentView: View {
|
||||
// 播放状态指示(loading/buffering/error)
|
||||
PlayerStatusOverlay(bridge: bridge)
|
||||
|
||||
// 录制错误覆盖层(显示在界面上不会一闪而过)
|
||||
#if os(iOS)
|
||||
if let errMsg = bridge.recorderErrorMessage {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.font(.system(size: 36))
|
||||
.foregroundColor(.orange)
|
||||
Text("Recording Error")
|
||||
.font(.headline).foregroundColor(.white)
|
||||
Text(errMsg)
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, 40)
|
||||
Button("Dismiss") {
|
||||
bridge.recorderErrorMessage = nil
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.black.opacity(0.75))
|
||||
}
|
||||
#endif
|
||||
|
||||
// 左上角应用图标 — iOS 锁屏控制 / macOS 切换控制栏
|
||||
MiniPlayerIcon()
|
||||
.frame(width: 32, height: 32)
|
||||
|
||||
@ -124,6 +124,7 @@ final class PlayerBridge: ObservableObject {
|
||||
let hlsRecorder = HLSRecorder()
|
||||
let pipController = PiPController()
|
||||
@Published var pendingExportURL: URL?
|
||||
@Published var recorderErrorMessage: String? // 录制错误直接显示在界面上
|
||||
#endif
|
||||
// 诊断日志
|
||||
private var diagLogURL: URL?
|
||||
@ -178,12 +179,14 @@ final class PlayerBridge: ObservableObject {
|
||||
|
||||
#if os(iOS)
|
||||
hlsRecorder.onRecordingSaved = { [weak self] url in
|
||||
NSLog("[MiniPlayer] onRecordingSaved called: %@", url.lastPathComponent)
|
||||
NSLog("[MiniPlayer] onRecordingSaved: %@", url.lastPathComponent)
|
||||
self?.recorderErrorMessage = nil
|
||||
self?.showToast("Saved: \(url.lastPathComponent)")
|
||||
// 直接用 UIKit present,不依赖 SwiftUI sheet binding
|
||||
self?.presentShareSheet(for: url)
|
||||
}
|
||||
hlsRecorder.onError = { [weak self] msg in
|
||||
NSLog("[MiniPlayer] onError: %@", msg)
|
||||
self?.recorderErrorMessage = msg
|
||||
self?.showToast(msg)
|
||||
}
|
||||
#endif
|
||||
@ -192,22 +195,29 @@ final class PlayerBridge: ObservableObject {
|
||||
#if os(iOS)
|
||||
/// 直接通过 UIKit present UIActivityViewController,绕过 SwiftUI sheet 可能的多 sheet 冲突
|
||||
func presentShareSheet(for url: URL) {
|
||||
NSLog("[MiniPlayer] presentShareSheet: %@", url.lastPathComponent)
|
||||
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 }
|
||||
else {
|
||||
recorderErrorMessage = "No window scene available"
|
||||
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
|
||||
// 录制完成后可以删掉临时文件?不,用户可能需要再次分享
|
||||
guard let presenter = topVC else {
|
||||
recorderErrorMessage = "No view controller to present share sheet"
|
||||
return
|
||||
}
|
||||
topVC?.present(activityVC, animated: true)
|
||||
NSLog("[MiniPlayer] presentShareSheet: presented for %@", url.lastPathComponent)
|
||||
|
||||
let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
||||
activityVC.completionWithItemsHandler = { _, _, _, _ in }
|
||||
presenter.present(activityVC, animated: true)
|
||||
NSLog("[MiniPlayer] presentShareSheet: presented successfully")
|
||||
}
|
||||
|
||||
/// 配置 AVAudioSession,支持后台音频和 PiP
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user