update is_loading update logic

This commit is contained in:
yggverse 2025-01-21 19:39:44 +02:00
parent 2f22185d6a
commit 88457b3fa0
6 changed files with 41 additions and 90 deletions

View File

@ -288,24 +288,12 @@ impl Tab {
match self.index.borrow().get(&key) { match self.index.borrow().get(&key) {
Some(item) => { Some(item) => {
// Update item components
item.update(); item.update();
// Update tab title on loading indicator inactive
if !item.page.is_loading() {
item.widget.tab_page.set_title(&item.page.title.borrow())
} }
}
// Update all tabs
None => { None => {
// update all tabs
for (_, item) in self.index.borrow().iter() { for (_, item) in self.index.borrow().iter() {
// Update item components
item.update(); item.update();
// Update tab title on loading indicator inactive
if !item.page.is_loading() {
item.widget.tab_page.set_title(&item.page.title.borrow())
}
} }
} }
} }

View File

@ -63,8 +63,6 @@ impl Item {
(browser_action, window_action, &action), (browser_action, window_action, &action),
)); ));
let client = Rc::new(Client::init(&page));
let widget = Rc::new(Widget::build( let widget = Rc::new(Widget::build(
id.as_str(), id.as_str(),
tab_view, tab_view,
@ -74,6 +72,9 @@ impl Item {
(is_pinned, is_selected, is_attention), (is_pinned, is_selected, is_attention),
)); ));
// Update tab loading indicator
let client = Rc::new(Client::init(&page, &widget.tab_page));
// Init events // Init events
if let Some(text) = request { if let Some(text) = request {
@ -133,9 +134,6 @@ impl Item {
pub fn update(&self) { pub fn update(&self) {
// Update child components // Update child components
self.page.update(); self.page.update();
// Update tab loading indicator
self.widget.tab_page.set_loading(self.page.is_loading());
} }
pub fn clean( pub fn clean(

View File

@ -2,6 +2,7 @@ mod driver;
mod feature; mod feature;
use super::Page; use super::Page;
use adw::TabPage;
use driver::Driver; use driver::Driver;
use feature::Feature; use feature::Feature;
use gtk::{ use gtk::{
@ -21,10 +22,10 @@ impl Client {
// Constructors // Constructors
/// Create new `Self` /// Create new `Self`
pub fn init(page: &Rc<Page>) -> Self { pub fn init(page: &Rc<Page>, tab_page: &TabPage) -> Self {
Self { Self {
cancellable: Cell::new(Cancellable::new()), cancellable: Cell::new(Cancellable::new()),
driver: Rc::new(Driver::build(page)), driver: Rc::new(Driver::build(page, tab_page)),
} }
} }

View File

@ -1,6 +1,7 @@
mod gemini; mod gemini;
use super::{Feature, Page}; use super::{Feature, Page};
use adw::TabPage;
use gemini::Gemini; use gemini::Gemini;
use std::rc::Rc; use std::rc::Rc;
@ -13,9 +14,9 @@ impl Driver {
// Constructors // Constructors
/// Build new `Self` /// Build new `Self`
pub fn build(page: &Rc<Page>) -> Self { pub fn build(page: &Rc<Page>, tab_page: &TabPage) -> Self {
Driver { Driver {
gemini: Gemini::init(page), gemini: Gemini::init(page, tab_page),
} }
} }
} }

View File

@ -1,4 +1,5 @@
use super::{Feature, Page}; use super::{Feature, Page};
use adw::TabPage;
use ggemini::client::{ use ggemini::client::{
connection::response::{data::Text, meta::Status}, connection::response::{data::Text, meta::Status},
Request, Request,
@ -18,7 +19,8 @@ use std::{cell::Cell, path::MAIN_SEPARATOR, rc::Rc, time::Duration};
pub struct Gemini { pub struct Gemini {
/// Should be initiated once /// Should be initiated once
client: Rc<ggemini::Client>, client: Rc<ggemini::Client>,
/// Handle target /// Handle targets
tab_page: TabPage,
page: Rc<Page>, page: Rc<Page>,
/// Validate redirection count by Gemini protocol specification /// Validate redirection count by Gemini protocol specification
redirects: Rc<Cell<usize>>, redirects: Rc<Cell<usize>>,
@ -28,19 +30,16 @@ impl Gemini {
// Constructors // Constructors
/// Create new `Self` /// Create new `Self`
pub fn init(page: &Rc<Page>) -> Self { pub fn init(page: &Rc<Page>, tab_page: &TabPage) -> Self {
// Init supported protocol libraries // Init supported protocol libraries
let client = Rc::new(ggemini::Client::new()); let client = Rc::new(ggemini::Client::new());
// Listen for [SocketClient](https://docs.gtk.org/gio/class.SocketClient.html) updates // Listen for [SocketClient](https://docs.gtk.org/gio/class.SocketClient.html) updates
client.socket.connect_event({ client.socket.connect_event({
let page = page.clone(); let page = page.clone();
let tab_page = tab_page.clone();
move |_, event, _, _| { move |_, event, _, _| {
page.navigation let progress_fraction = match event {
.request
.widget
.entry
.set_progress_fraction(match event {
// 0.1 reserved for handle begin // 0.1 reserved for handle begin
SocketClientEvent::Resolving => 0.2, SocketClientEvent::Resolving => 0.2,
SocketClientEvent::Resolved => 0.3, SocketClientEvent::Resolved => 0.3,
@ -53,13 +52,22 @@ impl Gemini {
SocketClientEvent::TlsHandshaked => 0.9, SocketClientEvent::TlsHandshaked => 0.9,
SocketClientEvent::Complete => 1.0, SocketClientEvent::Complete => 1.0,
_ => todo!(), // alert on API change _ => todo!(), // alert on API change
}) };
tab_page.set_loading(progress_fraction > 0.0);
page.navigation
.request
.widget
.entry
.set_progress_fraction(progress_fraction);
} }
}); });
Self { Self {
client, client,
page: page.clone(), page: page.clone(),
tab_page: tab_page.clone(),
redirects: Rc::new(Cell::new(0)), redirects: Rc::new(Cell::new(0)),
} }
} }
@ -84,8 +92,6 @@ impl Gemini {
self.page.search.unset(); self.page.search.unset();
self.page.input.unset(); self.page.input.unset();
self.page.title.replace("Loading..".into()); self.page.title.replace("Loading..".into());
// Begin action
self.page self.page
.navigation .navigation
.request .request
@ -93,10 +99,7 @@ impl Gemini {
.entry .entry
.set_progress_fraction(0.1); .set_progress_fraction(0.1);
self.page self.tab_page.set_loading(true);
.browser_action
.update
.activate(Some(&self.page.id));
if is_history { if is_history {
snap_history(&self.page, None); snap_history(&self.page, None);
@ -124,6 +127,7 @@ impl Gemini {
{ {
let uri = uri.clone(); let uri = uri.clone();
let page = self.page.clone(); let page = self.page.clone();
let tab_page = self.tab_page.clone();
let redirects = self.redirects.clone(); let redirects = self.redirects.clone();
move |result| match result { move |result| match result {
Ok(response) => { Ok(response) => {
@ -150,7 +154,6 @@ impl Gemini {
); );
} }
page.title.replace(title.into()); page.title.replace(title.into());
page.browser_action.update.activate(Some(&page.id));
} }
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-20 // https://geminiprotocol.net/docs/protocol-specification.gmi#status-20
Status::Success => match feature { Status::Success => match feature {
@ -220,7 +223,6 @@ impl Gemini {
}, },
); );
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
_ => match response.meta.mime { _ => match response.meta.mime {
Some(mime) => match mime.as_str() { Some(mime) => match mime.as_str() {
@ -252,21 +254,18 @@ impl Gemini {
// Deactivate progress fraction // Deactivate progress fraction
page.navigation.request.widget.entry.set_progress_fraction(0.0); page.navigation.request.widget.entry.set_progress_fraction(0.0);
tab_page.set_loading(false);
// Update window components // Update window components
page.window_action page.window_action
.find .find
.simple_action .simple_action
.set_enabled(true); .set_enabled(true);
page.browser_action.update.activate(Some(&page.id));
} }
Err(e) => { Err(e) => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string())); status.set_description(Some(&e.to_string()));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
}, },
), ),
@ -286,10 +285,8 @@ impl Gemini {
Priority::DEFAULT, Priority::DEFAULT,
0x400, // 1024 bytes per chunk, optional step for images download tracking 0x400, // 1024 bytes per chunk, optional step for images download tracking
0xA00000, // 10M bytes max to prevent memory overflow if server play with promises 0xA00000, // 10M bytes max to prevent memory overflow if server play with promises
move |_, total| { move |_, total|
// Update loading progress status.set_description(Some(&format!("Download: {total} bytes"))),
status.set_description(Some(&format!("Download: {total} bytes")));
},
{ {
let page = page.clone(); let page = page.clone();
move |result| match result { move |result| match result {
@ -304,17 +301,13 @@ impl Gemini {
page.title.replace(uri_to_title(&uri)); page.title.replace(uri_to_title(&uri));
page.content page.content
.to_image(&Texture::for_pixbuf(&buffer)); .to_image(&Texture::for_pixbuf(&buffer));
page.browser_action
.update
.activate(Some(&page.id));
} }
Err(e) => { Err(e) => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some(e.message())); status.set_description(Some(e.message()));
page.title.replace(status.title()); page.title.replace(status.title());
} }
}; }
page.browser_action.update.activate(Some(&page.id));
}, },
) )
} }
@ -323,7 +316,6 @@ impl Gemini {
status.set_description(Some(&e.to_string())); status.set_description(Some(&e.to_string()));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
} }
} }
}, },
@ -334,17 +326,13 @@ impl Gemini {
.content .content
.to_status_mime(mime, Some((&page.tab_action, &uri))); .to_status_mime(mime, Some((&page.tab_action, &uri)));
status.set_description(Some(&format!("Content type `{mime}` yet not supported"))); status.set_description(Some(&format!("Content type `{mime}` yet not supported")));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
}, },
None => { None => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some("MIME type not found")); status.set_description(Some("MIME type not found"));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
} }
}, },
@ -362,10 +350,7 @@ impl Gemini {
if total > 5 { if total > 5 {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some("Redirection limit reached")); status.set_description(Some("Redirection limit reached"));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
redirects.replace(0); // reset redirects.replace(0); // reset
// Disallow external redirection // Disallow external redirection
@ -374,10 +359,7 @@ impl Gemini {
|| uri.host() != target.host() { || uri.host() != target.host() {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some("External redirects not allowed by protocol specification")); status.set_description(Some("External redirects not allowed by protocol specification"));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
redirects.replace(0); // reset redirects.replace(0); // reset
// Valid // Valid
} else { } else {
@ -395,18 +377,14 @@ impl Gemini {
Err(e) => { Err(e) => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string())); status.set_description(Some(&e.to_string()));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
} }
} }
} }
None => { None => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some("Redirection target not found")); status.set_description(Some("Redirection target not found"));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
} }
} }
}, },
@ -423,23 +401,18 @@ impl Gemini {
})); }));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
} }
status => { status => {
let _status = page.content.to_status_failure(); let _status = page.content.to_status_failure();
_status.set_description(Some(&format!("Undefined status code `{status}`"))); _status.set_description(Some(&format!("Undefined status code `{status}`")));
page.title.replace(_status.title()); page.title.replace(_status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
} }
} }
Err(e) => { Err(e) => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string())); status.set_description(Some(&e.to_string()));
page.title.replace(status.title()); page.title.replace(status.title());
page.browser_action.update.activate(Some(&page.id));
}, },
} }
}, },

View File

@ -15,10 +15,7 @@ use widget::Widget;
use super::{Action as TabAction, BrowserAction, Profile, WindowAction}; use super::{Action as TabAction, BrowserAction, Profile, WindowAction};
use gtk::{ use gtk::{glib::GString, prelude::EditableExt};
glib::GString,
prelude::{EditableExt, EntryExt},
};
use sqlite::Transaction; use sqlite::Transaction;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
@ -192,13 +189,6 @@ impl Page {
Ok(()) Ok(())
} }
// Getters
/// Get `Self` loading status
pub fn is_loading(&self) -> bool {
self.navigation.request.widget.entry.progress_fraction() > 0.0
}
} }
// Tools // Tools