Files · Transfers: file operations, a transfer queue, downloads and storage
A file on its way is a Transfer with a state: waiting, moving at a rate, paused, done or failed with a reason. One row draws it for the queue and the downloads: its icon, its way, a bar while it moves or waits paused, a status with the time left, and only the actions its state allows. TransferQueue counts what moves and waits. DownloadManager keeps the finished below under Clear, opening on a press and showing their folder. FileOperationProgress tells a copy or move with its bar, time left and current file, its header wrapping by the header rule; a failure speaks in the danger tone. StorageUsage points to data_display's UsageBar.
This commit is contained in:
1 parent
b280929d07
commit
4ef9830def
11 files changed
+1180
-5
No files matched your search
@@ -9,6 +9,7 @@ use jiff::{Timestamp, ToSpan};
|
||||
mod actions;
|
||||
mod explorer;
|
||||
mod find;
|
||||
mod transfers;
|
||||
|
||||
use super::Page;
|
||||
use crate::{
|
||||
@@ -216,5 +217,9 @@ fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
.child(find::duplicates(window, cx))
|
||||
.child(find::archive(cx))
|
||||
.child(find::hex(window, cx))
|
||||
.child(transfers::operations(window, cx))
|
||||
.child(transfers::queue(window, cx))
|
||||
.child(transfers::downloads(window, cx))
|
||||
.child(transfers::storage(cx))
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
use ely_gpui_component::{
|
||||
data_display::UsageBar,
|
||||
files::{
|
||||
DownloadManager, FileOperation, FileOperationProgress, Transfer, TransferQueue,
|
||||
TransferState,
|
||||
},
|
||||
typography::format,
|
||||
};
|
||||
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
||||
|
||||
use crate::{
|
||||
probe::probe,
|
||||
ui::{change, keep, section},
|
||||
};
|
||||
|
||||
fn transfer(
|
||||
key: &str,
|
||||
name: &str,
|
||||
upload: bool,
|
||||
(moved, total): (u64, u64),
|
||||
state: TransferState,
|
||||
) -> Transfer {
|
||||
Transfer {
|
||||
key: SharedString::from(key.to_string()),
|
||||
name: SharedString::from(name.to_string()),
|
||||
upload,
|
||||
moved,
|
||||
total,
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operations(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let copy = keep(
|
||||
"files-copy",
|
||||
|| TransferState::Moving { rate: 38_000_000 },
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let now = copy.read(cx).clone();
|
||||
let (pause, resume, cancel) = (copy.clone(), copy.clone(), copy);
|
||||
let running = FileOperationProgress::new(
|
||||
"files-copy",
|
||||
FileOperation::Copy,
|
||||
12,
|
||||
"Atrium",
|
||||
(46_000_000, 184_000_000),
|
||||
now,
|
||||
)
|
||||
.current("Recordings/Walkthrough.mov")
|
||||
.on_pause(move |_, cx| change(&pause, cx, |state| *state = TransferState::Paused))
|
||||
.on_resume(move |_, cx| {
|
||||
change(&resume, cx, |state| {
|
||||
*state = TransferState::Moving { rate: 38_000_000 }
|
||||
})
|
||||
})
|
||||
.on_cancel(move |_, cx| {
|
||||
change(&cancel, cx, |state| {
|
||||
*state = TransferState::Failed("Cancelled".into())
|
||||
})
|
||||
});
|
||||
let failed = FileOperationProgress::new(
|
||||
"files-move-failed",
|
||||
FileOperation::Move,
|
||||
3,
|
||||
"Backup",
|
||||
(820_000, 4_800_000),
|
||||
TransferState::Failed("The disk Backup is full.".into()),
|
||||
);
|
||||
let done = FileOperationProgress::new(
|
||||
"files-move-done",
|
||||
FileOperation::Move,
|
||||
1,
|
||||
"Documents",
|
||||
(88_000, 88_000),
|
||||
TransferState::Done,
|
||||
);
|
||||
section(
|
||||
"FileOperationProgress",
|
||||
"A copy or a move under way: what it does and where to, a bar, the bytes done with the time left, and the file it takes now. Pause, resume and cancel while it runs.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"files-operations",
|
||||
div()
|
||||
.w(px(480.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(running)
|
||||
.child(failed)
|
||||
.child(done),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn queue(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let transfers = keep(
|
||||
"files-queue",
|
||||
|| {
|
||||
vec![
|
||||
transfer(
|
||||
"walkthrough",
|
||||
"Walkthrough.mov",
|
||||
true,
|
||||
(61_000_000, 184_000_000),
|
||||
TransferState::Moving { rate: 4_200_000 },
|
||||
),
|
||||
transfer(
|
||||
"budget",
|
||||
"Budget.csv",
|
||||
true,
|
||||
(0, 18_300),
|
||||
TransferState::Queued,
|
||||
),
|
||||
transfer(
|
||||
"moodboard",
|
||||
"Moodboard.png",
|
||||
false,
|
||||
(1_100_000, 3_200_000),
|
||||
TransferState::Paused,
|
||||
),
|
||||
transfer(
|
||||
"survey",
|
||||
"Survey.csv",
|
||||
false,
|
||||
(9_000, 42_000),
|
||||
TransferState::Failed("The server hung up.".into()),
|
||||
),
|
||||
transfer(
|
||||
"brief",
|
||||
"Brief.md",
|
||||
true,
|
||||
(4_800, 4_800),
|
||||
TransferState::Done,
|
||||
),
|
||||
]
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let now = transfers.read(cx).clone();
|
||||
let set = |to: TransferState| {
|
||||
let transfers = transfers.clone();
|
||||
move |key: &SharedString, _: &mut Window, cx: &mut App| {
|
||||
let to = to.clone();
|
||||
change(&transfers, cx, |all| {
|
||||
for each in all.iter_mut().filter(|each| each.key == *key) {
|
||||
each.state = to.clone();
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
let drop = transfers.clone();
|
||||
section(
|
||||
"TransferQueue",
|
||||
"Uploads and downloads in one queue: which way each goes, its bar and status, and pause, resume, retry or cancel as its state allows.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"files-queue",
|
||||
div().w(px(480.)).child(
|
||||
TransferQueue::new("files-queue", now)
|
||||
.pause(set(TransferState::Paused))
|
||||
.resume(set(TransferState::Moving { rate: 4_200_000 }))
|
||||
.retry(set(TransferState::Moving { rate: 2_000_000 }))
|
||||
.cancel(move |key, _, cx| change(&drop, cx, |all| all.retain(|each| each.key != *key))),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn downloads(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let downloads = keep(
|
||||
"files-downloads",
|
||||
|| {
|
||||
vec![
|
||||
transfer(
|
||||
"inter",
|
||||
"Inter-4.1.zip",
|
||||
false,
|
||||
(2_600_000, 6_900_000),
|
||||
TransferState::Moving { rate: 1_800_000 },
|
||||
),
|
||||
transfer(
|
||||
"rust",
|
||||
"rust-1.95.pkg",
|
||||
false,
|
||||
(0, 312_000_000),
|
||||
TransferState::Queued,
|
||||
),
|
||||
transfer(
|
||||
"atrium",
|
||||
"Atrium.jpg",
|
||||
false,
|
||||
(2_140_000, 2_140_000),
|
||||
TransferState::Done,
|
||||
),
|
||||
transfer(
|
||||
"notes",
|
||||
"Release notes.pdf",
|
||||
false,
|
||||
(430_000, 430_000),
|
||||
TransferState::Done,
|
||||
),
|
||||
]
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let now = downloads.read(cx).clone();
|
||||
let (drop, clear) = (downloads.clone(), downloads);
|
||||
section(
|
||||
"DownloadManager",
|
||||
"Downloads as a browser keeps them: those on their way above, the finished below under Clear. A finished one opens with a press and shows its folder.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"files-downloads",
|
||||
div().w(px(480.)).child(
|
||||
DownloadManager::new("files-downloads", now)
|
||||
.open(|key, _, _| log::info!("gallery: open {key}"))
|
||||
.show(|key, _, _| log::info!("gallery: show {key} in its folder"))
|
||||
.cancel(move |key, _, cx| change(&drop, cx, |all| all.retain(|each| each.key != *key)))
|
||||
.on_clear(move |_, cx| {
|
||||
change(&clear, cx, |all| all.retain(|each| each.state != TransferState::Done))
|
||||
}),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn storage(cx: &mut App) -> impl IntoElement + use<> {
|
||||
const GB: f64 = 1_000_000_000.0;
|
||||
section(
|
||||
"StorageUsage",
|
||||
"Where a disk's room goes, as data_display::UsageBar shows it: a part a kind, and what is left free.",
|
||||
cx,
|
||||
)
|
||||
.child(probe(
|
||||
"files-storage",
|
||||
div().w(px(480.)).child(
|
||||
UsageBar::new(512.0 * GB)
|
||||
.part("Documents", 38.0 * GB)
|
||||
.part("Photos", 142.0 * GB)
|
||||
.part("Music", 61.0 * GB)
|
||||
.part("Apps", 96.0 * GB)
|
||||
.amounts(|bytes| format::file_size(bytes as u64, false)),
|
||||
),
|
||||
))
|
||||
}
|
||||
Reference in new issue
Block a user