mod database;
use database::Database;
use gtk::{
gio::SimpleAction,
glib::{timeout_add_local, ControlFlow, GString, SourceId},
prelude::{ActionExt, EditableExt, EntryExt, ToVariant},
Entry,
};
use sqlite::Transaction;
use std::{cell::RefCell, sync::Arc, time::Duration};
const PLACEHOLDER_TEXT: &str = "URL or search term...";
const PROGRESS_ANIMATION_STEP: f64 = 0.05;
const PROGRESS_ANIMATION_TIME: u64 = 20;
struct Progress {
fraction: RefCell<f64>,
source_id: RefCell<Option<SourceId>>,
}
pub struct Widget {
gobject: Entry,
progress: Arc<Progress>,
}
impl Widget {
pub fn new_arc(
action_update: SimpleAction,
action_tab_page_navigation_reload: SimpleAction, ) -> Arc<Self> {
let progress = Arc::new(Progress {
fraction: RefCell::new(0.0),
source_id: RefCell::new(None),
});
let gobject = Entry::builder()
.placeholder_text(PLACEHOLDER_TEXT)
.hexpand(true)
.build();
gobject.connect_changed(move |_| {
action_update.activate(Some(&"".to_variant())); });
gobject.connect_activate(move |_| {
action_tab_page_navigation_reload.activate(None);
});
Arc::new(Self { gobject, progress })
}
pub fn clean(
&self,
transaction: &Transaction,
app_browser_window_tab_item_page_navigation_request_id: &i64,
) -> Result<(), String> {
match Database::records(
transaction,
app_browser_window_tab_item_page_navigation_request_id,
) {
Ok(records) => {
for record in records {
match Database::delete(transaction, &record.id) {
Ok(_) => {
}
Err(e) => return Err(e.to_string()),
}
}
}
Err(e) => return Err(e.to_string()),
}
Ok(())
}
pub fn restore(
&self,
transaction: &Transaction,
app_browser_window_tab_item_page_navigation_request_id: &i64,
) -> Result<(), String> {
match Database::records(
transaction,
app_browser_window_tab_item_page_navigation_request_id,
) {
Ok(records) => {
for record in records {
if let Some(text) = record.text {
self.gobject.set_text(&text);
}
}
}
Err(e) => return Err(e.to_string()),
}
Ok(())
}
pub fn save(
&self,
transaction: &Transaction,
app_browser_window_tab_item_page_navigation_request_id: &i64,
) -> Result<(), String> {
let text = self.gobject.text();
match Database::add(
transaction,
app_browser_window_tab_item_page_navigation_request_id,
match text.is_empty() {
true => None,
false => Some(text.as_str()),
},
) {
Ok(_) => {
}
Err(e) => return Err(e.to_string()),
}
Ok(())
}
pub fn update(&self, progress_fraction: Option<f64>) {
if let Some(value) = progress_fraction {
if value != self.progress.fraction.replace(value) {
if self.progress.source_id.borrow().is_none() {
self.progress.source_id.replace(Some(timeout_add_local(
Duration::from_millis(PROGRESS_ANIMATION_TIME),
{
let gobject = self.gobject.clone();
let progress = self.progress.clone();
move || {
if *progress.fraction.borrow() > gobject.progress_fraction() {
gobject.set_progress_fraction(
gobject.progress_fraction() + PROGRESS_ANIMATION_STEP,
);
return ControlFlow::Continue;
}
progress.source_id.replace(None);
if gobject.progress_fraction() == 1.0 {
gobject.set_progress_fraction(0.0);
}
ControlFlow::Break
}
},
)));
}
}
}
}
pub fn set_text(&self, value: &str) {
self.gobject.set_text(value);
}
pub fn gobject(&self) -> &Entry {
&self.gobject
}
pub fn is_empty(&self) -> bool {
0 == self.gobject.text_length()
}
pub fn text(&self) -> GString {
self.gobject.text()
}
pub fn migrate(tx: &Transaction) -> Result<(), String> {
if let Err(e) = Database::init(&tx) {
return Err(e.to_string());
}
Ok(())
}
}