implement separated widget mod for navigation request feature

This commit is contained in:
yggverse 2024-10-12 00:24:06 +03:00
parent 49c77df278
commit deb3ea3469
6 changed files with 337 additions and 119 deletions

View file

@ -1,104 +1,37 @@
mod database;
mod widget;
use database::Database;
use widget::Widget;
use gtk::{
gio::SimpleAction,
glib::{timeout_add_local, ControlFlow, GString, SourceId, Uri, UriFlags},
prelude::{ActionExt, EditableExt, EntryExt},
glib::{GString, Uri, UriFlags},
Entry,
};
use sqlite::Transaction;
use std::{cell::RefCell, sync::Arc, time::Duration};
// Progressbar animation setup
const PROGRESS_ANIMATION_STEP: f64 = 0.05;
const PROGRESS_ANIMATION_TIME: u64 = 20; //ms
struct Progress {
fraction: RefCell<f64>,
source_id: RefCell<Option<SourceId>>,
}
use std::sync::Arc;
// Main
pub struct Request {
progress: Arc<Progress>,
widget: Entry,
widget: Arc<Widget>,
}
impl Request {
// Construct
pub fn new(
pub fn new_arc(
// Actions
action_update: Arc<SimpleAction>,
action_tab_page_navigation_reload: Arc<SimpleAction>, // @TODO local `action_page_open`?
) -> Self {
// GTK
let widget = Entry::builder()
.placeholder_text("URL or search term...")
.hexpand(true)
.build();
// Connect events
widget.connect_changed(move |_| {
action_update.activate(None);
});
widget.connect_activate(move |_| {
action_tab_page_navigation_reload.activate(None);
});
// Init animated progressbar state
let progress = Arc::new(Progress {
fraction: RefCell::new(0.0),
source_id: RefCell::new(None),
});
// Result
Self { progress, widget }
) -> Arc<Self> {
Arc::new(Self {
widget: Widget::new_arc(action_update, action_tab_page_navigation_reload),
})
}
// Actions
pub fn update(&self, progress_fraction: Option<f64>) {
// Skip update animation for Non value
if let Some(value) = progress_fraction {
// Update shared fraction value for async progressbar function, animate on changed only
if value != self.progress.fraction.replace(value) {
// Start new frame on previous process function completed (`source_id` changed to None)
// If previous process still active, we have just updated shared fraction value before, to use it inside the active process
if self.progress.source_id.borrow().is_none() {
// Start new animation frame iterator, update `source_id`
self.progress.source_id.replace(Some(timeout_add_local(
Duration::from_millis(PROGRESS_ANIMATION_TIME),
{
// Clone async pointers dependency
let widget = self.widget.clone();
let progress = self.progress.clone();
// Frame
move || {
// Animate
if *progress.fraction.borrow() > widget.progress_fraction() {
widget.set_progress_fraction(
// Currently, here is no outrange validation, seems that wrapper make this work @TODO
widget.progress_fraction() + PROGRESS_ANIMATION_STEP,
);
return ControlFlow::Continue;
}
// Deactivate
progress.source_id.replace(None);
// Reset (to hide progress widget)
widget.set_progress_fraction(0.0);
// Stop iteration
ControlFlow::Break
}
},
)));
}
}
}
self.widget.update(progress_fraction);
}
pub fn clean(
@ -112,7 +45,7 @@ impl Request {
match Database::delete(transaction, &record.id) {
Ok(_) => {
// Delegate clean action to the item childs
// nothing yet..
self.widget.clean(transaction, &record.id)?;
}
Err(e) => return Err(e.to_string()),
}
@ -132,12 +65,8 @@ impl Request {
match Database::records(transaction, app_browser_window_tab_item_page_navigation_id) {
Ok(records) => {
for record in records {
if let Some(text) = record.text {
self.widget.set_text(&text);
}
// Delegate restore action to the item childs
// nothing yet..
self.widget.restore(transaction, &record.id)?;
}
}
Err(e) => return Err(e.to_string()),
@ -151,22 +80,12 @@ impl Request {
transaction: &Transaction,
app_browser_window_tab_item_page_navigation_id: &i64,
) -> Result<(), String> {
// Keep value in memory until operation complete
let text = self.widget.text();
match Database::add(
transaction,
app_browser_window_tab_item_page_navigation_id,
match text.is_empty() {
true => None,
false => Some(text.as_str()),
},
) {
match Database::add(transaction, app_browser_window_tab_item_page_navigation_id) {
Ok(_) => {
// let id = Database::last_insert_id(transaction);
let id = Database::last_insert_id(transaction);
// Delegate save action to childs
// nothing yet..
self.widget.save(transaction, &id)?;
}
Err(e) => return Err(e.to_string()),
}
@ -180,12 +99,12 @@ impl Request {
}
// Getters
pub fn widget(&self) -> &Entry {
&self.widget
pub fn gobject(&self) -> &Entry {
&self.widget.gobject()
}
pub fn is_empty(&self) -> bool {
0 == self.widget.text_length()
self.widget.is_empty()
}
pub fn text(&self) -> GString {
@ -207,7 +126,7 @@ impl Request {
}
// Delegate migration to childs
// nothing yet..
Widget::migrate(tx)?;
// Success
Ok(())