Open With and title cleanup

This commit is contained in:
Beingpax 2025-09-05 11:22:14 +05:45
parent 8cc3b76972
commit 12c850f77b
7 changed files with 39 additions and 93 deletions

View File

@ -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)";

View File

@ -7,7 +7,7 @@
"location" : "https://github.com/FluidInference/FluidAudio",
"state" : {
"branch" : "main",
"revision" : "abf7d9ef3f53a693e3721069071971eff84c002f"
"revision" : "052cbb27cf073a9407251d74ef3459ea258e41b3"
}
},
{

View File

@ -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
}

View File

@ -48,34 +48,3 @@
</array>
</dict>
</plist>
<!-- Somewhere near the existing keys -->
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Audio/Video File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.audio</string>
<string>public.movie</string>
</array>
<key>CFBundleTypeExtensions</key>
<array>
<string>wav</string>
<string>mp3</string>
<string>m4a</string>
<string>aiff</string>
<string>mp4</string>
<string>mov</string>
<string>aac</string>
<string>flac</string>
<string>caf</string>
</array>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,28 @@
import Foundation
import UniformTypeIdentifiers
struct SupportedMedia {
static let extensions: Set<String> = [
"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
}
}

View File

@ -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

View File

@ -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)
}
}
}