From 913030a95580248f5ee2752019d7f25c4c2d3154 Mon Sep 17 00:00:00 2001 From: yggverse Date: Sat, 25 Jan 2025 17:28:05 +0200 Subject: [PATCH] add new tab item action group, delegate history handle to action implementation --- src/app/browser.rs | 11 +- src/app/browser/window/tab.rs | 20 +-- src/app/browser/window/tab/action.rs | 25 ++++ src/app/browser/window/tab/item.rs | 30 ++++- src/app/browser/window/tab/item/action.rs | 16 ++- .../browser/window/tab/item/action/history.rs | 79 ++++++++++++ .../window/tab/item/action/history/back.rs | 13 ++ .../window/tab/item/action/history/forward.rs | 13 ++ .../window/tab/item/action/history/memory.rs | 68 ++++++++++ .../tab/item/action/history/memory/cursor.rs | 66 ++++++++++ src/app/browser/window/tab/item/client.rs | 9 +- .../window/tab/item/client/driver/gemini.rs | 8 +- src/app/browser/window/tab/item/page.rs | 16 +-- .../browser/window/tab/item/page/content.rs | 14 +-- .../window/tab/item/page/content/status.rs | 2 +- .../tab/item/page/content/status/mime.rs | 4 +- .../window/tab/item/page/content/text.rs | 6 +- .../tab/item/page/content/text/gemini.rs | 6 +- .../item/page/content/text/gemini/reader.rs | 6 +- src/app/browser/window/tab/item/page/input.rs | 6 +- .../window/tab/item/page/input/response.rs | 6 +- .../window/tab/item/page/input/sensitive.rs | 6 +- .../window/tab/item/page/navigation.rs | 19 ++- .../tab/item/page/navigation/history.rs | 117 +++--------------- .../tab/item/page/navigation/history/back.rs | 14 +-- .../item/page/navigation/history/forward.rs | 14 +-- .../item/page/navigation/history/widget.rs | 27 ---- .../tab/item/page/navigation/request.rs | 6 +- .../item/page/navigation/request/widget.rs | 14 +-- 29 files changed, 409 insertions(+), 232 deletions(-) create mode 100644 src/app/browser/window/tab/action.rs create mode 100644 src/app/browser/window/tab/item/action/history.rs create mode 100644 src/app/browser/window/tab/item/action/history/back.rs create mode 100644 src/app/browser/window/tab/item/action/history/forward.rs create mode 100644 src/app/browser/window/tab/item/action/history/memory.rs create mode 100644 src/app/browser/window/tab/item/action/history/memory/cursor.rs delete mode 100644 src/app/browser/window/tab/item/page/navigation/history/widget.rs diff --git a/src/app/browser.rs b/src/app/browser.rs index 1fb9a3cf..0b597f08 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -37,17 +37,22 @@ impl Browser { let widget = Rc::new(Widget::new( &window.widget.g_box, &[ - // Connect action groups (to apply accels) + // action groups ( - // Browser + // browser &action.id, action.simple_action_group.clone(), ), ( - // Window + // window &window.action.id, window.action.simple_action_group.clone(), ), + ( + // tab + &window.tab.action.id, + window.tab.action.simple_action_group.clone(), + ), ], )); diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index 2306eb3f..0389df59 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -1,9 +1,11 @@ +mod action; mod database; mod error; mod item; mod menu; mod widget; +use action::Action; use error::Error; pub use item::Item; use menu::Menu; @@ -27,6 +29,7 @@ pub struct Tab { window_action: Rc, profile: Rc, index: Rc, Rc>>>, + pub action: Rc, pub widget: Rc, } @@ -38,6 +41,8 @@ impl Tab { profile: &Rc, (browser_action, window_action): (&Rc, &Rc), ) -> Self { + let action = Rc::new(Action::new()); + // Init empty HashMap index let index: Rc, Rc>>> = Rc::new(RefCell::new(HashMap::new())); @@ -142,6 +147,7 @@ impl Tab { window_action: window_action.clone(), index, widget, + action, } } @@ -160,7 +166,7 @@ impl Tab { &self.widget.tab_view, &self.profile, // Actions - (&self.browser_action, &self.window_action), + (&self.browser_action, &self.window_action, &self.action), // Options ( position, @@ -260,19 +266,13 @@ impl Tab { pub fn page_history_back(&self, page_position: Option) { if let Some(item) = self.item(page_position) { - if let Some(back) = item.page.navigation.history.back(true) { - item.page.navigation.request.widget.entry.set_text(&back); - item.client.handle(&back, false); - } + item.action.history.back(true); } } pub fn page_history_forward(&self, page_position: Option) { if let Some(item) = self.item(page_position) { - if let Some(forward) = item.page.navigation.history.forward(true) { - item.page.navigation.request.widget.entry.set_text(&forward); - item.client.handle(&forward, false); - } + item.action.history.forward(true); } } @@ -338,7 +338,7 @@ impl Tab { transaction, record.id, &self.profile, - (&self.browser_action, &self.window_action), + (&self.browser_action, &self.window_action, &self.action), ) { Ok(items) => { for item in items { diff --git a/src/app/browser/window/tab/action.rs b/src/app/browser/window/tab/action.rs new file mode 100644 index 00000000..20c76f4b --- /dev/null +++ b/src/app/browser/window/tab/action.rs @@ -0,0 +1,25 @@ +use gtk::{ + gio::SimpleActionGroup, + glib::{uuid_string_random, GString}, +}; + +/// [SimpleActionGroup](https://docs.gtk.org/gio/class.SimpleActionGroup.html) wrapper for `Tab` actions +pub struct Action { + pub id: GString, + pub simple_action_group: SimpleActionGroup, +} + +impl Default for Action { + fn default() -> Self { + Self::new() + } +} + +impl Action { + pub fn new() -> Self { + Self { + id: uuid_string_random(), + simple_action_group: SimpleActionGroup::new(), + } + } +} diff --git a/src/app/browser/window/tab/item.rs b/src/app/browser/window/tab/item.rs index 19172044..d91145eb 100644 --- a/src/app/browser/window/tab/item.rs +++ b/src/app/browser/window/tab/item.rs @@ -15,7 +15,7 @@ use adw::TabView; use client::Client; use gtk::{ glib::{uuid_string_random, GString}, - prelude::{Cast, EditableExt}, + prelude::{ActionExt, ActionMapExt, Cast, EditableExt}, }; use page::Page; use sqlite::Transaction; @@ -31,6 +31,7 @@ pub struct Item { // Components pub page: Rc, pub widget: Rc, + pub action: Rc, } impl Item { @@ -40,7 +41,11 @@ impl Item { pub fn build( tab_view: &TabView, profile: &Rc, - (browser_action, window_action): (&Rc, &Rc), + (browser_action, window_action, tab_action): ( + &Rc, + &Rc, + &Rc, + ), (position, request, is_pinned, is_selected, is_attention, is_load): ( Position, Option, @@ -57,10 +62,22 @@ impl Item { let action = Rc::new(Action::new()); + tab_action + .simple_action_group + .add_action(&action.history.back); + + tab_action + .simple_action_group + .add_action(&action.history.forward); + let page = Rc::new(Page::build( &id, profile, (browser_action, window_action, &action), + ( + &format!("{}.{}", &tab_action.id, action.history.back.name()), + &format!("{}.{}", &tab_action.id, action.history.forward.name()), + ), )); let widget = Rc::new(Widget::build( @@ -128,6 +145,7 @@ impl Item { client, page, widget, + action, } } @@ -169,7 +187,11 @@ impl Item { app_browser_window_tab_id: i64, profile: &Rc, // Actions - (browser_action, window_action): (&Rc, &Rc), + (browser_action, window_action, item_action): ( + &Rc, + &Rc, + &Rc, + ), ) -> Result>, String> { let mut items = Vec::new(); @@ -181,7 +203,7 @@ impl Item { tab_view, profile, // Actions - (browser_action, window_action), + (browser_action, window_action, item_action), // Options tuple ( Position::End, diff --git a/src/app/browser/window/tab/item/action.rs b/src/app/browser/window/tab/item/action.rs index 16ad917c..e93b5f7e 100644 --- a/src/app/browser/window/tab/item/action.rs +++ b/src/app/browser/window/tab/item/action.rs @@ -1,6 +1,8 @@ +mod history; mod ident; mod load; +use history::History; use ident::Ident; use load::Load; @@ -8,6 +10,7 @@ use std::rc::Rc; /// [SimpleActionGroup](https://docs.gtk.org/gio/class.SimpleActionGroup.html) wrapper for `Browser` actions pub struct Action { + pub history: Rc, pub ident: Rc, pub load: Rc, } @@ -23,9 +26,18 @@ impl Action { /// Create new `Self` pub fn new() -> Self { + let ident = Rc::new(Ident::new()); + let load = Rc::new(Load::new()); + + let history = Rc::new(History::build({ + let load = load.clone(); + move |request| load.activate(Some(&request), false) + })); + Self { - ident: Rc::new(Ident::new()), - load: Rc::new(Load::new()), + history, + ident, + load, } } } diff --git a/src/app/browser/window/tab/item/action/history.rs b/src/app/browser/window/tab/item/action/history.rs new file mode 100644 index 00000000..14dab83e --- /dev/null +++ b/src/app/browser/window/tab/item/action/history.rs @@ -0,0 +1,79 @@ +mod back; +mod forward; +mod memory; + +use back::Back; +use forward::Forward; +use gtk::{gio::SimpleAction, glib::GString}; +use memory::Memory; +use std::rc::Rc; + +pub struct History { + memory: Rc, + pub back: SimpleAction, + pub forward: SimpleAction, +} + +impl History { + // Constructors + + /// Build new activated `Self` + pub fn build(callback: impl Fn(GString) + 'static) -> Self { + // Init childs + let memory = Rc::new(Memory::new()); + let back = SimpleAction::back(); + let forward = SimpleAction::forward(); + + // Init events + let callback = Rc::new(callback); + + back.connect_activate({ + let callback = callback.clone(); + let forward = forward.clone(); + let memory = memory.clone(); + move |this, _| { + if let Some(request) = memory.back(true) { + callback(request) + } + forward.set_enabled(memory.next(false).is_some()); + this.set_enabled(memory.back(false).is_some()); + } + }); + + forward.connect_activate({ + let back = back.clone(); + let callback = callback.clone(); + let memory = memory.clone(); + move |this, _| { + if let Some(request) = memory.next(true) { + callback(request) + } + back.set_enabled(memory.back(false).is_some()); + this.set_enabled(memory.next(false).is_some()); + } + }); + + // Done + Self { + memory, + back, + forward, + } + } + + // Actions + + pub fn add(&self, request: GString, follow_to_index: bool) { + self.memory.add(request, follow_to_index); + self.back.set_enabled(self.back(false).is_some()); + self.forward.set_enabled(self.forward(false).is_some()); + } + + pub fn back(&self, follow_to_index: bool) -> Option { + self.memory.back(follow_to_index) + } + + pub fn forward(&self, follow_to_index: bool) -> Option { + self.memory.next(follow_to_index) + } +} diff --git a/src/app/browser/window/tab/item/action/history/back.rs b/src/app/browser/window/tab/item/action/history/back.rs new file mode 100644 index 00000000..225f7f5d --- /dev/null +++ b/src/app/browser/window/tab/item/action/history/back.rs @@ -0,0 +1,13 @@ +use gtk::{gio::SimpleAction, glib::uuid_string_random}; + +pub trait Back { + fn back() -> Self; +} + +impl Back for SimpleAction { + fn back() -> Self { + let back = SimpleAction::new(&uuid_string_random(), None); + back.set_enabled(false); + back + } +} diff --git a/src/app/browser/window/tab/item/action/history/forward.rs b/src/app/browser/window/tab/item/action/history/forward.rs new file mode 100644 index 00000000..154b9fb7 --- /dev/null +++ b/src/app/browser/window/tab/item/action/history/forward.rs @@ -0,0 +1,13 @@ +use gtk::{gio::SimpleAction, glib::uuid_string_random}; + +pub trait Forward { + fn forward() -> Self; +} + +impl Forward for SimpleAction { + fn forward() -> Self { + let forward = SimpleAction::new(&uuid_string_random(), None); + forward.set_enabled(false); + forward + } +} diff --git a/src/app/browser/window/tab/item/action/history/memory.rs b/src/app/browser/window/tab/item/action/history/memory.rs new file mode 100644 index 00000000..0f26bb0b --- /dev/null +++ b/src/app/browser/window/tab/item/action/history/memory.rs @@ -0,0 +1,68 @@ +mod cursor; + +use cursor::Cursor; +use gtk::glib::GString; +use std::cell::RefCell; + +pub struct Memory { + cursor: RefCell, + index: RefCell>, +} + +impl Memory { + // Constructors + + pub fn new() -> Self { + Self { + cursor: RefCell::new(Cursor::new()), + index: RefCell::new(Vec::new()), + } + } + + // Actions + + pub fn add(&self, value: GString, follow_to_index: bool) { + let mut index = self.index.borrow_mut(); + + match index.last() { + Some(last) => { + if *last != value { + index.push(value); + } + } + None => index.push(value), + } + + if follow_to_index { + self.cursor.borrow_mut().go_last(index.len()); + } + } + + pub fn back(&self, follow_to_index: bool) -> Option { + let index = self.index.borrow(); + let len = index.len(); + + match if follow_to_index { + self.cursor.borrow_mut().go_back(len) + } else { + self.cursor.borrow().back(len) + } { + Some(i) => index.get(i).cloned(), + None => None, + } + } + + pub fn next(&self, follow_to_index: bool) -> Option { + let index = self.index.borrow(); + let len = index.len(); + + match if follow_to_index { + self.cursor.borrow_mut().go_next(len) + } else { + self.cursor.borrow().next(len) + } { + Some(i) => index.get(i).cloned(), + None => None, + } + } +} diff --git a/src/app/browser/window/tab/item/action/history/memory/cursor.rs b/src/app/browser/window/tab/item/action/history/memory/cursor.rs new file mode 100644 index 00000000..e734e8be --- /dev/null +++ b/src/app/browser/window/tab/item/action/history/memory/cursor.rs @@ -0,0 +1,66 @@ +pub struct Cursor(Option); + +impl Default for Cursor { + fn default() -> Self { + Self::new() + } +} + +impl Cursor { + // Constructors + + pub fn new() -> Self { + Self(None) + } + + // Actions + + pub fn go_last(&mut self, len: usize) -> Option { + self.0 = len2i(len); + self.0 + } + + pub fn go_next(&mut self, len: usize) -> Option { + self.0 = self.next(len); + self.0 + } + + pub fn go_back(&mut self, len: usize) -> Option { + self.0 = self.back(len); + self.0 + } + + // Getters + + pub fn next(&self, len: usize) -> Option { + let i = len2i(len)?; + let n = self.0.unwrap_or_default(); + + if n < i { + Some(n + 1) + } else { + None + } + } + + pub fn back(&self, len: usize) -> Option { + len2i(len)?; + let n = self.0.unwrap_or_default(); + + if n > 0 { + Some(n - 1) + } else { + None + } + } +} + +// Tools + +fn len2i(len: usize) -> Option { + if len > 0 { + Some(len - 1) + } else { + None + } +} diff --git a/src/app/browser/window/tab/item/client.rs b/src/app/browser/window/tab/item/client.rs index 7205c88d..6e71358b 100644 --- a/src/app/browser/window/tab/item/client.rs +++ b/src/app/browser/window/tab/item/client.rs @@ -105,7 +105,7 @@ impl Client { // begin redirection to new address suggested Err(uri) => subject .page - .tab_action + .item_action .load .activate(Some(&uri.to_string()), false), } @@ -215,10 +215,5 @@ fn snap_history(subject: &Rc, uri: Option<&Uri>) { } // Add new record into the page navigation history - if match subject.page.navigation.history.current() { - Some(current) => current != request, // apply additional filters - None => true, - } { - subject.page.navigation.history.add(request, true) - } + subject.page.item_action.history.add(request, true) } diff --git a/src/app/browser/window/tab/item/client/driver/gemini.rs b/src/app/browser/window/tab/item/client/driver/gemini.rs index 0a359069..47513be0 100644 --- a/src/app/browser/window/tab/item/client/driver/gemini.rs +++ b/src/app/browser/window/tab/item/client/driver/gemini.rs @@ -185,14 +185,14 @@ fn handle( }; if matches!(response.meta.status, Status::SensitiveInput) { subject.page.input.set_new_sensitive( - subject.page.tab_action.clone(), + subject.page.item_action.clone(), uri, Some(&title), Some(1024), ); } else { subject.page.input.set_new_response( - subject.page.tab_action.clone(), + subject.page.item_action.clone(), uri, Some(&title), Some(1024), @@ -369,7 +369,7 @@ fn handle( mime => { let status = subject.page .content - .to_status_mime(mime, Some((&subject.page.tab_action, &uri))); + .to_status_mime(mime, Some((&subject.page.item_action, &uri))); status.set_description(Some(&format!("Content type `{mime}` yet not supported"))); subject.page.navigation.request.widget.entry.set_progress_fraction(0.0); subject.tab_page.set_loading(false); @@ -443,7 +443,7 @@ fn handle( .set_text(&uri.to_string()); } redirects.replace(total); - subject.page.tab_action.load.activate(Some(&target.to_string()), false); + subject.page.item_action.load.activate(Some(&target.to_string()), false); } } Err(e) => { diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index 99c38320..d296d1bc 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -13,7 +13,7 @@ use navigation::Navigation; use search::Search; use widget::Widget; -use super::{Action as TabAction, BrowserAction, Profile, WindowAction}; +use super::{Action as ItemAction, BrowserAction, Profile, WindowAction}; use gtk::{glib::GString, prelude::EditableExt}; use sqlite::Transaction; @@ -24,7 +24,7 @@ pub struct Page { pub profile: Rc, // Actions pub browser_action: Rc, - pub tab_action: Rc, + pub item_action: Rc, pub window_action: Rc, // Components pub content: Rc, @@ -40,20 +40,22 @@ impl Page { pub fn build( id: &Rc, profile: &Rc, - (browser_action, window_action, tab_action): ( + (browser_action, window_action, item_action): ( &Rc, &Rc, - &Rc, + &Rc, ), + (back_action_name, forward_action_name): (&str, &str), ) -> Self { // Init components - let content = Rc::new(Content::build((window_action, tab_action))); + let content = Rc::new(Content::build((window_action, item_action))); let search = Rc::new(Search::new()); let navigation = Rc::new(Navigation::build( profile, - (browser_action, window_action, tab_action), + (browser_action, window_action, item_action), + (back_action_name, forward_action_name), )); let input = Rc::new(Input::new()); @@ -72,7 +74,7 @@ impl Page { profile: profile.clone(), // Actions browser_action: browser_action.clone(), - tab_action: tab_action.clone(), + item_action: item_action.clone(), window_action: window_action.clone(), // Components content, diff --git a/src/app/browser/window/tab/item/page/content.rs b/src/app/browser/window/tab/item/page/content.rs index b7a0b8f2..43e0a97b 100644 --- a/src/app/browser/window/tab/item/page/content.rs +++ b/src/app/browser/window/tab/item/page/content.rs @@ -5,7 +5,7 @@ mod text; use image::Image; use text::Text; -use super::{TabAction, WindowAction}; +use super::{ItemAction, WindowAction}; use adw::StatusPage; use gtk::{ gdk::Paintable, @@ -18,7 +18,7 @@ use std::{rc::Rc, time::Duration}; pub struct Content { window_action: Rc, - tab_action: Rc, + item_action: Rc, pub g_box: Box, } @@ -26,11 +26,11 @@ impl Content { // Construct /// Create new container for different components - pub fn build((window_action, tab_action): (&Rc, &Rc)) -> Self { + pub fn build((window_action, item_action): (&Rc, &Rc)) -> Self { Self { g_box: Box::builder().orientation(Orientation::Vertical).build(), window_action: window_action.clone(), - tab_action: tab_action.clone(), + item_action: item_action.clone(), } } @@ -77,7 +77,7 @@ impl Content { pub fn to_status_mime( &self, mime: &str, - download: Option<(&Rc, &Uri)>, + download: Option<(&Rc, &Uri)>, ) -> StatusPage { self.clean(); let status = status::mime::build(mime, download); @@ -90,7 +90,7 @@ impl Content { /// * action removes previous children component from `Self` pub fn to_status_identity(&self) -> StatusPage { self.clean(); - let status = status::identity::build(self.tab_action.clone()); + let status = status::identity::build(self.item_action.clone()); self.g_box.append(&status); status } @@ -122,7 +122,7 @@ impl Content { /// * could be useful to extract document title parsed from Gemtext pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text { self.clean(); - let text = Text::new_gemini(data, base, (&self.window_action, &self.tab_action)); + let text = Text::new_gemini(data, base, (&self.window_action, &self.item_action)); self.g_box.append(&text.g_box); text } diff --git a/src/app/browser/window/tab/item/page/content/status.rs b/src/app/browser/window/tab/item/page/content/status.rs index ee1bf7c8..209e63d6 100644 --- a/src/app/browser/window/tab/item/page/content/status.rs +++ b/src/app/browser/window/tab/item/page/content/status.rs @@ -4,4 +4,4 @@ pub mod identity; pub mod loading; pub mod mime; -use super::TabAction; +use super::ItemAction; diff --git a/src/app/browser/window/tab/item/page/content/status/mime.rs b/src/app/browser/window/tab/item/page/content/status/mime.rs index 3a917b5f..dd127854 100644 --- a/src/app/browser/window/tab/item/page/content/status/mime.rs +++ b/src/app/browser/window/tab/item/page/content/status/mime.rs @@ -1,11 +1,11 @@ -use super::TabAction; +use super::ItemAction; use adw::StatusPage; use gtk::{glib::Uri, prelude::ButtonExt, Align, Button}; use std::rc::Rc; /// Create new default `GObject` preset for mime issue /// [StatusPage](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.StatusPage.html) -pub fn build(mime: &str, download: Option<(&Rc, &Uri)>) -> StatusPage { +pub fn build(mime: &str, download: Option<(&Rc, &Uri)>) -> StatusPage { let status_page = StatusPage::builder() .description(format!("Content type `{mime}` not supported!")) .icon_name("dialog-question-symbolic") diff --git a/src/app/browser/window/tab/item/page/content/text.rs b/src/app/browser/window/tab/item/page/content/text.rs index e3923d65..1d2f8297 100644 --- a/src/app/browser/window/tab/item/page/content/text.rs +++ b/src/app/browser/window/tab/item/page/content/text.rs @@ -4,7 +4,7 @@ mod source; use gemini::Gemini; use source::Source; -use super::{TabAction, WindowAction}; +use super::{ItemAction, WindowAction}; use gtk::{ glib::Uri, prelude::{BoxExt, Cast}, @@ -28,10 +28,10 @@ impl Text { pub fn new_gemini( gemtext: &str, base: &Uri, - (window_action, tab_action): (&Rc, &Rc), + (window_action, item_action): (&Rc, &Rc), ) -> Self { // Init components - let gemini = Gemini::new(gemtext, base, (window_action, tab_action)); + let gemini = Gemini::new(gemtext, base, (window_action, item_action)); // Init main widget let g_box = Box::builder().orientation(Orientation::Vertical).build(); diff --git a/src/app/browser/window/tab/item/page/content/text/gemini.rs b/src/app/browser/window/tab/item/page/content/text/gemini.rs index 62ca88fe..24334a1b 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini.rs @@ -4,7 +4,7 @@ mod widget; use reader::Reader; use widget::Widget; -use crate::app::browser::window::{tab::item::Action as TabAction, Action as WindowAction}; +use crate::app::browser::window::{tab::item::Action as ItemAction, Action as WindowAction}; use gtk::glib::Uri; use std::rc::Rc; @@ -18,11 +18,11 @@ impl Gemini { pub fn new( gemtext: &str, base: &Uri, - (window_action, tab_action): (&Rc, &Rc), + (window_action, item_action): (&Rc, &Rc), ) -> Self { // Init components let reader = Rc::new( - Reader::new(gemtext, base, (window_action.clone(), tab_action.clone())).unwrap(), + Reader::new(gemtext, base, (window_action.clone(), item_action.clone())).unwrap(), ); // @TODO handle errors let widget = Rc::new(Widget::new(&reader.widget.text_view)); diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs index a0717769..abb44ff2 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs @@ -9,7 +9,7 @@ use syntax::Syntax; use tag::Tag; use widget::Widget; -use super::{TabAction, WindowAction}; +use super::{ItemAction, WindowAction}; use crate::app::browser::window::action::Position; use ggemtext::line::{ code::{Inline, Multiline}, @@ -43,7 +43,7 @@ impl Reader { pub fn new( gemtext: &str, base: &Uri, - (window_action, tab_action): (Rc, Rc), + (window_action, item_action): (Rc, Rc), ) -> Result { // Init default values let mut title = None; @@ -332,7 +332,7 @@ impl Reader { return match uri.scheme().as_str() { "gemini" | "titan" => { // Open new page in browser - tab_action.load.activate(Some(&uri.to_str()), true); + item_action.load.activate(Some(&uri.to_str()), true); } // Scheme not supported, delegate _ => UriLauncher::new(&uri.to_str()).launch( diff --git a/src/app/browser/window/tab/item/page/input.rs b/src/app/browser/window/tab/item/page/input.rs index 7c936d4b..5e7f6e51 100644 --- a/src/app/browser/window/tab/item/page/input.rs +++ b/src/app/browser/window/tab/item/page/input.rs @@ -2,7 +2,7 @@ mod response; mod sensitive; mod titan; -use super::TabAction; +use super::ItemAction; use adw::Clamp; use gtk::{glib::Uri, prelude::WidgetExt, Box, Label}; use response::Response; @@ -52,7 +52,7 @@ impl Input { // Setters pub fn set_new_response( &self, - action: Rc, + action: Rc, base: Uri, title: Option<&str>, size_limit: Option, @@ -64,7 +64,7 @@ impl Input { pub fn set_new_sensitive( &self, - action: Rc, + action: Rc, base: Uri, title: Option<&str>, max_length: Option, diff --git a/src/app/browser/window/tab/item/page/input/response.rs b/src/app/browser/window/tab/item/page/input/response.rs index 40f81656..90d15964 100644 --- a/src/app/browser/window/tab/item/page/input/response.rs +++ b/src/app/browser/window/tab/item/page/input/response.rs @@ -6,7 +6,7 @@ use control::Control; use form::Form; use title::Title; -use super::TabAction; +use super::ItemAction; use gtk::{ gio::SimpleAction, glib::{uuid_string_random, Uri, UriHideFlags}, @@ -28,7 +28,7 @@ impl Response { /// Build new `Self` pub fn build( - tab_action: Rc, + item_action: Rc, base: Uri, title: Option<&str>, size_limit: Option, @@ -77,7 +77,7 @@ impl Response { action_send.connect_activate({ let form = form.clone(); move |_, _| { - tab_action.load.activate( + item_action.load.activate( Some(&format!( "{}?{}", base.to_string_partial(UriHideFlags::QUERY), diff --git a/src/app/browser/window/tab/item/page/input/sensitive.rs b/src/app/browser/window/tab/item/page/input/sensitive.rs index ebe20ad3..c6cc9b36 100644 --- a/src/app/browser/window/tab/item/page/input/sensitive.rs +++ b/src/app/browser/window/tab/item/page/input/sensitive.rs @@ -1,6 +1,6 @@ mod form; -use super::TabAction; +use super::ItemAction; use form::Form; use gtk::{ gio::SimpleAction, @@ -22,7 +22,7 @@ impl Sensitive { /// Build new `Self` pub fn build( - tab_action: Rc, + item_action: Rc, base: Uri, title: Option<&str>, max_length: Option, @@ -54,7 +54,7 @@ impl Sensitive { action_send.connect_activate({ let form = form.clone(); move |_, _| { - tab_action.load.activate( + item_action.load.activate( Some(&format!( "{}?{}", base.to_string_partial(UriHideFlags::QUERY), diff --git a/src/app/browser/window/tab/item/page/navigation.rs b/src/app/browser/window/tab/item/page/navigation.rs index 1e5bbb23..26b35ca6 100644 --- a/src/app/browser/window/tab/item/page/navigation.rs +++ b/src/app/browser/window/tab/item/page/navigation.rs @@ -6,20 +6,18 @@ mod reload; mod request; mod widget; +use super::{BrowserAction, ItemAction, Profile, WindowAction}; use bookmark::Bookmark; -use gtk::Button; +use gtk::{Box, Button}; use history::History; use home::Home; use reload::Reload; use request::Request; -use widget::Widget; - -use super::{BrowserAction, Profile, TabAction, WindowAction}; use sqlite::Transaction; use std::rc::Rc; +use widget::Widget; pub struct Navigation { - pub history: Rc, pub profile: Rc, pub request: Rc, pub widget: Rc, @@ -28,21 +26,21 @@ pub struct Navigation { impl Navigation { pub fn build( profile: &Rc, - (browser_action, window_action, tab_action): ( + (browser_action, window_action, item_action): ( &Rc, &Rc, - &Rc, + &Rc, ), + (back_action_name, forward_action_name): (&str, &str), ) -> Self { // init children components - let history = Rc::new(History::build(window_action)); - let request = Rc::new(Request::build((browser_action, tab_action))); + let request = Rc::new(Request::build((browser_action, item_action))); // init main widget let widget = Rc::new(Widget::build( &Button::home(window_action), - &history.widget.g_box, // @TODO + &Box::history(back_action_name, forward_action_name), &Button::reload(window_action), &request.widget.entry, // @TODO &Button::bookmark(window_action), @@ -50,7 +48,6 @@ impl Navigation { // done Self { - history, profile: profile.clone(), request, widget, diff --git a/src/app/browser/window/tab/item/page/navigation/history.rs b/src/app/browser/window/tab/item/page/navigation/history.rs index 165d4e74..d64c7e94 100644 --- a/src/app/browser/window/tab/item/page/navigation/history.rs +++ b/src/app/browser/window/tab/item/page/navigation/history.rs @@ -1,107 +1,26 @@ -mod back; -mod forward; -mod widget; +pub mod back; +pub mod forward; -use back::Back; -use forward::Forward; -use widget::Widget; +pub use back::Back; +pub use forward::Forward; -use super::WindowAction; -use gtk::{glib::GString, Button}; -use std::{cell::RefCell, rc::Rc}; +use gtk::{prelude::BoxExt, Box, Button, Orientation}; -struct Memory { - request: GString, - // time: SystemTime, +pub trait History { + fn history(back_action_name: &str, forward_action_name: &str) -> Self; } -pub struct History { - // Extras - memory: RefCell>, - index: RefCell>, - // GTK - pub widget: Rc, -} +impl History for Box { + fn history(back_action_name: &str, forward_action_name: &str) -> Self { + let g_box = Box::builder() + .orientation(Orientation::Horizontal) + .css_classes([ + "linked", // merge childs + ]) + .build(); -impl History { - // Constructors - - /// Build new `Self` - pub fn build(action: &Rc) -> Self { - // Init widget - let widget = Rc::new(Widget::build( - &Button::back(action), - &Button::forward(action), - )); - - // Init memory - let memory = RefCell::new(Vec::new()); - - // Init index - let index = RefCell::new(None); - - Self { - memory, - index, - widget, - } - } - - // Actions - pub fn add(&self, request: GString, follow_to_index: bool) { - // Append new Memory record - self.memory.borrow_mut().push(Memory { - request: request.clone(), - //time: SystemTime::now(), - }); - - if follow_to_index { - // Even push action make positive len value, make sure twice - if !self.memory.borrow().is_empty() { - // Navigate to the last record appended - self.index.replace(Some(self.memory.borrow().len() - 1)); - } else { - self.index.replace(None); - } - } - } - - pub fn back(&self, follow_to_index: bool) -> Option { - let index = *self.index.borrow(); - if let Some(usize) = index { - // Make sure value positive to prevent panic - if usize > 0 { - if let Some(memory) = self.memory.borrow().get(usize - 1) { - if follow_to_index { - self.index.replace(Some(usize - 1)); - } - return Some(memory.request.clone()); - } - } - } - None - } - - pub fn current(&self) -> Option { - let index = *self.index.borrow(); - if let Some(usize) = index { - if let Some(memory) = self.memory.borrow().get(usize) { - return Some(memory.request.clone()); - } - } - None - } - - pub fn forward(&self, follow_to_index: bool) -> Option { - let index = *self.index.borrow(); - if let Some(usize) = index { - if let Some(memory) = self.memory.borrow().get(usize + 1) { - if follow_to_index { - self.index.replace(Some(usize + 1)); - } - return Some(memory.request.clone()); - } - } - None + g_box.append(&Button::back(back_action_name)); + g_box.append(&Button::forward(forward_action_name)); + g_box } } diff --git a/src/app/browser/window/tab/item/page/navigation/history/back.rs b/src/app/browser/window/tab/item/page/navigation/history/back.rs index e6196f64..cce1bbc8 100644 --- a/src/app/browser/window/tab/item/page/navigation/history/back.rs +++ b/src/app/browser/window/tab/item/page/navigation/history/back.rs @@ -1,19 +1,13 @@ -use super::WindowAction; -use gtk::{prelude::ActionExt, Button}; -use std::rc::Rc; +use gtk::Button; pub trait Back { - fn back(action: &Rc) -> Self; + fn back(action_name: &str) -> Self; } impl Back for Button { - fn back(action: &Rc) -> Self { + fn back(action_name: &str) -> Self { Button::builder() - .action_name(format!( - "{}.{}", - action.id, - action.history_back.simple_action.name() - )) // @TODO + .action_name(action_name) .icon_name("go-previous-symbolic") .tooltip_text("Back") .build() diff --git a/src/app/browser/window/tab/item/page/navigation/history/forward.rs b/src/app/browser/window/tab/item/page/navigation/history/forward.rs index 8cbfd58f..c560db98 100644 --- a/src/app/browser/window/tab/item/page/navigation/history/forward.rs +++ b/src/app/browser/window/tab/item/page/navigation/history/forward.rs @@ -1,19 +1,13 @@ -use super::WindowAction; -use gtk::{prelude::ActionExt, Button}; -use std::rc::Rc; +use gtk::Button; pub trait Forward { - fn forward(action: &Rc) -> Self; + fn forward(action_name: &str) -> Self; } impl Forward for Button { - fn forward(action: &Rc) -> Self { + fn forward(action_name: &str) -> Self { Button::builder() - .action_name(format!( - "{}.{}", - action.id, - action.history_back.simple_action.name() - )) // @TODO + .action_name(action_name) .icon_name("go-next-symbolic") .tooltip_text("Forward") .build() diff --git a/src/app/browser/window/tab/item/page/navigation/history/widget.rs b/src/app/browser/window/tab/item/page/navigation/history/widget.rs deleted file mode 100644 index 71f6f648..00000000 --- a/src/app/browser/window/tab/item/page/navigation/history/widget.rs +++ /dev/null @@ -1,27 +0,0 @@ -use gtk::{ - prelude::{BoxExt, IsA}, - Box, Orientation, -}; - -pub struct Widget { - pub g_box: Box, -} - -impl Widget { - // Constructors - - /// Build new `Self` - pub fn build(back: &impl IsA, forward: &impl IsA) -> Self { - let g_box = Box::builder() - .orientation(Orientation::Horizontal) - .css_classes([ - "linked", // merge childs - ]) - .build(); - - g_box.append(back); - g_box.append(forward); - - Self { g_box } - } -} diff --git a/src/app/browser/window/tab/item/page/navigation/request.rs b/src/app/browser/window/tab/item/page/navigation/request.rs index c5751d17..64cb9b96 100644 --- a/src/app/browser/window/tab/item/page/navigation/request.rs +++ b/src/app/browser/window/tab/item/page/navigation/request.rs @@ -4,7 +4,7 @@ mod widget; use widget::Widget; -use crate::app::browser::{window::tab::item::Action as TabAction, Action as BrowserAction}; +use crate::app::browser::{window::tab::item::Action as ItemAction, Action as BrowserAction}; use gtk::{ glib::{gformat, GString, Uri, UriFlags}, prelude::EditableExt, @@ -21,9 +21,9 @@ impl Request { // Constructors /// Build new `Self` - pub fn build((browser_action, tab_action): (&Rc, &Rc)) -> Self { + pub fn build((browser_action, item_action): (&Rc, &Rc)) -> Self { Self { - widget: Rc::new(Widget::build((browser_action, tab_action))), + widget: Rc::new(Widget::build((browser_action, item_action))), } } diff --git a/src/app/browser/window/tab/item/page/navigation/request/widget.rs b/src/app/browser/window/tab/item/page/navigation/request/widget.rs index b5e05818..d4b3c416 100644 --- a/src/app/browser/window/tab/item/page/navigation/request/widget.rs +++ b/src/app/browser/window/tab/item/page/navigation/request/widget.rs @@ -3,7 +3,7 @@ mod primary_icon; use primary_icon::PrimaryIcon; -use super::{BrowserAction, TabAction}; +use super::{BrowserAction, ItemAction}; use gtk::{ glib::{timeout_add_local, ControlFlow, SourceId}, prelude::{EditableExt, EntryExt, WidgetExt}, @@ -36,7 +36,7 @@ impl Widget { // Constructors /// Build new `Self` - pub fn build((browser_action, tab_action): (&Rc, &Rc)) -> Self { + pub fn build((browser_action, item_action): (&Rc, &Rc)) -> Self { // Init animated progress bar state let progress = Rc::new(Progress { fraction: RefCell::new(0.0), @@ -52,10 +52,10 @@ impl Widget { // Connect events entry.connect_icon_release({ - let tab_action = tab_action.clone(); + let item_action = item_action.clone(); move |this, position| match position { - EntryIconPosition::Primary => tab_action.ident.activate(), // @TODO PrimaryIcon impl - EntryIconPosition::Secondary => tab_action.load.activate(Some(&this.text()), true), + EntryIconPosition::Primary => item_action.ident.activate(), // @TODO PrimaryIcon impl + EntryIconPosition::Secondary => item_action.load.activate(Some(&this.text()), true), _ => todo!(), // unexpected } }); @@ -77,9 +77,9 @@ impl Widget { }); entry.connect_activate({ - let tab_action = tab_action.clone(); + let item_action = item_action.clone(); move |entry| { - tab_action.load.activate(Some(&entry.text()), true); + item_action.load.activate(Some(&entry.text()), true); } });