From 12c850f77b0bedfca4361f53b8ec0f3dde3bf743 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Fri, 5 Sep 2025 11:22:14 +0545 Subject: [PATCH] Open With and title cleanup --- VoiceInk.xcodeproj/project.pbxproj | 8 ++--- .../xcshareddata/swiftpm/Package.resolved | 2 +- VoiceInk/AppDelegate.swift | 6 ++-- VoiceInk/Info.plist | 31 ------------------ VoiceInk/Services/SupportedMedia.swift | 28 ++++++++++++++++ VoiceInk/Views/AudioTranscribeView.swift | 25 ++------------- VoiceInk/Views/ContentView.swift | 32 ++----------------- 7 files changed, 39 insertions(+), 93 deletions(-) create mode 100644 VoiceInk/Services/SupportedMedia.swift diff --git a/VoiceInk.xcodeproj/project.pbxproj b/VoiceInk.xcodeproj/project.pbxproj index f18f690..63a704e 100644 --- a/VoiceInk.xcodeproj/project.pbxproj +++ b/VoiceInk.xcodeproj/project.pbxproj @@ -459,7 +459,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 152; + CURRENT_PROJECT_VERSION = 153; DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\""; DEVELOPMENT_TEAM = V6J6A3VWY2; ENABLE_HARDENED_RUNTIME = YES; @@ -474,7 +474,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.52; + MARKETING_VERSION = 1.53; PRODUCT_BUNDLE_IDENTIFIER = com.prakashjoshipax.VoiceInk; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG ENABLE_NATIVE_SPEECH_ANALYZER $(inherited)"; @@ -493,7 +493,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 152; + CURRENT_PROJECT_VERSION = 153; DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\""; DEVELOPMENT_TEAM = V6J6A3VWY2; ENABLE_HARDENED_RUNTIME = YES; @@ -508,7 +508,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.52; + MARKETING_VERSION = 1.53; PRODUCT_BUNDLE_IDENTIFIER = com.prakashjoshipax.VoiceInk; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "ENABLE_NATIVE_SPEECH_ANALYZER $(inherited)"; diff --git a/VoiceInk.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/VoiceInk.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 886cfcd..2c29478 100644 --- a/VoiceInk.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/VoiceInk.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -7,7 +7,7 @@ "location" : "https://github.com/FluidInference/FluidAudio", "state" : { "branch" : "main", - "revision" : "abf7d9ef3f53a693e3721069071971eff84c002f" + "revision" : "052cbb27cf073a9407251d74ef3459ea258e41b3" } }, { diff --git a/VoiceInk/AppDelegate.swift b/VoiceInk/AppDelegate.swift index 4bc530b..20cd81e 100644 --- a/VoiceInk/AppDelegate.swift +++ b/VoiceInk/AppDelegate.swift @@ -1,5 +1,6 @@ import Cocoa import SwiftUI +import UniformTypeIdentifiers class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { @@ -50,14 +51,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { defaults.removeObject(forKey: "isPowerModeEnabled") } - // Keep in sync with AudioTranscribeView.supportedExtensions - private let supportedExtensions = ["wav", "mp3", "m4a", "aiff", "mp4", "mov", "aac", "flac", "caf"] - // Stash URL when app cold-starts to avoid spawning a new window/tab var pendingOpenFileURL: URL? func application(_ application: NSApplication, open urls: [URL]) { - guard let url = urls.first(where: { supportedExtensions.contains($0.pathExtension.lowercased()) }) else { + guard let url = urls.first(where: { SupportedMedia.isSupported(url: $0) }) else { return } diff --git a/VoiceInk/Info.plist b/VoiceInk/Info.plist index 7584b1c..7833f1f 100644 --- a/VoiceInk/Info.plist +++ b/VoiceInk/Info.plist @@ -48,34 +48,3 @@ - -CFBundleDocumentTypes - - - CFBundleTypeName - Audio/Video File - CFBundleTypeRole - Viewer - LSHandlerRank - Alternate - LSItemContentTypes - - public.audio - public.movie - - CFBundleTypeExtensions - - wav - mp3 - m4a - aiff - mp4 - mov - aac - flac - caf - - - - - diff --git a/VoiceInk/Services/SupportedMedia.swift b/VoiceInk/Services/SupportedMedia.swift new file mode 100644 index 0000000..c66c452 --- /dev/null +++ b/VoiceInk/Services/SupportedMedia.swift @@ -0,0 +1,28 @@ +import Foundation +import UniformTypeIdentifiers + +struct SupportedMedia { + static let extensions: Set = [ + "wav", "mp3", "m4a", "aiff", "mp4", "mov", "aac", "flac", "caf" + ] + + static let contentTypes: [UTType] = [ + .audio, .movie + ] + + static func isSupported(url: URL) -> Bool { + let fileExtension = url.pathExtension.lowercased() + if !fileExtension.isEmpty, extensions.contains(fileExtension) { + return true + } + + if let resourceValues = try? url.resourceValues(forKeys: [.contentTypeKey]), + let contentType = resourceValues.contentType { + return contentTypes.contains(where: { contentType.conforms(to: $0) }) + } + + return false + } +} + + diff --git a/VoiceInk/Views/AudioTranscribeView.swift b/VoiceInk/Views/AudioTranscribeView.swift index d73c8b8..3cebfa0 100644 --- a/VoiceInk/Views/AudioTranscribeView.swift +++ b/VoiceInk/Views/AudioTranscribeView.swift @@ -353,29 +353,8 @@ struct AudioTranscribeView: View { } } - // Validate file type by extension - let supportedExtensions = ["wav", "mp3", "m4a", "aiff", "mp4", "mov", "aac", "flac", "caf"] - let fileExtension = url.pathExtension.lowercased() - - // Check file extension first - if !fileExtension.isEmpty && supportedExtensions.contains(fileExtension) { - print("File type validated by extension: \(fileExtension)") - } else { - print("Unsupported file extension: \(fileExtension)") - // Try to validate by UTType as well - if let resourceValues = try? url.resourceValues(forKeys: [.contentTypeKey]), - let contentType = resourceValues.contentType { - if contentType.conforms(to: .audio) || contentType.conforms(to: .movie) { - print("File type validated by UTType: \(contentType.identifier)") - } else { - print("File does not conform to audio or movie type: \(contentType.identifier)") - return - } - } else { - print("Could not validate file type") - return - } - } + // Validate file type + guard SupportedMedia.isSupported(url: url) else { return } print("File validated successfully: \(url.lastPathComponent)") selectedAudioURL = url diff --git a/VoiceInk/Views/ContentView.swift b/VoiceInk/Views/ContentView.swift index a610b49..4736d4b 100644 --- a/VoiceInk/Views/ContentView.swift +++ b/VoiceInk/Views/ContentView.swift @@ -164,8 +164,7 @@ struct ContentView: View { @State private var hasLoadedData = false let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0" @StateObject private var licenseViewModel = LicenseViewModel() - // Capture the hosting window to update tab/window title dynamically - @State private var hostingWindow: NSWindow? + private var isSetupComplete: Bool { hasLoadedData && @@ -191,13 +190,6 @@ struct ContentView: View { } .navigationSplitViewStyle(.balanced) .frame(minWidth: 940, minHeight: 730) - // Resolve hosting NSWindow and set initial title - .background( - WindowTitleAccessor { window in - self.hostingWindow = window - self.hostingWindow?.title = selectedView.rawValue - } - ) .onAppear { hasLoadedData = true } @@ -237,10 +229,6 @@ struct ContentView: View { print("ContentView: No destination in notification") } } - // Update the tab/window title whenever the active view changes - .onChange(of: selectedView) { newValue in - hostingWindow?.title = newValue.rawValue - } } @ViewBuilder @@ -278,20 +266,4 @@ struct ContentView: View { } } -struct WindowTitleAccessor: NSViewRepresentable { - var onResolve: (NSWindow?) -> Void - - func makeNSView(context: Context) -> NSView { - let view = NSView() - DispatchQueue.main.async { [weak view] in - onResolve(view?.window) - } - return view - } - - func updateNSView(_ nsView: NSView, context: Context) { - DispatchQueue.main.async { [weak nsView] in - onResolve(nsView?.window) - } - } -} +