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.
249 lines
7.5 KiB
Rust
249 lines
7.5 KiB
Rust
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)),
|
|
),
|
|
))
|
|
}
|