From 2e6bdc5e4e14c23b60fdc0d8d02fd4947ec86cf5 Mon Sep 17 00:00:00 2001 From: Benson Margulies Date: Wed, 8 Apr 2026 12:27:58 -0400 Subject: [PATCH 1/4] some repairs from claude. --- FreeScaler.xcodeproj/project.pbxproj | 38 ++++++++++++++++--- FreeScaler/DropView.swift | 3 +- .../FSMainWindowController.swift | 10 ++--- FreeScaler/Upscaler.swift | 24 ++++++++---- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/FreeScaler.xcodeproj/project.pbxproj b/FreeScaler.xcodeproj/project.pbxproj index a9aba80..0f5f31d 100644 --- a/FreeScaler.xcodeproj/project.pbxproj +++ b/FreeScaler.xcodeproj/project.pbxproj @@ -433,13 +433,26 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = FreeScaler/FreeScaler.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=macosx*]" = RNLG254GCK; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; + ENABLE_APP_SANDBOX = YES; + ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readonly; + ENABLE_FILE_ACCESS_PICTURE_FOLDER = readonly; ENABLE_HARDENED_RUNTIME = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; + ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; + ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; + ENABLE_RESOURCE_ACCESS_CALENDARS = NO; + ENABLE_RESOURCE_ACCESS_CAMERA = NO; + ENABLE_RESOURCE_ACCESS_CONTACTS = NO; + ENABLE_RESOURCE_ACCESS_LOCATION = NO; + ENABLE_RESOURCE_ACCESS_PRINTING = NO; + ENABLE_RESOURCE_ACCESS_USB = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.photography"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; @@ -454,7 +467,7 @@ PRODUCT_BUNDLE_IDENTIFIER = it.murus.FreeScaler; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "FreeScaler DeveloperID"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; @@ -466,13 +479,26 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = FreeScaler/FreeScaler.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=macosx*]" = RNLG254GCK; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; + ENABLE_APP_SANDBOX = YES; + ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readonly; + ENABLE_FILE_ACCESS_PICTURE_FOLDER = readonly; ENABLE_HARDENED_RUNTIME = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; + ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; + ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; + ENABLE_RESOURCE_ACCESS_CALENDARS = NO; + ENABLE_RESOURCE_ACCESS_CAMERA = NO; + ENABLE_RESOURCE_ACCESS_CONTACTS = NO; + ENABLE_RESOURCE_ACCESS_LOCATION = NO; + ENABLE_RESOURCE_ACCESS_PRINTING = NO; + ENABLE_RESOURCE_ACCESS_USB = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.photography"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; @@ -487,7 +513,7 @@ PRODUCT_BUNDLE_IDENTIFIER = it.murus.FreeScaler; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "FreeScaler DeveloperID"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; diff --git a/FreeScaler/DropView.swift b/FreeScaler/DropView.swift index c931cf1..97be321 100644 --- a/FreeScaler/DropView.swift +++ b/FreeScaler/DropView.swift @@ -17,8 +17,7 @@ class DropView: NSView { required init?(coder: NSCoder) { super.init(coder: coder) - //self.wantsLayer = true - //self.layer?.backgroundColor = NSColor.gray.cgColor + self.wantsLayer = true registerForDraggedTypes([NSPasteboard.PasteboardType.URL, NSPasteboard.PasteboardType.fileURL]) } diff --git a/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift b/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift index c726a04..333008b 100644 --- a/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift +++ b/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift @@ -23,8 +23,12 @@ class FSMainWindowController: NSWindowController { // show main window NSApplication.shared.activate(ignoringOtherApps: true) self.window?.makeKeyAndOrderFront(nil) + // load model after the window is on screen + DispatchQueue.main.async { + self.setupModelFromPath(path: selectedModelPath) + } } - + override func windowDidLoad() { super.windowDidLoad() // set droplabelview @@ -34,10 +38,6 @@ class FSMainWindowController: NSWindowController { self.droplabelview.layer?.borderWidth = 1 self.droplabelview.layer?.borderColor = NSColor.tertiaryLabelColor.cgColor self.droplabelview.layer?.masksToBounds = true - // setup upscale model at start - print("setting up model at start...") - self.setupModelFromPath(path: selectedModelPath) - } diff --git a/FreeScaler/Upscaler.swift b/FreeScaler/Upscaler.swift index ecd453d..0b732d8 100644 --- a/FreeScaler/Upscaler.swift +++ b/FreeScaler/Upscaler.swift @@ -42,20 +42,30 @@ class Upscaler : NSObject { self.conf.computeUnits = cUnits ?? (useNeuralEngine ? aneOption : .cpuAndGPU) // model - let classificationModel = try! MLModel(contentsOf: URL(fileURLWithPath: path), configuration: self.conf) + guard let classificationModel = try? MLModel(contentsOf: URL(fileURLWithPath: path), configuration: self.conf) else { + DispatchQueue.main.async { + let alert = NSAlert() + alert.messageText = "Failed to load model" + alert.informativeText = "Could not load model from \(path)" + alert.runModal() + } + return + } if let visionModel = try? VNCoreMLModel(for: classificationModel) { self.visionModel = visionModel self.request = VNCoreMLRequest(model: visionModel) self.request?.imageCropAndScaleOption = .scaleFill self.request?.usesCPUOnly = false - + UserDefaults.standard.set(path, forKey: "selectedModelPath") - + } else { - let alert = NSAlert() - alert.messageText = "Invalid model" - alert.informativeText = "Unable to use model from \(path)\n\n" - alert.runModal() + DispatchQueue.main.async { + let alert = NSAlert() + alert.messageText = "Invalid model" + alert.informativeText = "Unable to use model from \(path)" + alert.runModal() + } } } From 05fccdd5f826fbd7ca869f064113d300cd5e836d Mon Sep 17 00:00:00 2001 From: Benson Margulies Date: Wed, 8 Apr 2026 12:46:24 -0400 Subject: [PATCH 2/4] more repairs. --- FreeScaler/DropView.swift | 4 ++ .../FSMainWindowController.swift | 47 +++++++++++++++---- FreeScaler/Upscaler.swift | 1 + 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/FreeScaler/DropView.swift b/FreeScaler/DropView.swift index 97be321..c540227 100644 --- a/FreeScaler/DropView.swift +++ b/FreeScaler/DropView.swift @@ -25,6 +25,10 @@ class DropView: NSView { super.draw(dirtyRect) } + override func hitTest(_ point: NSPoint) -> NSView? { + return nil + } + override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { print("dragging entered") self.layer?.backgroundColor = self.tcolor diff --git a/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift b/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift index 333008b..e51c921 100644 --- a/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift +++ b/FreeScaler/GUI/Main Window Controller/FSMainWindowController.swift @@ -42,21 +42,52 @@ class FSMainWindowController: NSWindowController { // MARK: SetUp CoreML Model - + func setupModelFromPath(path:String) { - // show wait window - self.waitprogr.startAnimation(nil) - self.waitlabel.stringValue = "Loading \(URL(fileURLWithPath: path).lastPathComponent) CoreML model, please wait..." - self.window?.beginSheet(self.waitwin) - - // load model + showLoadingOverlay(message: "Loading \(URL(fileURLWithPath: path).lastPathComponent)…") DispatchQueue.global().async { Upscaler.shared.setupUpscaleModelFromPath(path: path) DispatchQueue.main.async { - self.window?.endSheet(self.waitwin) + self.hideLoadingOverlay() } } } + + private func showLoadingOverlay(message: String) { + guard let contentView = self.window?.contentView else { return } + let overlay = NSView(frame: contentView.bounds) + overlay.autoresizingMask = [.width, .height] + overlay.identifier = NSUserInterfaceItemIdentifier("loadingOverlay") + overlay.wantsLayer = true + overlay.layer?.backgroundColor = NSColor.windowBackgroundColor.withAlphaComponent(0.9).cgColor + + let spinner = NSProgressIndicator() + spinner.style = .spinning + spinner.translatesAutoresizingMaskIntoConstraints = false + spinner.startAnimation(nil) + + let label = NSTextField(labelWithString: message) + label.translatesAutoresizingMaskIntoConstraints = false + label.alignment = .center + + let stack = NSStackView(views: [spinner, label]) + stack.orientation = .vertical + stack.spacing = 8 + stack.translatesAutoresizingMaskIntoConstraints = false + + overlay.addSubview(stack) + NSLayoutConstraint.activate([ + stack.centerXAnchor.constraint(equalTo: overlay.centerXAnchor), + stack.centerYAnchor.constraint(equalTo: overlay.centerYAnchor), + ]) + contentView.addSubview(overlay) + } + + private func hideLoadingOverlay() { + self.window?.contentView?.subviews + .filter { $0.identifier?.rawValue == "loadingOverlay" } + .forEach { $0.removeFromSuperview() } + } diff --git a/FreeScaler/Upscaler.swift b/FreeScaler/Upscaler.swift index 0b732d8..6ebf5dd 100644 --- a/FreeScaler/Upscaler.swift +++ b/FreeScaler/Upscaler.swift @@ -67,6 +67,7 @@ class Upscaler : NSObject { alert.runModal() } } + print("Done setting up model") } From 09652806caaefc8f0f5739fa3915b70509f9ac1e Mon Sep 17 00:00:00 2001 From: Benson Margulies Date: Wed, 8 Apr 2026 12:56:33 -0400 Subject: [PATCH 3/4] add ignorance. --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ From d7343ed8bc8d2784ce16f87747c80f43f926466a Mon Sep 17 00:00:00 2001 From: Benson Margulies Date: Wed, 8 Apr 2026 19:41:47 -0400 Subject: [PATCH 4/4] more warning removal. --- FreeScaler/AppDelegate.swift | 75 ++++++++++++- FreeScaler/Base.lproj/MainMenu.xib | 174 ----------------------------- 2 files changed, 74 insertions(+), 175 deletions(-) diff --git a/FreeScaler/AppDelegate.swift b/FreeScaler/AppDelegate.swift index 96326f0..159422b 100644 --- a/FreeScaler/AppDelegate.swift +++ b/FreeScaler/AppDelegate.swift @@ -31,9 +31,82 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { - func applicationDidFinishLaunching(_ aNotification: Notification) { self.startFreeScaler() } + func applicationDidFinishLaunching(_ aNotification: Notification) { + buildMainMenu() + self.startFreeScaler() + } func applicationWillTerminate(_ aNotification: Notification) { } func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { return true } + + @objc func showCustomModelsDirInFinder(_ sender: Any) { + createCustomModelsDirectoryIfNeeded() + NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: customModelsPath).absoluteURL]) + } + + // MARK: - Main Menu (built programmatically to avoid XIB loading inconsistencies) + + private func buildMainMenu() { + let mainMenu = NSMenu() + + // App menu + let appMenuItem = NSMenuItem() + let appMenu = NSMenu() + appMenu.addItem(withTitle: "About FreeScaler", action: #selector(NSApplication.orderFrontStandardAboutPanel(_:)), keyEquivalent: "") + appMenu.addItem(.separator()) + let servicesItem = NSMenuItem(title: "Services", action: nil, keyEquivalent: "") + let servicesMenu = NSMenu(title: "Services") + servicesItem.submenu = servicesMenu + NSApp.servicesMenu = servicesMenu + appMenu.addItem(servicesItem) + appMenu.addItem(.separator()) + appMenu.addItem(withTitle: "Hide FreeScaler", action: #selector(NSApplication.hide(_:)), keyEquivalent: "h") + let hideOthersItem = appMenu.addItem(withTitle: "Hide Others", action: #selector(NSApplication.hideOtherApplications(_:)), keyEquivalent: "h") + hideOthersItem.keyEquivalentModifierMask = [.command, .option] + appMenu.addItem(withTitle: "Show All", action: #selector(NSApplication.unhideAllApplications(_:)), keyEquivalent: "") + appMenu.addItem(.separator()) + appMenu.addItem(withTitle: "Quit FreeScaler", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q") + appMenuItem.submenu = appMenu + mainMenu.addItem(appMenuItem) + + // File menu + let fileMenuItem = NSMenuItem() + let fileMenu = NSMenu(title: "File") + fileMenu.addItem(withTitle: "Import…", action: #selector(FSMainWindowController.clickImport(_:)), keyEquivalent: "i") + fileMenu.addItem(.separator()) + fileMenu.addItem(withTitle: "Close", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w") + fileMenu.addItem(.separator()) + fileMenu.addItem(withTitle: "Show Custom Models In Finder", action: #selector(showCustomModelsDirInFinder(_:)), keyEquivalent: "") + fileMenuItem.submenu = fileMenu + mainMenu.addItem(fileMenuItem) + + // Edit menu + let editMenuItem = NSMenuItem() + let editMenu = NSMenu(title: "Edit") + editMenu.addItem(withTitle: "Undo", action: Selector(("undo:")), keyEquivalent: "z") + let redoItem = editMenu.addItem(withTitle: "Redo", action: Selector(("redo:")), keyEquivalent: "z") + redoItem.keyEquivalentModifierMask = [.command, .shift] + editMenu.addItem(.separator()) + editMenu.addItem(withTitle: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x") + editMenu.addItem(withTitle: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c") + editMenu.addItem(withTitle: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v") + editMenu.addItem(withTitle: "Delete", action: #selector(NSText.delete(_:)), keyEquivalent: "") + editMenu.addItem(withTitle: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a") + editMenuItem.submenu = editMenu + mainMenu.addItem(editMenuItem) + + // Window menu + let windowMenuItem = NSMenuItem() + let windowMenu = NSMenu(title: "Window") + windowMenu.addItem(withTitle: "Minimize", action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent: "m") + windowMenu.addItem(withTitle: "Zoom", action: #selector(NSWindow.performZoom(_:)), keyEquivalent: "") + windowMenu.addItem(.separator()) + windowMenu.addItem(withTitle: "Bring All to Front", action: #selector(NSApplication.arrangeInFront(_:)), keyEquivalent: "") + windowMenuItem.submenu = windowMenu + NSApp.windowsMenu = windowMenu + mainMenu.addItem(windowMenuItem) + + NSApp.mainMenu = mainMenu + } } diff --git a/FreeScaler/Base.lproj/MainMenu.xib b/FreeScaler/Base.lproj/MainMenu.xib index df640ab..4d85882 100644 --- a/FreeScaler/Base.lproj/MainMenu.xib +++ b/FreeScaler/Base.lproj/MainMenu.xib @@ -13,179 +13,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -