diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index f685b9f8..a41aed68 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -284,13 +284,13 @@ impl Tab { /// Reload page at `i32` position or selected page on `None` given pub fn reload(&self, page_position: Option) { if let Some(item) = self.item(page_position) { - item.client.handle(&item.page.navigation.request()); + item.client.handle(&item.page.navigation.request(), true); } } pub fn open(&self, page_position: Option, request: &str) { if let Some(item) = self.item(page_position) { - item.action.load.activate(Some(request)); + item.action.load.activate(Some(request), true); } } diff --git a/src/app/browser/window/tab/item.rs b/src/app/browser/window/tab/item.rs index f4b915b5..3dd04793 100644 --- a/src/app/browser/window/tab/item.rs +++ b/src/app/browser/window/tab/item.rs @@ -90,7 +90,7 @@ impl Item { if let Some(uri) = page.navigation.home() { let request = uri.to_string(); page.navigation.set_request(&request); - client.handle(&request); + client.handle(&request, true); } } }); @@ -98,10 +98,10 @@ impl Item { action.load.connect_activate({ let page = page.clone(); let client = client.clone(); - move |request| { + move |request, is_snap_history| { if let Some(request) = request { page.navigation.set_request(&request); - client.handle(&request); + client.handle(&request, is_snap_history); } } }); @@ -114,7 +114,7 @@ impl Item { action.reload.connect_activate({ let page = page.clone(); let client = client.clone(); - move |_, _| client.handle(&page.navigation.request()) + move |_, _| client.handle(&page.navigation.request(), true) }); action.reload.connect_enabled_notify({ @@ -151,7 +151,7 @@ impl Item { if let Some(request) = request { page.navigation.set_request(request); if is_load { - client.handle(request) + client.handle(request, true) } } diff --git a/src/app/browser/window/tab/item/action.rs b/src/app/browser/window/tab/item/action.rs index b829dcaa..24bea278 100644 --- a/src/app/browser/window/tab/item/action.rs +++ b/src/app/browser/window/tab/item/action.rs @@ -40,7 +40,7 @@ impl Action { let history = Rc::new(History::build({ let load = load.clone(); - move |request| load.activate(Some(&request)) + move |request| load.activate(Some(&request), false) })); Self { diff --git a/src/app/browser/window/tab/item/action/load.rs b/src/app/browser/window/tab/item/action/load.rs index f8669735..e11da482 100644 --- a/src/app/browser/window/tab/item/action/load.rs +++ b/src/app/browser/window/tab/item/action/load.rs @@ -23,7 +23,7 @@ impl Load { Self { simple_action: SimpleAction::new( &uuid_string_random(), - Some(&::static_variant_type()), + Some(&<(String, bool)>::static_variant_type()), ), } } @@ -32,25 +32,30 @@ impl Load { /// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal /// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value - pub fn activate(&self, request: Option<&str>) { - self.simple_action - .activate(Some(&(request.unwrap_or_default()).to_variant())); + pub fn activate(&self, request: Option<&str>, is_history: bool) { + self.simple_action.activate(Some( + &(request.unwrap_or_default(), is_history).to_variant(), + )); } // Events /// Define callback function for /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal - pub fn connect_activate(&self, callback: impl Fn(Option) + 'static) { + pub fn connect_activate(&self, callback: impl Fn(Option, bool) + 'static) { self.simple_action.connect_activate(move |_, this| { - let request = this - .expect("Expected `request` variant") - .get::() - .expect("Parameter type does not match `String`"); - callback(match request.is_empty() { - true => None, - false => Some(request.into()), - }) + let (request, is_history) = this + .expect("Expected (`request`,`is_history`) variant") + .get::<(String, bool)>() + .expect("Parameter type does not match (`String`,`bool`) tuple"); + + callback( + match request.is_empty() { + true => None, + false => Some(request.into()), + }, + is_history, + ) }); } } diff --git a/src/app/browser/window/tab/item/client.rs b/src/app/browser/window/tab/item/client.rs index 5cb2abe8..a9a4ca64 100644 --- a/src/app/browser/window/tab/item/client.rs +++ b/src/app/browser/window/tab/item/client.rs @@ -36,7 +36,7 @@ impl Client { /// Route tab item `request` to protocol driver /// * or `navigation` entry if the value not provided - pub fn handle(&self, request: &str) { + pub fn handle(&self, request: &str, is_snap_history: bool) { // Move focus out from navigation entry @TODO self.page.browser_action.escape.activate(None); @@ -61,8 +61,14 @@ impl Client { match result { // route by scheme Ok(uri) => match uri.scheme().as_str() { - "file" => driver.file.handle(uri, feature, cancellable), - "gemini" | "titan" => driver.gemini.handle(uri, feature, cancellable), + "file" => driver + .file + .handle(uri, feature, cancellable, is_snap_history), + "gemini" | "titan" => { + driver + .gemini + .handle(uri, feature, cancellable, is_snap_history) + } scheme => { // no scheme match driver, complete with failure message let status = page.content.to_status_failure(); @@ -74,7 +80,10 @@ impl Client { } }, // begin redirection to new address suggested - Err(query) => page.item_action.load.activate(Some(&query)), + Err(query) => page + .item_action + .load + .activate(Some(&query), is_snap_history), } } }) diff --git a/src/app/browser/window/tab/item/client/driver/file.rs b/src/app/browser/window/tab/item/client/driver/file.rs index aa87f3d1..253ea817 100644 --- a/src/app/browser/window/tab/item/client/driver/file.rs +++ b/src/app/browser/window/tab/item/client/driver/file.rs @@ -20,7 +20,13 @@ impl File { Self { page: page.clone() } // @TODO } - pub fn handle(&self, uri: Uri, feature: Rc, cancellable: Cancellable) { + pub fn handle( + &self, + uri: Uri, + feature: Rc, + cancellable: Cancellable, + is_snap_history: bool, + ) { use directory::Directory; use gtk::{ gio::{File, FileQueryInfoFlags, FileType}, @@ -36,7 +42,7 @@ impl File { let page = self.page.clone(); match file.query_file_type(FileQueryInfoFlags::NONE, Some(&cancellable)) { - FileType::Directory => Directory { file }.handle(&page), + FileType::Directory => Directory { file }.handle(&page, is_snap_history), _ => file.clone().query_info_async( "standard::content-type", FileQueryInfoFlags::NONE, diff --git a/src/app/browser/window/tab/item/client/driver/file/directory.rs b/src/app/browser/window/tab/item/client/driver/file/directory.rs index b031164f..47052a8f 100644 --- a/src/app/browser/window/tab/item/client/driver/file/directory.rs +++ b/src/app/browser/window/tab/item/client/driver/file/directory.rs @@ -6,7 +6,7 @@ pub struct Directory { } impl Directory { - pub fn handle(&self, page: &Rc) { + pub fn handle(&self, page: &Rc, is_snap_history: bool) { page.set_progress(1.0); page.content.to_directory( &self.file, @@ -20,16 +20,21 @@ impl Directory { { let page = page.clone(); move |file| { - page.item_action.load.activate(Some(&format!( - "file://{}", - file.path().unwrap().to_str().unwrap() - ))) + page.item_action.load.activate( + Some(&format!( + "file://{}", + file.path().unwrap().to_str().unwrap() + )), + is_snap_history, + ) } }, ), ); page.set_title(&self.file.parse_name()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } page.window_action.find.simple_action.set_enabled(false); page.window_action.save_as.simple_action.set_enabled(false); } 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 9ca839fb..946e52b3 100644 --- a/src/app/browser/window/tab/item/client/driver/gemini.rs +++ b/src/app/browser/window/tab/item/client/driver/gemini.rs @@ -65,18 +65,27 @@ impl Gemini { // Actions - pub fn handle(&self, uri: Uri, feature: Rc, cancellable: Cancellable) { + pub fn handle( + &self, + uri: Uri, + feature: Rc, + cancellable: Cancellable, + is_snap_history: bool, + ) { use ggemini::client::connection::Request; match uri.scheme().as_str() { "gemini" => handle( Request::Gemini { uri }, - self.client.clone(), - self.page.clone(), - self.redirects.clone(), - feature, + ( + self.client.clone(), + self.page.clone(), + self.redirects.clone(), + feature, + ), cancellable, None, + is_snap_history, ), "titan" => { self.page.input.set_new_titan({ @@ -91,12 +100,15 @@ impl Gemini { mime: header.mime.map(|mime| mime.into()), token: header.token.map(|token| token.into()), }, - client.clone(), - page.clone(), - redirects.clone(), - feature.clone(), + ( + client.clone(), + page.clone(), + redirects.clone(), + feature.clone(), + ), cancellable.clone(), Some(on_failure), + is_snap_history, ) } }); @@ -111,12 +123,10 @@ impl Gemini { fn handle( request: Request, - client: Rc, - page: Rc, - redirects: Rc>, - feature: Rc, + (client, page, redirects, feature): (Rc, Rc, Rc>, Rc), cancellable: Cancellable, on_failure: Option>, + is_snap_history: bool, ) { let uri = request.uri().clone(); client.request_async( @@ -146,7 +156,9 @@ fn handle( let title = input.to_string(); page.set_progress(0.0); page.set_title(&title); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset match input { // https://geminiprotocol.net/docs/protocol-specification.gmi#status-10 @@ -230,7 +242,9 @@ fn handle( ); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, _ => match success.mime() { @@ -271,7 +285,9 @@ fn handle( .find .simple_action .set_enabled(true); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, Err(e) => { @@ -279,7 +295,9 @@ fn handle( status.set_description(Some(&e.to_string())); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, }, @@ -288,7 +306,9 @@ fn handle( status.set_description(Some(&e.to_string())); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset } } @@ -298,7 +318,9 @@ fn handle( status.set_description(Some(&e.to_string())); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, } @@ -343,7 +365,9 @@ fn handle( } } page.set_progress(0.0); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, ) @@ -353,7 +377,9 @@ fn handle( status.set_description(Some(&e.to_string())); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset } } @@ -368,7 +394,9 @@ fn handle( status.set_description(Some(&format!("Content type `{mime}` yet not supported"))); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset }, } @@ -404,7 +432,7 @@ fn handle( page.navigation.set_request(&target.to_string()); } redirects.replace(total); - page.item_action.load.activate(Some(&target.to_string())); + page.item_action.load.activate(Some(&target.to_string()), false); } } Err(e) => { @@ -426,7 +454,9 @@ fn handle( status.set_description(Some(message.as_ref().unwrap_or(&certificate.to_string()))); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset } } @@ -441,7 +471,9 @@ fn handle( status.set_description(Some(message.as_ref().unwrap_or(&temporary.to_string()))); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset if let Some(callback) = on_failure { callback() @@ -458,7 +490,9 @@ fn handle( status.set_description(Some(message.as_ref().unwrap_or(&permanent.to_string()))); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset if let Some(callback) = on_failure { callback() @@ -472,7 +506,9 @@ fn handle( status.set_description(Some(&e.to_string())); page.set_progress(0.0); page.set_title(&status.title()); - page.snap_history(); + if is_snap_history { + page.snap_history(); + } redirects.replace(0); // reset } } 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 fffcfda9..beab4bbe 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 @@ -24,7 +24,9 @@ pub fn build(mime: &str, download: Option<(&Rc, &Uri)>) -> StatusPag let action = action.clone(); let request = request.clone(); move |_| { - action.load.activate(Some(&format!("download:{}", request))); + action + .load + .activate(Some(&format!("download:{}", request)), true) } }); 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 a04be284..bb4bc361 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 @@ -388,7 +388,7 @@ impl Gemini { // Select link handler by scheme return match uri.scheme().as_str() { "gemini" | "titan" => { - item_action.load.activate(Some(&uri.to_str())) + 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/response.rs b/src/app/browser/window/tab/item/page/input/response.rs index b8338e32..f17031ce 100644 --- a/src/app/browser/window/tab/item/page/input/response.rs +++ b/src/app/browser/window/tab/item/page/input/response.rs @@ -81,11 +81,14 @@ impl Response for Box { action_send.connect_activate({ let form = form.clone(); move |_, _| { - item_action.load.activate(Some(&format!( - "{}?{}", - base.to_string_partial(UriHideFlags::QUERY), - Uri::escape_string(&form.text(), None, false), - ))) + item_action.load.activate( + Some(&format!( + "{}?{}", + base.to_string_partial(UriHideFlags::QUERY), + Uri::escape_string(&form.text(), None, false), + )), + false, + ) } }); 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 d5ea9e9a..9b821a77 100644 --- a/src/app/browser/window/tab/item/page/input/sensitive.rs +++ b/src/app/browser/window/tab/item/page/input/sensitive.rs @@ -59,11 +59,14 @@ impl Sensitive for Box { action_send.connect_activate({ let form = form.clone(); move |_, _| { - item_action.load.activate(Some(&format!( - "{}?{}", - base.to_string_partial(UriHideFlags::QUERY), - Uri::escape_string(&form.password_entry_row.text(), None, false), - ))) + item_action.load.activate( + Some(&format!( + "{}?{}", + base.to_string_partial(UriHideFlags::QUERY), + Uri::escape_string(&form.password_entry_row.text(), None, false), + )), + false, + ) } });