Replaced file_picker's Load/Browse with a custom NativePickerRegistrar Swift plugin that opens NSOpenPanel with showsHiddenFiles = true. The file_picker package hardcodes this to false, making hidden folders like ~/.claude invisible in its dialogs. Changes: - New NativePickerRegistrar.swift: custom NSOpenPanel with hidden files - New NativePicker Dart service using method channel - Browse: only shows folders (canChooseFiles=false), hidden visible - Load: only shows .jsonl files, hidden folders visible - Registered via AppDelegate.applicationDidFinishLaunching - Removed file_picker dependency from home_screen imports - Fixed all info-level lint issues (super params, null-aware, doc comment) - Signed, notarized, stapled DMG
85 lines
3.2 KiB
Swift
85 lines
3.2 KiB
Swift
import Cocoa
|
|
import FlutterMacOS
|
|
import UniformTypeIdentifiers
|
|
|
|
/// Registers a method channel for native file picking with hidden files visible.
|
|
/// Called from Dart via `ensureInitialized`.
|
|
class NativePickerRegistrar: NSObject, FlutterPlugin {
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
let channel = FlutterMethodChannel(
|
|
name: "com.svrnty.native_picker",
|
|
binaryMessenger: registrar.messenger)
|
|
let instance = NativePickerRegistrar()
|
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
|
}
|
|
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
switch call.method {
|
|
case "getDirectoryPath":
|
|
let args = call.arguments as? [String: Any] ?? [:]
|
|
let dialog = NSOpenPanel()
|
|
|
|
if let initial = args["initialDirectory"] as? String, !initial.isEmpty {
|
|
dialog.directoryURL = URL(fileURLWithPath: initial)
|
|
}
|
|
dialog.showsHiddenFiles = true
|
|
dialog.canChooseDirectories = true
|
|
dialog.canChooseFiles = false
|
|
dialog.allowsMultipleSelection = false
|
|
dialog.treatsFilePackagesAsDirectories = true
|
|
dialog.message = "Select a folder containing session files"
|
|
|
|
guard let window = NSApp.keyWindow else {
|
|
result(FlutterError(code: "NO_WINDOW", message: "No key window found", details: nil))
|
|
return
|
|
}
|
|
|
|
dialog.beginSheetModal(for: window) { response in
|
|
if response == .OK, let url = dialog.url {
|
|
result(url.path)
|
|
} else {
|
|
result(nil)
|
|
}
|
|
}
|
|
|
|
case "pickFiles":
|
|
let args = call.arguments as? [String: Any] ?? [:]
|
|
let dialog = NSOpenPanel()
|
|
|
|
if let initial = args["initialDirectory"] as? String, !initial.isEmpty {
|
|
dialog.directoryURL = URL(fileURLWithPath: initial)
|
|
}
|
|
dialog.showsHiddenFiles = true
|
|
dialog.canChooseDirectories = false
|
|
dialog.canChooseFiles = true
|
|
dialog.allowsMultipleSelection = false
|
|
|
|
if let extensions = args["allowedExtensions"] as? [String], !extensions.isEmpty {
|
|
if #available(macOS 11.0, *) {
|
|
let contentTypes = extensions.compactMap { UTType(filenameExtension: $0) }
|
|
dialog.allowedContentTypes = contentTypes
|
|
} else {
|
|
dialog.allowedFileTypes = extensions
|
|
}
|
|
}
|
|
dialog.message = "Select a session file"
|
|
|
|
guard let window = NSApp.keyWindow else {
|
|
result(FlutterError(code: "NO_WINDOW", message: "No key window found", details: nil))
|
|
return
|
|
}
|
|
|
|
dialog.beginSheetModal(for: window) { response in
|
|
if response == .OK, let url = dialog.url {
|
|
result([url.path])
|
|
} else {
|
|
result(nil)
|
|
}
|
|
}
|
|
|
|
default:
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
}
|