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) {
Some(item) => {
// Update item components
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 => {
// update all tabs
for (_, item) in self.index.borrow().iter() {
// Update item components
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),
));
let client = Rc::new(Client::init(&page));
let widget = Rc::new(Widget::build(
id.as_str(),
tab_view,
@ -74,6 +72,9 @@ impl Item {
(is_pinned, is_selected, is_attention),
));
// Update tab loading indicator
let client = Rc::new(Client::init(&page, &widget.tab_page));
// Init events
if let Some(text) = request {
@ -133,9 +134,6 @@ impl Item {
pub fn update(&self) {
// Update child components
self.page.update();
// Update tab loading indicator
self.widget.tab_page.set_loading(self.page.is_loading());
}
pub fn clean(

View File

@ -2,6 +2,7 @@ mod driver;
mod feature;
use super::Page;
use adw::TabPage;
use driver::Driver;
use feature::Feature;
use gtk::{
@ -21,10 +22,10 @@ impl Client {
// Constructors
/// Create new `Self`
pub fn init(page: &Rc<Page>) -> Self {
pub fn init(page: &Rc<Page>, tab_page: &TabPage) -> Self {
Self {
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;
use super::{Feature, Page};
use adw::TabPage;
use gemini::Gemini;
use std::rc::Rc;
@ -13,9 +14,9 @@ impl Driver {
// Constructors
/// Build new `Self`
pub fn build(page: &Rc<Page>) -> Self {
pub fn build(page: &Rc<Page>, tab_page: &TabPage) -> Self {
Driver {
gemini: Gemini::init(page),
gemini: Gemini::init(page, tab_page),
}
}
}

View File

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