From 8f9f5d3eaa20f1f119822a291f366c057e83b74c Mon Sep 17 00:00:00 2001 From: yggverse Date: Mon, 11 Nov 2024 14:47:51 +0200 Subject: [PATCH] implement is_attention tab state decorator --- src/app/browser/window.rs | 11 +++- src/app/browser/window/action/append.rs | 65 +++++++++++++++---- src/app/browser/window/tab.rs | 17 ++++- src/app/browser/window/tab/item.rs | 13 +++- .../item/page/content/text/gemini/reader.rs | 3 +- 5 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index 92681b79..ed5e7913 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -38,8 +38,15 @@ impl Window { // Init events action.append().connect_activate({ let tab = tab.clone(); - move |position, request, is_pinned, is_selected, is_load| { - tab.append(position, request, is_pinned, is_selected, is_load); + move |position, request, is_pinned, is_selected, is_attention, is_load| { + tab.append( + position, + request, + is_pinned, + is_selected, + is_attention, + is_load, + ); } }); diff --git a/src/app/browser/window/action/append.rs b/src/app/browser/window/action/append.rs index 15911e21..5aa4de1a 100644 --- a/src/app/browser/window/action/append.rs +++ b/src/app/browser/window/action/append.rs @@ -9,6 +9,7 @@ const DEFAULT_POSITION: i32 = -1; const DEFAULT_REQUEST: String = String::new(); const DEFAULT_IS_PINNED: bool = false; const DEFAULT_IS_SELECTED: bool = true; +const DEFAULT_IS_ATTENTION: bool = false; const DEFAULT_IS_LOAD: bool = false; /// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Append` action of `Window` group @@ -30,6 +31,7 @@ impl Append { DEFAULT_REQUEST, DEFAULT_IS_PINNED, DEFAULT_IS_SELECTED, + DEFAULT_IS_ATTENTION, DEFAULT_IS_LOAD, ) .to_variant(), @@ -43,7 +45,8 @@ impl Append { /// * this action reset previous state for action after activation pub fn activate_default_once(&self) { // Save current state in memory - let (position, request, is_pinned, is_selected, is_load) = state(&self.gobject); + let (position, request, is_pinned, is_selected, is_attention, is_load) = + state(&self.gobject); // Set default state self.change_state( @@ -51,6 +54,7 @@ impl Append { Some(DEFAULT_REQUEST), DEFAULT_IS_PINNED, DEFAULT_IS_SELECTED, + DEFAULT_IS_ATTENTION, DEFAULT_IS_LOAD, ); @@ -58,7 +62,14 @@ impl Append { self.gobject.activate(None); // Return previous state - self.change_state(position, request, is_pinned, is_selected, is_load); + self.change_state( + position, + request, + is_pinned, + is_selected, + is_attention, + is_load, + ); } /// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal @@ -69,19 +80,35 @@ impl Append { request: Option, is_pinned: bool, is_selected: bool, + is_attention: bool, is_load: bool, ) { // Save current state in memory - let (_position, _request, _is_pinned, _is_selected, _is_load) = state(&self.gobject); + let (_position, _request, _is_pinned, _is_selected, _is_attention, _is_load) = + state(&self.gobject); // Apply requested state - self.change_state(position, request, is_pinned, is_selected, is_load); + self.change_state( + position, + request, + is_pinned, + is_selected, + is_attention, + is_load, + ); // Activate action self.gobject.activate(None); // Return previous state - self.change_state(_position, _request, _is_pinned, _is_selected, _is_load); + self.change_state( + _position, + _request, + _is_pinned, + _is_selected, + _is_attention, + _is_load, + ); } /// Emit state change for action @@ -91,6 +118,7 @@ impl Append { request: Option, is_pinned: bool, is_selected: bool, + is_attention: bool, is_load: bool, ) { self.gobject.change_state( @@ -108,6 +136,7 @@ impl Append { }, is_pinned, is_selected, + is_attention, is_load, ) .to_variant(), @@ -118,14 +147,21 @@ impl Append { /// Define callback function for /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal - /// * return `position`,`request`,`is_pinned`,`is_selected`,`is_load` state as tuple + /// * return `position`,`request`,`is_pinned`,`is_selected`,`is_attention`,`is_load` state as tuple pub fn connect_activate( &self, - callback: impl Fn(Option, Option, bool, bool, bool) + 'static, + callback: impl Fn(Option, Option, bool, bool, bool, bool) + 'static, ) { self.gobject.connect_activate(move |this, _| { - let (position, request, is_pinned, is_selected, is_load) = state(this); - callback(position, request, is_pinned, is_selected, is_load) + let (position, request, is_pinned, is_selected, is_attention, is_load) = state(this); + callback( + position, + request, + is_pinned, + is_selected, + is_attention, + is_load, + ) }); } @@ -143,12 +179,12 @@ impl Append { } /// Shared helper to get C-based action state in Optional format -pub fn state(this: &SimpleAction) -> (Option, Option, bool, bool, bool) { - let (position, request, is_pinned, is_selected, is_load) = this +pub fn state(this: &SimpleAction) -> (Option, Option, bool, bool, bool, bool) { + let (position, request, is_pinned, is_selected, is_attention, is_load) = this .state() - .expect("Expected (`position`,`request`,`is_pinned`,`is_selected`,`is_load`) state") - .get::<(i32, String, bool, bool, bool)>() - .expect("Parameter type does not match (`i32`,`String`,`bool`,`bool`,`bool`) tuple"); + .expect("Expected (`position`,`request`,`is_pinned`,`is_selected`,`is_attention`,`is_load`) state") + .get::<(i32, String, bool, bool, bool,bool)>() + .expect("Parameter type does not match (`i32`,`String`,`bool`,`bool`,`bool`,`bool`) tuple"); ( // Convert from C-based variant value to Option if position == DEFAULT_POSITION { @@ -163,6 +199,7 @@ pub fn state(this: &SimpleAction) -> (Option, Option, bool, bool, b }, is_pinned, is_selected, + is_attention, is_load, ) } diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index fcbde079..c3e8e069 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -85,6 +85,8 @@ impl Tab { item.update(); } } + // Reset attention decorator + page.set_needs_attention(false); } } }); @@ -105,6 +107,7 @@ impl Tab { request: Option, is_pinned: bool, is_selected: bool, + is_attention: bool, is_load: bool, ) -> Rc { // Init new tab item @@ -113,9 +116,19 @@ impl Tab { self.browser_action.clone(), self.window_action.clone(), // Options tuple - (position, request, is_pinned, is_selected, is_load), + ( + position, + request, + is_pinned, + is_selected, + is_attention, + is_load, + ), )); + // Apply tab attention request + item.widget().gobject().set_needs_attention(is_attention); + // Register dynamically created tab components in the HashMap index self.index .borrow_mut() @@ -310,7 +323,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, None, false, true, false); + self.append(None, None, false, true, false, false); } // @TODO other/child features.. diff --git a/src/app/browser/window/tab/item.rs b/src/app/browser/window/tab/item.rs index aba587ce..5fc1f745 100644 --- a/src/app/browser/window/tab/item.rs +++ b/src/app/browser/window/tab/item.rs @@ -34,10 +34,10 @@ impl Item { browser_action: Rc, window_action: Rc, // Options tuple @TODO struct? - options: (Option, Option, bool, bool, bool), + options: (Option, Option, bool, bool, bool, bool), ) -> Self { // Get item options from tuple - let (position, request, is_pinned, is_selected, is_load) = options; + let (position, request, is_pinned, is_selected, _is_attention, is_load) = options; // Generate unique ID for new page components let id = uuid_string_random(); @@ -150,7 +150,14 @@ impl Item { browser_action.clone(), window_action.clone(), // Options tuple - (None, None, record.is_pinned, record.is_selected, false), + ( + None, + None, + record.is_pinned, + record.is_selected, + false, + false, + ), )); // Delegate restore action to the item childs 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 d8e2d813..cd28cc86 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 @@ -294,7 +294,8 @@ impl Reader { false, false, true, - ); // @TODO + true, + ); } // Scheme not supported, delegate _ => UriLauncher::new(&uri.to_str()).launch(