You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
51 lines
1.9 KiB
51 lines
1.9 KiB
import Foundation
|
|
|
|
/// Quell- und Zielordner, persistiert über Security-Scoped Bookmarks statt
|
|
/// roher Pfade — überlebt damit auch einen späteren Wechsel in den App
|
|
/// Sandbox (README: "@AppStorage + Security-Scoped Bookmarks").
|
|
@MainActor
|
|
final class AppSettings: ObservableObject {
|
|
@Published private(set) var sourceFolder: URL?
|
|
@Published private(set) var targetFolder: URL?
|
|
|
|
private enum DefaultsKey {
|
|
static let sourceBookmark = "dev.zielke.droptwo.sourceFolderBookmark"
|
|
static let targetBookmark = "dev.zielke.droptwo.targetFolderBookmark"
|
|
}
|
|
|
|
init() {
|
|
sourceFolder = Self.resolveBookmark(forKey: DefaultsKey.sourceBookmark)
|
|
targetFolder = Self.resolveBookmark(forKey: DefaultsKey.targetBookmark)
|
|
}
|
|
|
|
func setSourceFolder(_ url: URL) {
|
|
sourceFolder = url
|
|
Self.storeBookmark(for: url, key: DefaultsKey.sourceBookmark)
|
|
}
|
|
|
|
func setTargetFolder(_ url: URL) {
|
|
targetFolder = url
|
|
Self.storeBookmark(for: url, key: DefaultsKey.targetBookmark)
|
|
}
|
|
|
|
private static func storeBookmark(for url: URL, key: String) {
|
|
do {
|
|
let data = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
|
|
UserDefaults.standard.set(data, forKey: key)
|
|
} catch {
|
|
// Best effort: der Ordner bleibt für die laufende Sitzung trotzdem
|
|
// gesetzt, nur der Neustart-Fall geht dann verloren.
|
|
}
|
|
}
|
|
|
|
private static func resolveBookmark(forKey key: String) -> URL? {
|
|
guard let data = UserDefaults.standard.data(forKey: key) else { return nil }
|
|
var isStale = false
|
|
guard let url = try? URL(resolvingBookmarkData: data, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale) else {
|
|
return nil
|
|
}
|
|
_ = url.startAccessingSecurityScopedResource()
|
|
return url
|
|
}
|
|
}
|