From 7bc2d478d05edb5ae067d84efd1ab5cf1c293f57 Mon Sep 17 00:00:00 2001 From: yggverse Date: Mon, 11 Nov 2024 12:52:46 +0200 Subject: [PATCH] add request state --- src/app/browser/window.rs | 4 +- src/app/browser/window/action/append.rs | 60 ++++++++++++++----- src/app/browser/window/tab.rs | 11 +++- src/app/browser/window/tab/item.rs | 11 ++++ .../item/page/content/text/gemini/reader.rs | 9 ++- 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index be26c151..4daba859 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -38,8 +38,8 @@ impl Window { // Init events action.append().connect_activate({ let tab = tab.clone(); - move |position, is_pinned, is_selected| { - tab.append(position, is_pinned, is_selected); + move |position, request, is_pinned, is_selected| { + tab.append(position, request, is_pinned, is_selected); } }); diff --git a/src/app/browser/window/action/append.rs b/src/app/browser/window/action/append.rs index cd9c474a..de6026dc 100644 --- a/src/app/browser/window/action/append.rs +++ b/src/app/browser/window/action/append.rs @@ -4,8 +4,9 @@ use gtk::{ prelude::{ActionExt, ToVariant}, }; -/// C-compatible variant type +/// C-compatible variant type defaults const DEFAULT_POSITION: i32 = -1; +const DEFAULT_REQUEST: String = String::new(); const DEFAULT_IS_PINNED: bool = false; const DEFAULT_IS_SELECTED: bool = true; @@ -23,7 +24,13 @@ impl Append { gobject: SimpleAction::new_stateful( &uuid_string_random(), None, - &(DEFAULT_POSITION, DEFAULT_IS_PINNED, DEFAULT_IS_SELECTED).to_variant(), + &( + DEFAULT_POSITION, + DEFAULT_REQUEST, + DEFAULT_IS_PINNED, + DEFAULT_IS_SELECTED, + ) + .to_variant(), ), } } @@ -34,11 +41,12 @@ impl Append { /// * this action reset previous state for action after activation pub fn activate_default_once(&self) { // Save current state in memory - let (position, is_pinned, is_selected) = state(&self.gobject); + let (position, request, is_pinned, is_selected) = state(&self.gobject); // Set default state self.change_state( Some(DEFAULT_POSITION), + Some(DEFAULT_REQUEST), DEFAULT_IS_PINNED, DEFAULT_IS_SELECTED, ); @@ -47,7 +55,7 @@ impl Append { self.gobject.activate(None); // Return previous state - self.change_state(position, is_pinned, is_selected); + self.change_state(position, request, is_pinned, is_selected); } /// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal @@ -55,24 +63,31 @@ impl Append { pub fn activate_stateful_once( &self, position: Option, + request: Option, is_pinned: bool, is_selected: bool, ) { // Save current state in memory - let (_position, _is_pinned, _is_selected) = state(&self.gobject); + let (_position, _request, _is_pinned, _is_selected) = state(&self.gobject); // Apply requested state - self.change_state(position, is_pinned, is_selected); + self.change_state(position, request, is_pinned, is_selected); // Activate action self.gobject.activate(None); // Return previous state - self.change_state(_position, _is_pinned, _is_selected); + self.change_state(_position, _request, _is_pinned, _is_selected); } /// Emit state change for action - pub fn change_state(&self, position: Option, is_pinned: bool, is_selected: bool) { + pub fn change_state( + &self, + position: Option, + request: Option, + is_pinned: bool, + is_selected: bool, + ) { self.gobject.change_state( &( // Convert Option to C-based variant value @@ -81,6 +96,11 @@ impl Append { } else { DEFAULT_POSITION }, + if let Some(request) = request { + request + } else { + DEFAULT_REQUEST + }, is_pinned, is_selected, ) @@ -93,10 +113,13 @@ impl Append { /// Define callback function for /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal /// * return `position`, `is_pinned`, `is_selected` state as tuple - pub fn connect_activate(&self, callback: impl Fn(Option, bool, bool) + 'static) { + pub fn connect_activate( + &self, + callback: impl Fn(Option, Option, bool, bool) + 'static, + ) { self.gobject.connect_activate(move |this, _| { - let (position, is_pinned, is_selected) = state(this); - callback(position, is_pinned, is_selected) + let (position, request, is_pinned, is_selected) = state(this); + callback(position, request, is_pinned, is_selected) }); } @@ -114,12 +137,12 @@ impl Append { } /// Shared helper to get C-based action state in Optional format -pub fn state(this: &SimpleAction) -> (Option, bool, bool) { - let (position, is_pinned, is_selected) = this +pub fn state(this: &SimpleAction) -> (Option, Option, bool, bool) { + let (position, request, is_pinned, is_selected) = this .state() - .expect("Expected (`position`,`is_pinned`,`is_selected`) state") - .get::<(i32, bool, bool)>() - .expect("Parameter type does not match (`i32`,`bool`,`bool`) tuple"); + .expect("Expected (`position`,`request`,`is_pinned`,`is_selected`) state") + .get::<(i32, String, bool, bool)>() + .expect("Parameter type does not match (`i32`,`String`,`bool`,`bool`) tuple"); ( // Convert from C-based variant value to Option if position == DEFAULT_POSITION { @@ -127,6 +150,11 @@ pub fn state(this: &SimpleAction) -> (Option, bool, bool) { } else { Some(position) }, + if request.is_empty() { + None + } else { + Some(request) + }, is_pinned, is_selected, ) diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index 8474454f..20bd0f7a 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -99,7 +99,13 @@ impl Tab { } // Actions - pub fn append(&self, position: Option, is_pinned: bool, is_selected: bool) -> Rc { + pub fn append( + &self, + position: Option, + request: Option, + is_pinned: bool, + is_selected: bool, + ) -> Rc { // Init new tab item let item = Rc::new(Item::new( self.widget.gobject(), @@ -107,6 +113,7 @@ impl Tab { self.window_action.clone(), // Options position, + request, is_pinned, is_selected, )); @@ -305,7 +312,7 @@ impl Tab { pub fn init(&self) { // Append just one blank page if no tabs available after last session restore if self.index.borrow().is_empty() { - self.append(None, false, true); + self.append(None, None, false, true); } // @TODO other/child features.. diff --git a/src/app/browser/window/tab/item.rs b/src/app/browser/window/tab/item.rs index 1b0637a3..0240b2c4 100644 --- a/src/app/browser/window/tab/item.rs +++ b/src/app/browser/window/tab/item.rs @@ -36,6 +36,7 @@ impl Item { window_action: Rc, // Options position: Option, + request: Option, is_pinned: bool, is_selected: bool, ) -> Self { @@ -65,6 +66,15 @@ impl Item { // Init events + if let Some(text) = request { + page.navigation() + .request() + .widget() + .gobject() + .set_text(&text); + page.load(true); + } // @TODO load optionally + action.load().connect_activate({ let page = page.clone(); move |request| { @@ -144,6 +154,7 @@ impl Item { window_action.clone(), // Options None, + None, record.is_pinned, record.is_selected, )); 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 46a32fae..cca2803d 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 @@ -288,9 +288,12 @@ impl Reader { return match uri.scheme().as_str() { "gemini" => { // Open new page in browser - window_action - .append() - .activate_stateful_once(None, false, false); + window_action.append().activate_stateful_once( + None, + Some(uri.to_string()), + false, + false, + ); // @TODO } // Scheme not supported, delegate _ => UriLauncher::new(&uri.to_str()).launch(