Keep a stepped-past download from replacing the open photograph
Opening a photograph from the library starts a download and a timer that polls for it. Every step along the roll started another, and each one put its result on screen when it landed, so a frame stepped past earlier could arrive last and replace the one whose name was showing. Each open now takes a generation number; a download that lands for an older generation is recorded in the activity list (its bytes are cached) and goes no further. The outgoing session also stayed live until the new download landed. Its sliders kept working, and a second step before the first landed saved that session's edit under the new photograph's identity. The session is now dropped as soon as its edit is saved.
This commit is contained in:
+47
-47
File diff suppressed because one or more lines are too long
+25
-25
@@ -39,7 +39,7 @@ The list is longer than it is tall, so a way to walk it that cannot be lost to t
|
|||||||
|
|
||||||
Anchored on the fingers' midpoint, and on the pointer, so the gesture reads as magnifying the picture rather than sliding it about. Double-tap is the way to an exact 1:1; this is the way to everything in between. Past 1:1 the pixels are shown as they are, square and unsmoothed; below it, filtered.
|
Anchored on the fingers' midpoint, and on the pointer, so the gesture reads as magnifying the picture rather than sliding it about. Double-tap is the way to an exact 1:1; this is the way to everything in between. Past 1:1 the pixels are shown as they are, square and unsmoothed; below it, filtered.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:1908`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:1949`</sub>
|
||||||
|
|
||||||
### Move a magnified photograph about
|
### Move a magnified photograph about
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ Anchored on the fingers' midpoint, and on the pointer, so the gesture reads as m
|
|||||||
|
|
||||||
Only once there is something outside the viewport to reach, which is why the cursor becomes a hand exactly then. The view is clamped to the frame: panning past the edge would show undefined area beside the photograph, and that reads as a rendering fault rather than as the end of the picture.
|
Only once there is something outside the viewport to reach, which is why the cursor becomes a hand exactly then. The view is clamped to the frame: panning past the edge would show undefined area beside the photograph, and that reads as a rendering fault rather than as the end of the picture.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2004`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2045`</sub>
|
||||||
|
|
||||||
### Paint a mask by hand
|
### Paint a mask by hand
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ Only once there is something outside the viewport to reach, which is why the cur
|
|||||||
|
|
||||||
A model's mask stops inside a shoulder and leaks into the hair, and no single edge control fixes two errors that go opposite ways. The whole stroke is one step in the history, so taking a mark back costs one press however long it took to make.
|
A model's mask stops inside a shoulder and leaks into the hair, and no single edge control fixes two errors that go opposite ways. The whole stroke is one step in the history, so taking a mark back costs one press however long it took to make.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2095`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2136`</sub>
|
||||||
|
|
||||||
### Open this list
|
### Open this list
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ A model's mask stops inside a shoulder and leaks into the hair, and no single ed
|
|||||||
|
|
||||||
Most of the keys are develop's, and a reference that could only be opened from the grid had to be looked up before opening the photograph they were wanted for.
|
Most of the keys are develop's, and a reference that could only be opened from the grid had to be looked up before opening the photograph they were wanted for.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2321`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2362`</sub>
|
||||||
|
|
||||||
### Take back the last change
|
### Take back the last change
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ Most of the keys are develop's, and a reference that could only be opened from t
|
|||||||
|
|
||||||
A whole drag is one step, so undo takes back a decision rather than a frame of a gesture. The list is there because arriving six steps back costs what arriving from one does.
|
A whole drag is one step, so undo takes back a decision rather than a frame of a gesture. The list is there because arriving six steps back costs what arriving from one does.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2351`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2392`</sub>
|
||||||
|
|
||||||
### Do it again after taking it back
|
### Do it again after taking it back
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ A whole drag is one step, so undo takes back a decision rather than a frame of a
|
|||||||
- **Keyboard** — `Ctrl+Shift+Z`, or `Ctrl+Y`
|
- **Keyboard** — `Ctrl+Shift+Z`, or `Ctrl+Y`
|
||||||
- **See it** — [in the manual](manual/README.md#history-snapshots-presets)
|
- **See it** — [in the manual](manual/README.md#history-snapshots-presets)
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2365`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2406`</sub>
|
||||||
|
|
||||||
### Remove a repair
|
### Remove a repair
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ A whole drag is one step, so undo takes back a decision rather than a frame of a
|
|||||||
- **Pointer** — Click it, then Delete Repair
|
- **Pointer** — Click it, then Delete Repair
|
||||||
- **Keyboard** — `Delete` or `Backspace`, while repairing
|
- **Keyboard** — `Delete` or `Backspace`, while repairing
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2385`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2426`</sub>
|
||||||
|
|
||||||
### Copy the settings from this photograph
|
### Copy the settings from this photograph
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ A whole drag is one step, so undo takes back a decision rather than a frame of a
|
|||||||
|
|
||||||
The button is the copy that has to work: a tablet has no modifier key to hold and no menu bar to hang the action from. The shortcut is an accelerator for a control that is on screen either way.
|
The button is the copy that has to work: a tablet has no modifier key to hold and no menu bar to hang the action from. The shortcut is an accelerator for a control that is on screen either way.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2404`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2445`</sub>
|
||||||
|
|
||||||
### Paste the settings onto this photograph
|
### Paste the settings onto this photograph
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ The button is the copy that has to work: a tablet has no modifier key to hold an
|
|||||||
|
|
||||||
The button names what would be pasted — "3 adjustments", and whether the crop is coming with it — which the shortcut cannot say. Both paste the same scope.
|
The button names what would be pasted — "3 adjustments", and whether the crop is coming with it — which the shortcut cannot say. Both paste the same scope.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2417`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2458`</sub>
|
||||||
|
|
||||||
### Choose which kinds of edit a copy carries
|
### Choose which kinds of edit a copy carries
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ The button names what would be pasted — "3 adjustments", and whether the crop
|
|||||||
|
|
||||||
Lightroom's Copy Settings. Pasting a look across a shoot usually means leaving each frame's crop and rotation alone, and that is a choice to make at the moment of copying.
|
Lightroom's Copy Settings. Pasting a look across a shoot usually means leaving each frame's crop and rotation alone, and that is a choice to make at the moment of copying.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2435`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2476`</sub>
|
||||||
|
|
||||||
### Export this photograph as the last one was
|
### Export this photograph as the last one was
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ Lightroom's Copy Settings. Pasting a look across a shoot usually means leaving e
|
|||||||
|
|
||||||
Every export runs on the defaults in Settings, so "as the last one was" is what the button already does. The chord is Lightroom's and darktable's, kept so hands that learned it there need not learn it again.
|
Every export runs on the defaults in Settings, so "as the last one was" is what the button already does. The chord is Lightroom's and darktable's, kept so hands that learned it there need not learn it again.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2460`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2501`</sub>
|
||||||
|
|
||||||
### Choose how to export, then export
|
### Choose how to export, then export
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ Every export runs on the defaults in Settings, so "as the last one was" is what
|
|||||||
|
|
||||||
The export sheet is the export defaults alone with an Export button. What is chosen there is kept, so it is also what the next Ctrl+Shift+E uses.
|
The export sheet is the export defaults alone with an Export button. What is chosen there is kept, so it is also what the next Ctrl+Shift+E uses.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2473`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2514`</sub>
|
||||||
|
|
||||||
### Keep a crop that leaves a mask outside
|
### Keep a crop that leaves a mask outside
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ The export sheet is the export defaults alone with an Export button. What is cho
|
|||||||
- **Pointer** — Press "Keep crop" on the notice, or "Undo crop" to take it back
|
- **Pointer** — Press "Keep crop" on the notice, or "Undo crop" to take it back
|
||||||
- **Keyboard** — `Enter` keeps it; `Ctrl+Z` takes the crop back, like any other step
|
- **Keyboard** — `Enter` keeps it; `Ctrl+Z` takes the crop back, like any other step
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2538`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2579`</sub>
|
||||||
|
|
||||||
### Go back to the grid
|
### Go back to the grid
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ The export sheet is the export defaults alone with an Export button. What is cho
|
|||||||
|
|
||||||
Lightroom's key for the grid. Escape gets there too, but a step at a time — out of a mode, then out of a zoom — where this goes straight back.
|
Lightroom's key for the grid. Escape gets there too, but a step at a time — out of a mode, then out of a zoom — where this goes straight back.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2555`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2596`</sub>
|
||||||
|
|
||||||
### Nudge the control last moved
|
### Nudge the control last moved
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ Lightroom's key for the grid. Escape gets there too, but a step at a time — ou
|
|||||||
|
|
||||||
Lightroom's keys for the selected slider. There is no focus ring on a slider here, so "selected" is the last one moved — the same control `R` puts back — which covers the framing sliders, perspective included, as well as the adjustments.
|
Lightroom's keys for the selected slider. There is no focus ring on a slider here, so "selected" is the last one moved — the same control `R` puts back — which covers the framing sliders, perspective included, as well as the adjustments.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2584`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2625`</sub>
|
||||||
|
|
||||||
### Change which group of adjustments is on screen
|
### Change which group of adjustments is on screen
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ Lightroom's keys for the selected slider. There is no focus ring on a slider her
|
|||||||
|
|
||||||
The groups are whatever the operation set declares itself to be about, so there are as many as the pipeline has and no key can be assigned to one of them by name. Stepping is the binding that survives a node being added.
|
The groups are whatever the operation set declares itself to be about, so there are as many as the pipeline has and no key can be assigned to one of them by name. Stepping is the binding that survives a node being added.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2612`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2653`</sub>
|
||||||
|
|
||||||
### Look at the photograph at 1:1
|
### Look at the photograph at 1:1
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ The groups are whatever the operation set declares itself to be about, so there
|
|||||||
|
|
||||||
Noise reduction and capture sharpening are judgements about single pixels, and a fitted view averages several of the file's into each one on screen — so the frame looks softer than it is and the correction goes too far. The point and the magnification survive opening the next photograph, which is what makes checking the same eye across forty portraits forty keystrokes rather than forty pans. From 1:1 on the photograph is drawn as its own pixels, each a hard-edged square, rather than smoothed into a blur.
|
Noise reduction and capture sharpening are judgements about single pixels, and a fitted view averages several of the file's into each one on screen — so the frame looks softer than it is and the correction goes too far. The point and the magnification survive opening the next photograph, which is what makes checking the same eye across forty portraits forty keystrokes rather than forty pans. From 1:1 on the photograph is drawn as its own pixels, each a hard-edged square, rather than smoothed into a blur.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2648`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2689`</sub>
|
||||||
|
|
||||||
### Rate this photograph
|
### Rate this photograph
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ Noise reduction and capture sharpening are judgements about single pixels, and a
|
|||||||
- **Pointer** — Click a star in the top bar
|
- **Pointer** — Click a star in the top bar
|
||||||
- **Keyboard** — `0`–`5`
|
- **Keyboard** — `0`–`5`
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2705`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2746`</sub>
|
||||||
|
|
||||||
### Pick or reject this photograph
|
### Pick or reject this photograph
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ Noise reduction and capture sharpening are judgements about single pixels, and a
|
|||||||
|
|
||||||
The grid's keys, on the photograph that is open (FR-UI-5, 2026-09-19). Judging here does not move on to the next frame: that belongs to culling, and in develop the photograph in front of you is the one being worked on.
|
The grid's keys, on the photograph that is open (FR-UI-5, 2026-09-19). Judging here does not move on to the next frame: that belongs to culling, and in develop the photograph in front of you is the one being worked on.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2711`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2752`</sub>
|
||||||
|
|
||||||
### Give this photograph a colour label
|
### Give this photograph a colour label
|
||||||
|
|
||||||
@@ -232,7 +232,7 @@ The grid's keys, on the photograph that is open (FR-UI-5, 2026-09-19). Judging h
|
|||||||
|
|
||||||
The grid's keys, on the photograph that is open, so labelling while stepping through a folder is one hand's work. The bar names the label in words beside its mark.
|
The grid's keys, on the photograph that is open, so labelling while stepping through a folder is one hand's work. The bar names the label in words beside its mark.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2741`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2782`</sub>
|
||||||
|
|
||||||
### Move to the next or previous photograph
|
### Move to the next or previous photograph
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ The grid's keys, on the photograph that is open, so labelling while stepping thr
|
|||||||
|
|
||||||
The edit on screen is saved on the way out, so stepping through a folder is as much a departure as going back to the grid and loses nothing. A and D as well as the arrows, so the left hand steps along the roll while the right stays on the mouse.
|
The edit on screen is saved on the way out, so stepping through a folder is as much a departure as going back to the grid and loses nothing. A and D as well as the arrows, so the left hand steps along the roll while the right stays on the mouse.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2766`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2807`</sub>
|
||||||
|
|
||||||
### See the photograph before you edited it
|
### See the photograph before you edited it
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ The edit on screen is saved on the way out, so stepping through a folder is as m
|
|||||||
|
|
||||||
Held rather than toggled, and no split screen: a split halves the working image on the tablet the column was sized for, and the comparison photographers describe making is a flick back and forth. It takes no history step, so checking whether a frame is overcooked costs nothing to undo afterwards.
|
Held rather than toggled, and no split screen: a split halves the working image on the tablet the column was sized for, and the comparison photographers describe making is a flick back and forth. It takes no history step, so checking whether a frame is overcooked costs nothing to undo afterwards.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:2896`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:2937`</sub>
|
||||||
|
|
||||||
### Put one control back to its default
|
### Put one control back to its default
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ The question a correction raises is whether it did what it was for — whether t
|
|||||||
|
|
||||||
One key for "up one", innermost first: a question before the sheet under it, a sheet before the view, a view before the library. Nothing is left behind a dialogue that the key walked straight past.
|
One key for "up one", innermost first: a question before the sheet under it, a sheet before the view, a view before the library. Nothing is left behind a dialogue that the key walked straight past.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:987`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:1013`</sub>
|
||||||
|
|
||||||
### Do what a sheet offers
|
### Do what a sheet offers
|
||||||
|
|
||||||
@@ -346,7 +346,7 @@ One key for "up one", innermost first: a question before the sheet under it, a s
|
|||||||
- **Pointer** — Press its button — Export, or Copy
|
- **Pointer** — Press its button — Export, or Copy
|
||||||
- **Keyboard** — `Enter`, on the export and copy sheets
|
- **Keyboard** — `Enter`, on the export and copy sheets
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/app.slint:997`</sub>
|
<sub>`ui/dr-ui/ui/app.slint:1023`</sub>
|
||||||
|
|
||||||
### Scroll by the scrollbar
|
### Scroll by the scrollbar
|
||||||
|
|
||||||
@@ -354,7 +354,7 @@ One key for "up one", innermost first: a question before the sheet under it, a s
|
|||||||
|
|
||||||
A list cut off at its edge looks, to a mouse, like a list that ends there — the film stocks past the tenth read as deleted. The bar says there is more and where the view is in it, and it is the one way to scroll that needs neither a wheel nor a drag on the content, which may be a row that would take the click.
|
A list cut off at its edge looks, to a mouse, like a list that ends there — the film stocks past the tenth read as deleted. The bar says there is more and where the view is in it, and it is the one way to scroll that needs neither a wheel nor a drag on the content, which may be a row that would take the click.
|
||||||
|
|
||||||
<sub>`ui/dr-ui/ui/widgets.slint:1074`</sub>
|
<sub>`ui/dr-ui/ui/widgets.slint:1131`</sub>
|
||||||
|
|
||||||
## Collections sidebar
|
## Collections sidebar
|
||||||
|
|
||||||
|
|||||||
@@ -2670,6 +2670,14 @@ fn wire_remote_open(
|
|||||||
let inspection = inspection.clone();
|
let inspection = inspection.clone();
|
||||||
let prefetch = prefetch.clone();
|
let prefetch = prefetch.clone();
|
||||||
|
|
||||||
|
// Which open is the current one. Every open starts its own download and
|
||||||
|
// its own timer, and a walk along the roll starts one per press — so the
|
||||||
|
// transfers land in whatever order the network finishes them, not the
|
||||||
|
// order they were asked for. Without this the photograph stepped past
|
||||||
|
// three presses ago could arrive last and replace the one whose name is
|
||||||
|
// on screen, and its edit would then be saved under that name.
|
||||||
|
let current = Rc::new(Cell::new(0u64));
|
||||||
|
|
||||||
{
|
{
|
||||||
let weak = window.as_weak();
|
let weak = window.as_weak();
|
||||||
let library = library.clone();
|
let library = library.clone();
|
||||||
@@ -2689,6 +2697,18 @@ fn wire_remote_open(
|
|||||||
// before the identity below is overwritten.
|
// before the identity below is overwritten.
|
||||||
presets::save_open_edit(&w, &open_image.borrow(), &session, &library);
|
presets::save_open_edit(&w, &open_image.borrow(), &session, &library);
|
||||||
|
|
||||||
|
// And let the outgoing session go now, not when the download
|
||||||
|
// lands. Kept, its sliders stayed live over a photograph that was
|
||||||
|
// no longer the open one, and a second step before the first
|
||||||
|
// landed saved *that* session's edit under the new photograph's
|
||||||
|
// identity, which is set a few lines below.
|
||||||
|
*session.borrow_mut() = None;
|
||||||
|
rows.set_vec(Vec::<ParamRow>::new());
|
||||||
|
w.global::<Develop>().set_enabled(false);
|
||||||
|
|
||||||
|
current.set(current.get() + 1);
|
||||||
|
let mine = current.get();
|
||||||
|
|
||||||
let name = path.rsplit('/').next().unwrap_or(&path).to_string();
|
let name = path.rsplit('/').next().unwrap_or(&path).to_string();
|
||||||
reset_view_state(&w);
|
reset_view_state(&w);
|
||||||
w.set_filename(name.clone().into());
|
w.set_filename(name.clone().into());
|
||||||
@@ -2748,6 +2768,7 @@ fn wire_remote_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log::info!("fetching {path} for develop");
|
log::info!("fetching {path} for develop");
|
||||||
|
|
||||||
w.set_load_error("Downloading…".into());
|
w.set_load_error("Downloading…".into());
|
||||||
|
|
||||||
let rx = library::spawn_full_fetch(conn, path.clone(), cache);
|
let rx = library::spawn_full_fetch(conn, path.clone(), cache);
|
||||||
@@ -2774,6 +2795,7 @@ fn wire_remote_open(
|
|||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
let viewport = viewport.clone();
|
let viewport = viewport.clone();
|
||||||
let inspection = inspection.clone();
|
let inspection = inspection.clone();
|
||||||
|
let current = current.clone();
|
||||||
let sidecar_rx = Rc::new(sidecar_rx);
|
let sidecar_rx = Rc::new(sidecar_rx);
|
||||||
let timer = Rc::new(slint::Timer::default());
|
let timer = Rc::new(slint::Timer::default());
|
||||||
let held = timer.clone();
|
let held = timer.clone();
|
||||||
@@ -2786,6 +2808,18 @@ fn wire_remote_open(
|
|||||||
held.stop();
|
held.stop();
|
||||||
let Some(w) = weak.upgrade() else { return };
|
let Some(w) = weak.upgrade() else { return };
|
||||||
|
|
||||||
|
// Stepped past while it was coming down. The transfer
|
||||||
|
// still counts — it is in the cache, and the step back
|
||||||
|
// will be a disk read — but it is not what is on screen.
|
||||||
|
if current.get() != mine {
|
||||||
|
match &got {
|
||||||
|
Ok(b) => job.finish(activity::describe_bytes(b.len() as u64)),
|
||||||
|
Err(e) => job.fail(e.message.clone()),
|
||||||
|
}
|
||||||
|
log::debug!("{name}: landed after the view moved on");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let bytes = match got {
|
let bytes = match got {
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user