fix: window close exits app + save dialog diagnostics
- AppDel: use NSWindow.willCloseNotification observer with visibility check instead of broken applicationShouldTerminateAfterLastWindowClosed logic (SwiftUI WindowGroup keeps hidden windows that blocked termination) - finishWriting callback: use DispatchQueue.main.async instead of Task @MainActor (more reliable from non-main-thread AVFoundation callback) - Add extensive NSLog diagnostics: callback invoked, file existence check, file size, status codes, nil checks
This commit is contained in:
parent
cf53afd7c8
commit
eb3e98d567
@ -5,11 +5,37 @@ import SwiftBricks
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
|
||||
// 主窗口关闭时退出应用;辅助面板(播放列表等 NSPanel)关闭不退出
|
||||
// 主窗口关闭时退出应用
|
||||
class AppDel: NSObject, NSApplicationDelegate {
|
||||
private var closeObserver: Any?
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
// 监听所有窗口关闭事件
|
||||
closeObserver = NotificationCenter.default.addObserver(
|
||||
forName: NSWindow.willCloseNotification,
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { _ in
|
||||
// 延迟检查:等当前关闭事件完成后再判断
|
||||
DispatchQueue.main.async {
|
||||
let nonPanelWindows = NSApp.windows.filter { !($0 is NSPanel) && $0.isVisible }
|
||||
NSLog("[MiniPlayer] Window closed. Visible non-panel windows: %d", nonPanelWindows.count)
|
||||
if nonPanelWindows.isEmpty {
|
||||
NSLog("[MiniPlayer] No visible main windows, terminating app")
|
||||
NSApp.terminate(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
// 如果剩余窗口全是 NSPanel(播放列表等),说明主窗口已关闭,应退出
|
||||
return !sender.windows.contains { !($0 is NSPanel) }
|
||||
return true
|
||||
}
|
||||
|
||||
deinit {
|
||||
if let obs = closeObserver {
|
||||
NotificationCenter.default.removeObserver(obs)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -312,8 +312,12 @@ final class PlayerRecorder: NSObject {
|
||||
audioInput?.markAsFinished()
|
||||
|
||||
writer?.finishWriting { [weak self] in
|
||||
Task { @MainActor in
|
||||
guard let self = self, let w = self.writer else { return }
|
||||
NSLog("[Recorder] finishWriting callback invoked")
|
||||
DispatchQueue.main.async {
|
||||
guard let self = self, let w = self.writer else {
|
||||
NSLog("[Recorder] ⚠️ self or writer is nil in finishWriting callback")
|
||||
return
|
||||
}
|
||||
let vFrames = self.captureFrameCount
|
||||
NSLog("[Recorder] finishWriting: status=%d, error=%@, videoFrames=%d, audioFrames=%d",
|
||||
w.status.rawValue,
|
||||
@ -321,9 +325,18 @@ final class PlayerRecorder: NSObject {
|
||||
vFrames, totalAudioFrames)
|
||||
|
||||
if w.status == .completed, let tempURL = self.tempURL {
|
||||
// 弹出保存对话框,用户可改名
|
||||
self.showSaveDialog(tempURL: tempURL)
|
||||
// 检查文件是否存在且有内容
|
||||
if FileManager.default.fileExists(atPath: tempURL.path) {
|
||||
let size = (try? FileManager.default.attributesOfItem(atPath: tempURL.path)[.size] as? UInt64) ?? 0
|
||||
NSLog("[Recorder] ✓ Temp file exists: %@, size=%llu bytes", tempURL.lastPathComponent, size)
|
||||
self.showSaveDialog(tempURL: tempURL)
|
||||
} else {
|
||||
NSLog("[Recorder] ⚠️ Temp file missing: %@", tempURL.path)
|
||||
self.onError?("Recording file missing")
|
||||
}
|
||||
} else {
|
||||
NSLog("[Recorder] ✗ finishWriting failed: status=%d, error=%@",
|
||||
w.status.rawValue, w.error?.localizedDescription ?? "unknown")
|
||||
self.onError?("Recording failed: \(w.error?.localizedDescription ?? "unknown (status=\(w.status.rawValue))")")
|
||||
if let url = self.tempURL {
|
||||
try? FileManager.default.removeItem(at: url)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user