X-Git-Url: https://git.r.bdr.sh/rbdr/captura/blobdiff_plain/ba17de891507da74fb07423803fd636a4457354c..3472041dfee0a6e8c8a29e949f239bae13e1a18f:/Captura/CapturaApp.swift?ds=inline diff --git a/Captura/CapturaApp.swift b/Captura/CapturaApp.swift index d9c3ff0..14e266c 100644 --- a/Captura/CapturaApp.swift +++ b/Captura/CapturaApp.swift @@ -1,12 +1,11 @@ import SwiftUI -import SwiftData import Cocoa import Combine import AVFoundation @main struct CapturaApp: App { - + @NSApplicationDelegateAdaptor(CapturaAppDelegate.self) var appDelegate var body: some Scene { @@ -20,7 +19,7 @@ struct CapturaApp: App { } } -class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { +@objc(CapturaAppDelegate) class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { @Environment(\.openURL) var openURL var statusItem: NSStatusItem! @@ -39,6 +38,8 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { var remoteFiles: [CapturaRemoteFile] = [] var captureSessionConfiguration: CaptureSessionConfiguration = CaptureSessionConfiguration() + @objc dynamic var scriptedPreferences: ScriptedPreferences = ScriptedPreferences() + func applicationDidFinishLaunching(_ notification: Notification) { setupStatusBar() NotificationCenter.default.addObserver( @@ -57,7 +58,7 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let button = statusItem.button { - button.image = NSImage(systemSymbolName: "rectangle.dashed.badge.record", accessibilityDescription: "Captura") + button.image = NSImage(named: "Idle") } statusItem.isVisible = true @@ -97,20 +98,23 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { window.close() } } - + // MARK: - URL Event Handler func application(_ application: NSApplication, open urls: [URL]) { - print("AAAH OPENING") if (CapturaSettings.shouldAllowURLAutomation) { for url in urls { if let action = CapturaURLDecoder.decodeParams(url: url) { switch action { case let .configure(config): - print("AAAH CONFIGURING \(config)") - CapturaSettings.apply(config) + NotificationCenter.default.post(name: .setConfiguration, object: nil, userInfo: [ + "config": config + ]) case let .record(config): - print(config) + NotificationCenter.default.post(name: .setCaptureSessionConfiguration, object: nil, userInfo: [ + "config": config + ]) + NotificationCenter.default.post(name: .startAreaSelection, object: nil, userInfo: nil) } } } @@ -128,9 +132,14 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { func menuWillOpen(_ menu: NSMenu) { if captureState != .idle { - menu.cancelTracking() + menu.cancelTrackingWithoutAnimation() + if captureState == .selectingArea { + NotificationCenter.default.post(name: .startRecording, object: nil, userInfo: nil) + return + } if captureState == .recording { NotificationCenter.default.post(name: .stopRecording, object: nil, userInfo: nil) + return } } } @@ -197,6 +206,22 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { if let frame = notification.userInfo?["frame"] { receivedFrame(frame as! CVImageBuffer) } + case .setConfiguration: + DispatchQueue.main.async { + if let userInfo = notification.userInfo { + if let config = userInfo["config"] as? ConfigureAction { + self.setConfiguration(config) + } + } + } + case .reloadConfiguration: + reloadConfiguration() + case .setCaptureSessionConfiguration: + if let userInfo = notification.userInfo { + if let config = userInfo["config"] as? RecordAction { + setCaptureSessionConfiguration(config) + } + } case .NSManagedObjectContextObjectsDidChange: DispatchQueue.main.async { self.fetchRemoteItems() @@ -212,11 +237,12 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { helpShown = false if captureState != .selectingArea { captureState = .selectingArea + updateImage() if let button = statusItem.button { let rectInWindow = button.convert(button.bounds, to: nil) let rectInScreen = button.window?.convertToScreen(rectInWindow) NSApp.activate(ignoringOtherApps: true) - recordingWindow = RecordingWindow(rectInScreen) + recordingWindow = RecordingWindow(captureSessionConfiguration, rectInScreen) recordingWindow?.makeKeyAndOrderFront(nil) recordingWindow?.orderFrontRegardless() boxListener = recordingWindow?.recordingContentView.$box @@ -250,7 +276,7 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { stopTimer = DispatchWorkItem { self.stopRecording() } - DispatchQueue.main.asyncAfter(deadline: .now() + 300, execute: stopTimer!) + DispatchQueue.main.asyncAfter(deadline: .now() + Double(captureSessionConfiguration.maxLength), execute: stopTimer!) outputFile = CapturaFile() if captureSessionConfiguration.shouldSaveMp4 { @@ -296,6 +322,7 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { func reset() { captureState = .idle updateImage() + captureSessionConfiguration = CaptureSessionConfiguration() stop() } @@ -305,7 +332,10 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { if now - gifCallbackTimer > .nanoseconds(1_000_000_000 / UInt64(captureSessionConfiguration.frameRate)) { gifCallbackTimer = now DispatchQueue.main.async { - if let cgImage = frame.cgImage?.resize(by: self.pixelDensity) { + if var cgImage = frame.cgImage { + if self.pixelDensity > 1 { + cgImage = cgImage.resize(by: self.pixelDensity) ?? cgImage + } self.images.append(cgImage) } } @@ -324,6 +354,18 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { } } + func setConfiguration(_ config: ConfigureAction) { + CapturaSettings.apply(config) + } + + func reloadConfiguration() { + self.captureSessionConfiguration = CaptureSessionConfiguration() + } + + func setCaptureSessionConfiguration(_ config: RecordAction) { + self.captureSessionConfiguration = CaptureSessionConfiguration(from: config) + } + // MARK: - CoreData private func fetchRemoteItems() { @@ -360,19 +402,23 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { if let button = statusItem.button { let image: String = switch captureState { case .idle: - "rectangle.dashed.badge.record" + "Idle" case .selectingArea: - "circle.rectangle.dashed" + if recordingWindow?.recordingContentView.box != nil { + "Ready to Record" + } else { + "Selecting" + } case .recording: - "checkmark.rectangle" + "Stop Frame 1" case .uploading: - "dock.arrow.up.rectangle" + "Upload Frame 1" case .uploaded: - "checkmark.rectangle.fill" + "OK" case .error: - "xmark.rectangle.fill" + "ERR" } - button.image = NSImage(systemSymbolName: image, accessibilityDescription: "Captura") + button.image = NSImage(named: image) } } @@ -383,7 +429,6 @@ class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate { boxListener?.cancel() recordingWindow?.close() recordingWindow = nil - captureSessionConfiguration = CaptureSessionConfiguration() } private func uploadOrCopy() async -> Bool {