Redline: OneDrive folder transport as alternative to AirDrop (MMDB-2631) #23
@@ -132,6 +132,13 @@ public final class AppModel {
|
||||
}
|
||||
func setTransport(_ value: SendTransport) { transport = value }
|
||||
func setResolvedOneDriveFolder(_ value: URL?) { resolvedOneDriveFolder = value }
|
||||
|
||||
/// Bumped by chooseTransport/chooseOneDriveFolder (SettingsView.swift) before each
|
||||
/// spawns its async watcher-reconcile Task; that Task checks its own snapshot
|
||||
/// against the live value before every mutating step, so rapid toggling always
|
||||
/// lets the LAST choice win instead of applying stale, superseded work. Not
|
||||
/// `@Observable`-relevant state — pure internal bookkeeping, never read by a View.
|
||||
var reconcileGeneration = 0
|
||||
func rememberLastComposedPDF(_ url: URL) { lastComposedPDFURL = url }
|
||||
|
||||
/// True when a last-composed PDF path is known this run, or the newest
|
||||
@@ -211,6 +218,17 @@ public final class AppModel {
|
||||
await watcher.setRecordUncommented(transport == .airDrop)
|
||||
|
||||
do {
|
||||
// BLOCKER fix: reconcile the watcher's internal watchFolder with the live
|
||||
// watchFolderURL UNCONDITIONALLY, before it ever starts. `paths` (and so the
|
||||
// watcher's initial folder, set in its own init) now comes from the same
|
||||
// transport-aware TransportSettings.effectiveFolders() as watchFolderURL, so
|
||||
// in the normal case this is a no-op — but it is the only thing that would
|
||||
// have caught the old bug (launch paths built AirDrop-only while OneDrive was
|
||||
// the persisted transport, leaving the watcher's FSEvents stream pointed at a
|
||||
// stale folder for the whole session) and it stays cheap insurance against
|
||||
// that class of drift ever recurring. Calling it before start() only updates
|
||||
// the stored folder — no FSEvents stream exists yet to restart.
|
||||
try await watcher.updateWatchFolder(watchFolderURL)
|
||||
try await watcher.start { [weak self] _ in
|
||||
Task { @MainActor in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -50,9 +50,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
Task { await model.bootstrap() }
|
||||
}
|
||||
|
||||
private static func makeLaunchModel() -> AppModel {
|
||||
/// Builds the model exactly the way the real app launches: paths come from
|
||||
/// `TransportSettings.resolvedAppSupportPaths()` — transport-aware, so the watcher
|
||||
/// this feeds is never seeded with a stale AirDrop folder while OneDrive is the
|
||||
/// persisted transport (that was the BLOCKER this function used to have, when it
|
||||
/// called the AirDrop-only `FolderSettings.resolvedAppSupportPaths()` instead).
|
||||
/// `appSupportRoot` exists only so PickerSelfTest's relaunch-simulation sub-step can
|
||||
/// point this at a temp directory instead of the real
|
||||
/// ~/Library/Application Support/Shotdeck — production always calls this with no
|
||||
/// argument (the real root). Internal, not private, for that same reason.
|
||||
static func makeLaunchModel(appSupportRoot: URL? = nil) -> AppModel {
|
||||
do {
|
||||
let paths = try FolderSettings.resolvedAppSupportPaths()
|
||||
let paths = try TransportSettings.resolvedAppSupportPaths(root: appSupportRoot)
|
||||
return try makeModel(paths: paths)
|
||||
} catch {
|
||||
Log.ui.critical(
|
||||
|
||||
Reference in New Issue
Block a user