Improve display of paused state
This commit is contained in:
parent
2109c8c3d6
commit
49595d87f3
3 changed files with 90 additions and 58 deletions
|
|
@ -29,7 +29,8 @@ size = Size
|
|||
# Progress footer
|
||||
details = Details
|
||||
dismiss = Dismiss message
|
||||
operations-in-progress = {$count} actions in progress ({$percent}%)...
|
||||
operations-running = {$running} operations running ({$percent}%)...
|
||||
operations-running-finished = {$running} operations running ({$percent}%), {$finished} finished...
|
||||
pause = Pause
|
||||
resume = Resume
|
||||
|
||||
|
|
@ -138,12 +139,15 @@ edit-history = Edit history
|
|||
history = History
|
||||
no-history = No items in history.
|
||||
pending = Pending
|
||||
progress = {$percent}%
|
||||
progress-cancelled = {$percent}%, cancelled
|
||||
progress-paused = {$percent}%, paused
|
||||
failed = Failed
|
||||
complete = Complete
|
||||
compressing = Compressing {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from "{$from}" to "{$to}" ({$percent}%)...
|
||||
} from "{$from}" to "{$to}" ({$progress})...
|
||||
compressed = Compressed {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
|
|
@ -154,17 +158,17 @@ created = Created "{$name}" in "{$parent}"
|
|||
copying = Copying {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from "{$from}" to "{$to}" ({$percent}%)...
|
||||
} from "{$from}" to "{$to}" ({$progress})...
|
||||
copied = Copied {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from "{$from}" to "{$to}"
|
||||
emptying-trash = Emptying {trash} ({$percent}%)...
|
||||
emptying-trash = Emptying {trash} ({$progress})...
|
||||
emptied-trash = Emptied {trash}
|
||||
extracting = Extracting {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from "{$from}" to "{$to}" ({$percent}%)...
|
||||
} from "{$from}" to "{$to}" ({$progress})...
|
||||
extracted = Extracted {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
|
|
@ -174,7 +178,7 @@ set-executable-and-launched = Set "{$name}" as executable and launched
|
|||
moving = Moving {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from "{$from}" to "{$to}" ({$percent}%)...
|
||||
} from "{$from}" to "{$to}" ({$progress})...
|
||||
moved = Moved {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
|
|
@ -184,7 +188,7 @@ renamed = Renamed "{$from}" to "{$to}"
|
|||
restoring = Restoring {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
} from {trash} ({$percent})...
|
||||
} from {trash} ({$progress})...
|
||||
restored = Restored {$items} {$items ->
|
||||
[one] item
|
||||
*[other] items
|
||||
|
|
|
|||
54
src/app.rs
54
src/app.rs
|
|
@ -524,7 +524,7 @@ pub struct App {
|
|||
pending_operations: BTreeMap<u64, (Operation, f32, Controller)>,
|
||||
progress_operations: BTreeSet<u64>,
|
||||
complete_operations: BTreeMap<u64, Operation>,
|
||||
failed_operations: BTreeMap<u64, (Operation, f32, String)>,
|
||||
failed_operations: BTreeMap<u64, (Operation, f32, Controller, String)>,
|
||||
search_id: widget::Id,
|
||||
#[cfg(feature = "wayland")]
|
||||
surface_ids: HashMap<WlOutput, WindowId>,
|
||||
|
|
@ -1218,6 +1218,8 @@ impl App {
|
|||
}
|
||||
|
||||
fn edit_history(&self) -> Element<Message> {
|
||||
let cosmic_theme::Spacing { space_m, .. } = theme::active().cosmic().spacing;
|
||||
|
||||
let mut children = Vec::new();
|
||||
|
||||
//TODO: get height from theme?
|
||||
|
|
@ -1265,7 +1267,7 @@ impl App {
|
|||
])
|
||||
.align_y(Alignment::Center)
|
||||
.into(),
|
||||
widget::text(op.pending_text(*progress as i32)).into(),
|
||||
widget::text(op.pending_text(*progress as i32, controller.state())).into(),
|
||||
]));
|
||||
}
|
||||
children.push(section.into());
|
||||
|
|
@ -1273,9 +1275,9 @@ impl App {
|
|||
|
||||
if !self.failed_operations.is_empty() {
|
||||
let mut section = widget::settings::section().title(fl!("failed"));
|
||||
for (_id, (op, progress, error)) in self.failed_operations.iter().rev() {
|
||||
for (_id, (op, progress, controller, error)) in self.failed_operations.iter().rev() {
|
||||
section = section.add(widget::column::with_children(vec![
|
||||
widget::text(op.pending_text(*progress as i32)).into(),
|
||||
widget::text(op.pending_text(*progress as i32, controller.state())).into(),
|
||||
widget::text(error).into(),
|
||||
]));
|
||||
}
|
||||
|
|
@ -1294,7 +1296,9 @@ impl App {
|
|||
children.push(widget::text::body(fl!("no-history")).into());
|
||||
}
|
||||
|
||||
widget::column::with_children(children).into()
|
||||
widget::column::with_children(children)
|
||||
.spacing(space_m)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn preview<'a>(
|
||||
|
|
@ -2419,12 +2423,14 @@ impl Application for App {
|
|||
}
|
||||
Message::PendingError(id, err) => {
|
||||
if let Some((op, progress, controller)) = self.pending_operations.remove(&id) {
|
||||
self.failed_operations.insert(id, (op, progress, err));
|
||||
// Only show dialog if not cancelled
|
||||
if !controller.is_cancelled() {
|
||||
self.dialog_pages.push_back(DialogPage::FailedOperation(id));
|
||||
}
|
||||
// Remove from progress
|
||||
self.progress_operations.remove(&id);
|
||||
self.failed_operations
|
||||
.insert(id, (op, progress, controller, err));
|
||||
}
|
||||
// Close progress notification if all relavent operations are finished
|
||||
if !self
|
||||
|
|
@ -3421,7 +3427,7 @@ impl Application for App {
|
|||
),
|
||||
DialogPage::FailedOperation(id) => {
|
||||
//TODO: try next dialog page (making sure index is used by Dialog messages)?
|
||||
let (operation, _, err) = self.failed_operations.get(id)?;
|
||||
let (operation, _, _, err) = self.failed_operations.get(id)?;
|
||||
|
||||
//TODO: nice description of error
|
||||
widget::dialog()
|
||||
|
|
@ -3874,25 +3880,37 @@ impl Application for App {
|
|||
}
|
||||
if op.show_progress_notification() {
|
||||
if title.is_empty() {
|
||||
title = op.pending_text(*progress as i32);
|
||||
title = op.pending_text(*progress as i32, controller.state());
|
||||
}
|
||||
total_progress += progress;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
let in_progress_count = count;
|
||||
let running = count;
|
||||
// Adjust the progress bar so it does not jump around when operations finish
|
||||
while count < self.progress_operations.len() {
|
||||
total_progress += 100.0;
|
||||
count += 1;
|
||||
for id in self.progress_operations.iter() {
|
||||
if self.complete_operations.contains_key(&id) {
|
||||
total_progress += 100.0;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
let finished = count - running;
|
||||
total_progress /= count as f32;
|
||||
if in_progress_count > 1 {
|
||||
title = fl!(
|
||||
"operations-in-progress",
|
||||
count = in_progress_count,
|
||||
percent = (total_progress as i32)
|
||||
);
|
||||
if running > 1 {
|
||||
if finished > 0 {
|
||||
title = fl!(
|
||||
"operations-running-finished",
|
||||
running = running,
|
||||
finished = finished,
|
||||
percent = (total_progress as i32)
|
||||
);
|
||||
} else {
|
||||
title = fl!(
|
||||
"operations-running",
|
||||
running = running,
|
||||
percent = (total_progress as i32)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: get height from theme?
|
||||
|
|
|
|||
|
|
@ -224,8 +224,15 @@ fn zip_extract<R: io::Read + io::Seek, P: AsRef<Path>>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ControllerState {
|
||||
Cancelled,
|
||||
Paused,
|
||||
Running,
|
||||
}
|
||||
|
||||
struct ControllerInner {
|
||||
state: Mutex<u32>,
|
||||
state: Mutex<ControllerState>,
|
||||
condvar: Condvar,
|
||||
}
|
||||
|
||||
|
|
@ -235,14 +242,10 @@ pub struct Controller {
|
|||
}
|
||||
|
||||
impl Controller {
|
||||
const RUNNING: u32 = 0;
|
||||
const PAUSED: u32 = 1;
|
||||
const CANCELLED: u32 = 2;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: Arc::new(ControllerInner {
|
||||
state: Mutex::new(Self::RUNNING),
|
||||
state: Mutex::new(ControllerState::Running),
|
||||
condvar: Condvar::new(),
|
||||
}),
|
||||
}
|
||||
|
|
@ -251,42 +254,44 @@ impl Controller {
|
|||
pub fn check(&self) -> Result<(), String> {
|
||||
let mut state = self.inner.state.lock().unwrap();
|
||||
loop {
|
||||
if *state == Self::CANCELLED {
|
||||
return Err(fl!("cancelled"));
|
||||
} else if *state == Self::PAUSED {
|
||||
state = self.inner.condvar.wait(state).unwrap();
|
||||
} else {
|
||||
return Ok(());
|
||||
match *state {
|
||||
ControllerState::Cancelled => return Err(fl!("cancelled")),
|
||||
ControllerState::Paused => {
|
||||
state = self.inner.condvar.wait(state).unwrap();
|
||||
}
|
||||
ControllerState::Running => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn state(&self) -> ControllerState {
|
||||
*self.inner.state.lock().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_state(&self, state: ControllerState) {
|
||||
*self.inner.state.lock().unwrap() = state;
|
||||
self.inner.condvar.notify_all();
|
||||
}
|
||||
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
let state = self.inner.state.lock().unwrap();
|
||||
*state == Self::CANCELLED
|
||||
matches!(self.state(), ControllerState::Cancelled)
|
||||
}
|
||||
|
||||
pub fn cancel(&self) {
|
||||
let mut state = self.inner.state.lock().unwrap();
|
||||
*state = Self::CANCELLED;
|
||||
self.inner.condvar.notify_all();
|
||||
self.set_state(ControllerState::Cancelled);
|
||||
}
|
||||
|
||||
pub fn is_paused(&self) -> bool {
|
||||
let state = self.inner.state.lock().unwrap();
|
||||
*state == Self::PAUSED
|
||||
matches!(self.state(), ControllerState::Paused)
|
||||
}
|
||||
|
||||
pub fn pause(&self) {
|
||||
let mut state = self.inner.state.lock().unwrap();
|
||||
*state = Self::PAUSED;
|
||||
self.inner.condvar.notify_all();
|
||||
self.set_state(ControllerState::Paused);
|
||||
}
|
||||
|
||||
pub fn unpause(&self) {
|
||||
let mut state = self.inner.state.lock().unwrap();
|
||||
*state = Self::RUNNING;
|
||||
self.inner.condvar.notify_all();
|
||||
//TODO: ensure this does not override Cancel?
|
||||
self.set_state(ControllerState::Running);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -528,43 +533,48 @@ fn paths_parent_name<'a>(paths: &'a Vec<PathBuf>) -> Cow<'a, str> {
|
|||
}
|
||||
|
||||
impl Operation {
|
||||
pub fn pending_text(&self, percent: i32) -> String {
|
||||
pub fn pending_text(&self, percent: i32, state: ControllerState) -> String {
|
||||
let progress = || match state {
|
||||
ControllerState::Running => fl!("progress", percent = percent),
|
||||
ControllerState::Paused => fl!("progress-paused", percent = percent),
|
||||
ControllerState::Cancelled => fl!("progress-cancelled", percent = percent),
|
||||
};
|
||||
match self {
|
||||
Self::Compress { paths, to, .. } => fl!(
|
||||
"compressing",
|
||||
items = paths.len(),
|
||||
from = paths_parent_name(paths),
|
||||
to = file_name(to),
|
||||
percent = percent
|
||||
progress = progress()
|
||||
),
|
||||
Self::Copy { paths, to } => fl!(
|
||||
"copying",
|
||||
items = paths.len(),
|
||||
from = paths_parent_name(paths),
|
||||
to = file_name(to),
|
||||
percent = percent
|
||||
progress = progress()
|
||||
),
|
||||
Self::Delete { paths } => fl!(
|
||||
"moving",
|
||||
items = paths.len(),
|
||||
from = paths_parent_name(paths),
|
||||
to = fl!("trash"),
|
||||
percent = percent
|
||||
progress = progress()
|
||||
),
|
||||
Self::EmptyTrash => fl!("emptying-trash", percent = percent),
|
||||
Self::EmptyTrash => fl!("emptying-trash", progress = progress()),
|
||||
Self::Extract { paths, to } => fl!(
|
||||
"extracting",
|
||||
items = paths.len(),
|
||||
from = paths_parent_name(paths),
|
||||
to = file_name(to),
|
||||
percent = percent
|
||||
progress = progress()
|
||||
),
|
||||
Self::Move { paths, to } => fl!(
|
||||
"moving",
|
||||
items = paths.len(),
|
||||
from = paths_parent_name(paths),
|
||||
to = file_name(to),
|
||||
percent = percent
|
||||
progress = progress()
|
||||
),
|
||||
Self::NewFile { path } => fl!(
|
||||
"creating",
|
||||
|
|
@ -579,7 +589,7 @@ impl Operation {
|
|||
Self::Rename { from, to } => {
|
||||
fl!("renaming", from = file_name(from), to = file_name(to))
|
||||
}
|
||||
Self::Restore { paths } => fl!("restoring", items = paths.len(), percent = percent),
|
||||
Self::Restore { paths } => fl!("restoring", items = paths.len(), progress = progress()),
|
||||
Self::SetExecutableAndLaunch { path } => {
|
||||
fl!("setting-executable-and-launching", name = file_name(path))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue