+
+ @NSApplicationDelegateAdaptor(CapturaAppDelegate.self) var appDelegate
+
+ var body: some Scene {
+ WindowGroup {
+ PreferencesScreen()
+ .handlesExternalEvents(
+ preferring: Set(arrayLiteral: "PreferencesScreen"), allowing: Set(arrayLiteral: "*")
+ )
+ .frame(width: 650, height: 450)
+ }
+ .handlesExternalEvents(matching: Set(arrayLiteral: "PreferencesScreen"))
+ //.modelContainer(for: CapturaRemoteFile.self)
+ }
+}
+
+@objc(CapturaAppDelegate) class CapturaAppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate
+{
+
+ @Environment(\.openURL) var openURL
+ var statusItem: NSStatusItem!
+ var captureState: CaptureState = .idle
+ var recordingWindow: RecordingWindow? = nil
+ var preferencesWindow: PreferencesWindow? = nil
+ var boxListener: AnyCancellable? = nil
+ var popover: NSPopover? = nil
+ var helpShown = false
+ var captureSession: CapturaCaptureSession? = nil
+ var images: [CGImage] = []
+ var outputFile: CapturaFile? = nil
+ var gifCallbackTimer = ContinuousClock.now
+ var pixelDensity: CGFloat = 1.0
+ var stopTimer: DispatchWorkItem?
+ var remoteFiles: [CapturaRemoteFile] = []
+ var captureSessionConfiguration: CaptureSessionConfiguration = CaptureSessionConfiguration()
+
+ // Sparkle Configuration
+ @IBOutlet var checkForUpdatesMenuItem: NSMenuItem!
+ let updaterController: SPUStandardUpdaterController = SPUStandardUpdaterController(
+ startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
+
+ @objc dynamic var scriptedPreferences: ScriptedPreferences = ScriptedPreferences()
+
+ func applicationDidFinishLaunching(_ notification: Notification) {
+ setupStatusBar()
+ NotificationCenter.default.addObserver(
+ self,
+ selector: #selector(self.didReceiveNotification(_:)),
+ name: nil,
+ object: nil)
+ closeWindow()
+ fetchRemoteItems()
+ }
+
+ // MARK: - Setup Functions
+
+ private func setupStatusBar() {
+ statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
+
+ if let button = statusItem.button {
+ if let image = NSImage(named: "MenuBar/Idle") {
+ image.isTemplate = true
+ image.size = NSSize(width: 18, height: 18)
+ button.image = image
+ }
+ }
+
+ statusItem.isVisible = true
+ statusItem.menu = NSMenu()
+ statusItem.menu?.delegate = self
+
+ // Create the Popover
+ popover = NSPopover()
+ popover?.contentViewController = HelpPopoverViewController()
+ popover?.behavior = .transient
+
+ setupMenu()
+ }
+
+ private func setupMenu() {
+
+ statusItem.menu?.removeAllItems()
+
+ statusItem.menu?.addItem(
+ NSMenuItem(
+ title: "Record", action: #selector(CapturaAppDelegate.onClickStartRecording),
+ keyEquivalent: ""))
+ if remoteFiles.count > 0 {
+ statusItem.menu?.addItem(NSMenuItem.separator())
+ for remoteFile in remoteFiles {
+ let remoteFileItem = NSMenuItem(
+ title: remoteFile.name, action: #selector(CapturaAppDelegate.onClickRemoteFile),
+ keyEquivalent: "")
+ remoteFileItem.representedObject = remoteFile
+ statusItem.menu?.addItem(remoteFileItem)
+ }
+ }
+ statusItem.menu?.addItem(NSMenuItem.separator())
+ statusItem.menu?.addItem(
+ NSMenuItem(
+ title: "Open Local Folder", action: #selector(CapturaAppDelegate.onOpenFolder),
+ keyEquivalent: ""))
+ statusItem.menu?.addItem(NSMenuItem.separator())
+
+ checkForUpdatesMenuItem = NSMenuItem(
+ title: "Check for Updates",
+ action: #selector(SPUStandardUpdaterController.checkForUpdates(_:)), keyEquivalent: "")
+ checkForUpdatesMenuItem.target = updaterController
+ statusItem.menu?.addItem(checkForUpdatesMenuItem)
+
+ statusItem.menu?.addItem(
+ NSMenuItem(
+ title: "Preferences", action: #selector(CapturaAppDelegate.onOpenPreferences),
+ keyEquivalent: ""))
+ statusItem.menu?.addItem(
+ NSMenuItem(title: "Quit", action: #selector(CapturaAppDelegate.onQuit), keyEquivalent: ""))
+ }
+
+ private func closeWindow() {
+ if let window = NSApplication.shared.windows.first {
+ window.close()
+ }
+ }
+
+ // MARK: - URL Event Handler
+
+ func application(_ application: NSApplication, open urls: [URL]) {
+ if CapturaSettings.shouldAllowURLAutomation {
+ for url in urls {
+ if let action = CapturaURLDecoder.decodeParams(url: url) {
+ switch action {
+ case let .configure(config):
+ NotificationCenter.default.post(
+ name: .setConfiguration, object: nil,
+ userInfo: [
+ "config": config
+ ])
+ case let .record(config):
+ NotificationCenter.default.post(
+ name: .setCaptureSessionConfiguration, object: nil,
+ userInfo: [
+ "config": config
+ ])
+ NotificationCenter.default.post(name: .startAreaSelection, object: nil, userInfo: nil)
+ }