fix(settings): align preferences with runtime behavior

This commit is contained in:
nimbold
2026-06-05 11:41:56 +03:30
parent 2b820ec802
commit 4a9d4cab2f
11 changed files with 258 additions and 57 deletions
@@ -28,29 +28,46 @@ struct DirectoryPickerRow: View {
let category: DownloadCategory
@State private var path = ""
@State private var message = ""
var body: some View {
LabeledContent {
HStack(spacing: 8) {
TextField("Folder path", text: Binding(
get: { settings.downloadDirectories[category] ?? path },
set: { newValue in
path = newValue
settings.setDirectory(newValue, for: category)
}
))
.textFieldStyle(.roundedBorder)
.font(.system(.body, design: .monospaced))
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) {
TextField("Folder path", text: $path)
.textFieldStyle(.roundedBorder)
.font(.system(.body, design: .monospaced))
.onSubmit {
applyPath()
}
Button {
selectFolder()
} label: {
Label("Select", systemImage: "folder.badge.plus")
Button {
applyPath()
} label: {
Label("Apply", systemImage: "checkmark")
}
.disabled(path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
Button {
selectFolder()
} label: {
Label("Select", systemImage: "folder.badge.plus")
}
}
Text(message.isEmpty ? statusMessage(for: path) : message)
.font(.caption)
.foregroundStyle(message.isEmpty ? .secondary : .primary)
}
} label: {
Label(category.rawValue, systemImage: category.symbolName)
}
.onAppear {
syncPathFromSettings()
}
.onChange(of: settings.downloadDirectories[category]) { _, _ in
syncPathFromSettings()
}
}
private func selectFolder() {
@@ -62,7 +79,70 @@ struct DirectoryPickerRow: View {
panel.directoryURL = settings.destinationDirectory(for: category)
if panel.runModal() == .OK, let url = panel.url {
path = url.path
settings.setDirectory(url.path, for: category)
message = "Saved."
}
}
private func syncPathFromSettings() {
path = settings.downloadDirectories[category] ?? settings.destinationDirectory(for: category).path
message = ""
}
private func applyPath() {
let trimmed = path.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
message = "Enter a folder path."
return
}
let expanded = NSString(string: trimmed).expandingTildeInPath
var isDirectory: ObjCBool = false
if FileManager.default.fileExists(atPath: expanded, isDirectory: &isDirectory) {
guard isDirectory.boolValue else {
message = "This path points to a file, not a folder."
return
}
} else {
do {
try FileManager.default.createDirectory(
at: URL(fileURLWithPath: expanded, isDirectory: true),
withIntermediateDirectories: true
)
} catch {
message = "Could not create folder: \(error.localizedDescription)"
return
}
}
guard FileManager.default.isWritableFile(atPath: expanded) else {
message = "Firelink cannot write to this folder."
return
}
settings.setDirectory(expanded, for: category)
path = expanded
message = "Saved."
}
private func statusMessage(for path: String) -> String {
let trimmed = path.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return "Enter a folder path." }
let expanded = NSString(string: trimmed).expandingTildeInPath
var isDirectory: ObjCBool = false
if FileManager.default.fileExists(atPath: expanded, isDirectory: &isDirectory) {
if !isDirectory.boolValue {
return "This path points to a file, not a folder."
}
return FileManager.default.isWritableFile(atPath: expanded)
? "Ready."
: "Firelink cannot write to this folder."
}
return "Folder will be created when applied."
}
}