fix animated progressbar feature

This commit is contained in:
yggverse 2024-09-29 22:51:43 +03:00
parent cbea5335b6
commit 273d41d577
2 changed files with 55 additions and 20 deletions

View File

@ -402,7 +402,7 @@ impl Page {
Some(Status::Prepare) => 0.25, Some(Status::Prepare) => 0.25,
Some(Status::Connect) => 0.50, Some(Status::Connect) => 0.50,
Some(Status::Request) => 0.75, Some(Status::Request) => 0.75,
Some(Status::Response) => 1.0, Some(Status::Response | Status::Success) => 1.0,
_ => 0.0, _ => 0.0,
}; };

View File

@ -1,16 +1,24 @@
use gtk::{ use gtk::{
gio::SimpleAction, gio::SimpleAction,
glib::{timeout_add_local, ControlFlow, GString, Uri, UriFlags}, glib::{timeout_add_local, ControlFlow, GString, SourceId, Uri, UriFlags},
prelude::{ActionExt, EditableExt, EntryExt}, prelude::{ActionExt, EditableExt, EntryExt},
Entry, Entry,
}; };
use std::{sync::Arc, time::Duration}; use std::{cell::RefCell, sync::Arc, time::Duration};
const PROGRESS_ANIMATION_STEP: f64 = 0.2; // Progressbar animation setup
const PROGRESS_ANIMATION_TIME: u64 = 25; const PROGRESS_ANIMATION_STEP: f64 = 0.05;
const PROGRESS_ANIMATION_TIME: u64 = 25; //ms
struct Progress {
fraction: RefCell<f64>,
source_id: RefCell<Option<SourceId>>,
}
// Main
pub struct Request { pub struct Request {
progress: Arc<Progress>,
widget: Entry, widget: Entry,
} }
@ -41,26 +49,53 @@ impl Request {
action_tab_page_reload.activate(None); action_tab_page_reload.activate(None);
}); });
// Init animated progressbar state
let progress = Arc::new(Progress {
fraction: RefCell::new(0.0),
source_id: RefCell::new(None),
});
// Result // Result
Self { widget } Self { progress, widget }
} }
// Actions // Actions
pub fn update(&self, progress_fraction: f64) { pub fn update(&self, progress_fraction: f64) {
// Animate progress fraction update // Update shared fraction value for async progressbar animation
timeout_add_local(Duration::from_millis(PROGRESS_ANIMATION_TIME), { self.progress.fraction.replace(progress_fraction);
let widget = self.widget.clone();
move || { // Start new frame on previous process completed only (`source_id` is None)
if progress_fraction > widget.progress_fraction() { // If previous process still active, we have just updated shared fraction value before, to use it inside the active process
widget.set_progress_fraction( if self.progress.source_id.borrow().is_none() {
widget.progress_fraction() + PROGRESS_ANIMATION_STEP, // Start new animation frame iterator, update `source_id`
); self.progress.source_id.replace(Some(timeout_add_local(
return ControlFlow::Continue; Duration::from_millis(PROGRESS_ANIMATION_TIME),
} {
widget.set_progress_fraction(progress_fraction); // Clone async pointers dependency
ControlFlow::Break let widget = self.widget.clone();
} let progress = self.progress.clone();
});
// Frame
move || {
// Animate
if *progress.fraction.borrow() > widget.progress_fraction() {
widget.set_progress_fraction(
widget.progress_fraction() + PROGRESS_ANIMATION_STEP,
);
return ControlFlow::Continue;
}
// Deactivate
progress.source_id.replace(None);
// Reset
widget.set_progress_fraction(0.0);
// Stop iteration
ControlFlow::Break
}
},
)));
}
} }
// Setters // Setters