Import into the library, which is on the server
There was a local destination, defaulting to ~/Pictures, and an "upload" switch that could be turned off. That was wrong twice over. DarkRoom's library *is* a folder on a Nextcloud server (FR-NC-6) — there is no local library — so a user-chosen local destination built a second pile of photographs that no view in the application ever lists, and made "where did my import go" a question with two answers. An import now has exactly one destination and the page asks nothing about it. With no account there is nowhere to go at all, so Import is refused rather than quietly filling a folder. What lands on the device is a staging copy in a directory the app owns, the same shape `export` uses for its outbox and for the reason its module docs give: staging first is the only path, not a fallback for being offline. The bytes have to reach disk before the network — streaming a card straight to the server would let a move-import erase a card against an in-flight upload, and would make importing impossible with no connection (FR-NC-10). A staged file is removed once the server confirms it; one that is not confirmed stays queued, and the next import drains it. And the rule that was stated but never enforced: `retirable` was reported and `dr_ingest::retire` was never called by anything, so a move-import silently behaved as a copy. The card is now emptied by the worker, of exactly those photographs the *server* has confirmed — not those merely written here, because the staging copy is removed moments later and anything unconfirmed would then exist nowhere at all. FR-NC-7b said "copied locally first ... then queued for upload", which is a staging area; it has been rewritten to say so in terms that do not also permit what was built. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+18
-21
@@ -85,11 +85,11 @@ export component ImportPage inherits Rectangle {
|
||||
in property <string> survey-summary;
|
||||
|
||||
// --- where they are going --------------------------------------------
|
||||
/// The library root. Shown, not editable — see the header comment.
|
||||
in property <string> destination;
|
||||
/// The folder on the server the originals go on to, once they are safely
|
||||
/// on disk (FR-NC-7b). Empty when no account is signed in, which hides the
|
||||
/// line rather than showing an empty one.
|
||||
/// The library folder on the server — the only destination there is.
|
||||
///
|
||||
/// Empty means no account is signed in, and Import stays disabled: the
|
||||
/// library lives on the server, so an import without one has nowhere to
|
||||
/// go at all.
|
||||
in property <string> upload-target;
|
||||
in-out property <string> folder-template;
|
||||
/// The template expanded against a real date, so the answer to "what will
|
||||
@@ -272,27 +272,24 @@ export component ImportPage inherits Rectangle {
|
||||
spacing: Theme.gap;
|
||||
Label { text: "Library"; }
|
||||
Value {
|
||||
text: root.destination;
|
||||
text: root.upload-target != "" ? root.upload-target
|
||||
: "not signed in";
|
||||
overflow: elide;
|
||||
horizontal-stretch: 1;
|
||||
}
|
||||
}
|
||||
|
||||
if root.upload-target != "": HorizontalLayout {
|
||||
spacing: Theme.gap;
|
||||
Label { text: "Server"; }
|
||||
Value {
|
||||
text: root.upload-target;
|
||||
overflow: elide;
|
||||
horizontal-stretch: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Said once, here, rather than beside the Import button:
|
||||
// the order is the promise, and a user watching a slow
|
||||
// upload needs to already know the photographs are on disk.
|
||||
// The order is the promise, and a user watching a slow
|
||||
// upload needs to already know the photographs are safe.
|
||||
// Said here, beside the destination, rather than beside the
|
||||
// Import button where it would read as a warning.
|
||||
if root.upload-target != "": Caption {
|
||||
text: "Copied here and verified first, then uploaded.";
|
||||
text: "Copied to this computer and verified first, then uploaded. Anything that does not go up stays queued for the next import.";
|
||||
wrap: word-wrap;
|
||||
}
|
||||
|
||||
if root.upload-target == "": Caption {
|
||||
text: "Sign in first — the library this imports into is on the server.";
|
||||
wrap: word-wrap;
|
||||
}
|
||||
|
||||
@@ -333,7 +330,7 @@ export component ImportPage inherits Rectangle {
|
||||
// The one operation in this application with no undo,
|
||||
// and the only honest place to say so is beside the
|
||||
// control that arms it (FR-NC-7b).
|
||||
text: "The card is emptied only after every file is verified in the library — and, on a library that syncs, after it has reached the server.";
|
||||
text: "The card is emptied only of photographs the server has confirmed. Anything that does not upload keeps its card copy — which is then the only copy there is.";
|
||||
wrap: word-wrap;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user