diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index f26d8341..d743f34a 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -221,16 +221,26 @@ impl Page { } } } - Request::Search(ref query) => { - // try autocomplete scheme prefix @TODO optional resolve timeout - if self.navigation.request.to_gemini(500).is_none() { - // make search request to default provider @TODO optional - self.navigation.request.widget.entry.set_text(&format!( - "gemini://tlgs.one/search?{}", - Uri::escape_string(query, None, false) - )); - } - self.load(true) + Request::Search(query) => { + // try autocomplete scheme and request it on successful resolve + // otherwise make search request @TODO optional search provider + self.navigation + .request + .to_gemini_async(500, Some(&self.client.cancellable()), { + let tab_action = self.tab_action.clone(); + move |result| { + tab_action.load.activate( + Some(&match result { + Some(url) => url, + None => gformat!( + "gemini://tlgs.one/search?{}", + Uri::escape_string(&query, None, false) + ), + }), + true, + ) + } + }); } }; } diff --git a/src/app/browser/window/tab/item/page/navigation/request.rs b/src/app/browser/window/tab/item/page/navigation/request.rs index 54a8cfc0..bbc98524 100644 --- a/src/app/browser/window/tab/item/page/navigation/request.rs +++ b/src/app/browser/window/tab/item/page/navigation/request.rs @@ -99,11 +99,26 @@ impl Request { self.widget.entry.set_text(&self.source()); } - pub fn to_gemini(&self, resolver_timeout: u32) -> Option { - self.gemini(resolver_timeout).and_then(|url| { - self.widget.entry.set_text(&url); - Some(url) - }) + /// Asynchronously try replace `Self` entry value with valid, resolvable Gemini request + /// * callback with `None` if current value does not compatible with Gemini scheme + pub fn to_gemini_async( + &self, + resolver_timeout: u32, + cancellable: Option<&Cancellable>, + callback: impl FnOnce(Option) + 'static, + ) { + self.gemini_async(resolver_timeout, cancellable, { + let entry = self.widget.entry.clone(); + move |result| { + callback(match result { + Some(url) => { + entry.set_text(&url); + Some(url) + } + None => None, + }) + } + }); } // Getters @@ -145,7 +160,14 @@ impl Request { gformat!("source:{}", self.strip_prefix()) } - pub fn gemini(&self, resolver_timeout: u32) -> Option { + /// Asynchronously get valid, resolvable Gemini request for current `Self` entry value + /// * callback with `None` if current value does not compatible with Gemini scheme + pub fn gemini_async( + &self, + resolver_timeout: u32, + cancellable: Option<&Cancellable>, + callback: impl FnOnce(Option) + 'static, + ) -> Option { // suggest scheme let url = gformat!("gemini://{}", self.strip_prefix().trim()); @@ -156,13 +178,13 @@ impl Request { // is connectable if let Ok(connectable) = NetworkAddress::parse_uri(&url, 1965) { - // is resolvable @TODO async - if resolver - .lookup_by_name(&connectable.hostname(), Cancellable::NONE) - .is_ok() - { - return Some(url); - } + // is resolvable + resolver.lookup_by_name_async(&connectable.hostname(), cancellable, move |result| { + callback(match result { + Ok(_) => Some(url), + Err(_) => None, + }) + }); } None }