diff --git a/crates/gosub_instance/src/lib.rs b/crates/gosub_instance/src/lib.rs index 43261058..74fea883 100644 --- a/crates/gosub_instance/src/lib.rs +++ b/crates/gosub_instance/src/lib.rs @@ -57,7 +57,7 @@ impl EngineInstance { handles: Handles, ) -> Result { let fetcher = Arc::new(Fetcher::new(url.clone())); - let data = C::TreeDrawer::with_fetcher(url.clone(), fetcher.clone(), layouter, false).await?; + let (data, _handle) = C::TreeDrawer::with_fetcher(url.clone(), fetcher.clone(), layouter, false).await?; let (itx, irx) = tokio::sync::mpsc::channel(128); diff --git a/crates/gosub_interface/src/draw.rs b/crates/gosub_interface/src/draw.rs index 90185450..f1fcec72 100644 --- a/crates/gosub_interface/src/draw.rs +++ b/crates/gosub_interface/src/draw.rs @@ -1,9 +1,11 @@ -use crate::config::HasDrawComponents; +use crate::config::{HasDocument, HasDrawComponents}; +use crate::document_handle::DocumentHandle; use crate::eventloop::EventLoopHandle; use crate::layout::LayoutTree; use crate::render_backend::{ImgCache, NodeDesc, RenderBackend}; use gosub_net::http::fetcher::Fetcher; use gosub_shared::geo::{Point, SizeU32, FP}; +use gosub_shared::types::Result; use std::future::Future; use std::sync::mpsc::Sender; use std::sync::Arc; @@ -20,9 +22,10 @@ pub trait TreeDrawer { url: Url, layouter: C::Layouter, debug: bool, - ) -> impl Future> + ) -> impl Future)>> where - Self: Sized; + Self: Sized, + C: HasDocument; fn from_source( // The initial url that the source was loaded from @@ -33,9 +36,10 @@ pub trait TreeDrawer { layouter: C::Layouter, // Debug flag debug: bool, - ) -> gosub_shared::types::Result + ) -> Result<(Self, DocumentHandle)> where - Self: Sized; + Self: Sized, + C: HasDocument; fn with_fetcher( // The initial url that the source was loaded from @@ -46,9 +50,10 @@ pub trait TreeDrawer { layouter: C::Layouter, // Debug flag debug: bool, - ) -> impl Future> + ) -> impl Future)>> where - Self: Sized; + Self: Sized, + C: HasDocument; fn clear_buffers(&mut self); fn toggle_debug(&mut self); @@ -67,9 +72,17 @@ pub trait TreeDrawer { fn delete_scene(&mut self); - fn reload(&mut self, el: impl EventLoopHandle) -> impl Future + 'static; + fn reload(&mut self, el: impl EventLoopHandle) -> impl Future>> + 'static + where + C: HasDocument; - fn navigate(&mut self, url: Url, el: impl EventLoopHandle) -> impl Future + 'static; + fn navigate( + &mut self, + url: Url, + el: impl EventLoopHandle, + ) -> impl Future>> + 'static + where + C: HasDocument; fn reload_from(&mut self, tree: C::RenderTree); } diff --git a/crates/gosub_renderer/src/draw.rs b/crates/gosub_renderer/src/draw.rs index 5593161b..8ef68404 100644 --- a/crates/gosub_renderer/src/draw.rs +++ b/crates/gosub_renderer/src/draw.rs @@ -6,6 +6,7 @@ use crate::render_tree::{load_html_rendertree, load_html_rendertree_fetcher, loa use anyhow::anyhow; use gosub_interface::config::{HasDrawComponents, HasHtmlParser}; use gosub_interface::css3::{CssProperty, CssPropertyMap, CssValue}; +use gosub_interface::document_handle::DocumentHandle; use gosub_interface::draw::TreeDrawer; use gosub_interface::eventloop::EventLoopHandle; use gosub_interface::layout::{Layout, LayoutTree, Layouter, TextLayout}; @@ -209,26 +210,33 @@ where self.dirty = true; } - async fn from_url(url: Url, layouter: C::Layouter, debug: bool) -> Result { - let (rt, fetcher) = load_html_rendertree::(url.clone(), None).await?; + async fn from_url(url: Url, layouter: C::Layouter, debug: bool) -> Result<(Self, DocumentHandle)> { + let (rt, handle, fetcher) = load_html_rendertree::(url.clone(), None).await?; - Ok(Self::new(rt, layouter, Arc::new(fetcher), debug)) + Ok((Self::new(rt, layouter, Arc::new(fetcher), debug), handle)) } - fn from_source(url: Url, source_html: &str, layouter: C::Layouter, debug: bool) -> Result { + fn from_source( + url: Url, + source_html: &str, + layouter: C::Layouter, + debug: bool, + ) -> Result<(Self, DocumentHandle)> { let fetcher = Fetcher::new(url.clone()); - let rt = load_html_rendertree_source::(url, source_html)?; + let (rt, handle) = load_html_rendertree_source::(url, source_html)?; - Ok(Self::new(rt, layouter, Arc::new(fetcher), debug)) + Ok((Self::new(rt, layouter, Arc::new(fetcher), debug), handle)) } - async fn with_fetcher(url: Url, fetcher: Arc, layouter: C::Layouter, debug: bool) -> Result - where - Self: Sized, - { - let rt = load_html_rendertree_fetcher::(url.clone(), &fetcher).await?; + async fn with_fetcher( + url: Url, + fetcher: Arc, + layouter: C::Layouter, + debug: bool, + ) -> Result<(Self, DocumentHandle)> { + let (rt, handle) = load_html_rendertree_fetcher::(url.clone(), &fetcher).await?; - Ok(Self::new(rt, layouter, fetcher, debug)) + Ok((Self::new(rt, layouter, fetcher, debug), handle)) } fn clear_buffers(&mut self) { @@ -291,39 +299,47 @@ where self.debugger_scene = None; } - fn reload(&mut self, el: impl EventLoopHandle) -> impl Future + 'static { + fn reload(&mut self, el: impl EventLoopHandle) -> impl Future>> + 'static { let fetcher = self.fetcher.clone(); async move { info!("Reloading tab"); - let rt = match load_html_rendertree_fetcher::(fetcher.base().clone(), &fetcher).await { + let (rt, handle) = match load_html_rendertree_fetcher::(fetcher.base().clone(), &fetcher).await { Ok(rt) => rt, Err(e) => { error!("Failed to reload tab: {e}"); - return; + return Err(e); } }; el.reload_from(rt); + + Ok(handle) } } - fn navigate(&mut self, url: Url, el: impl EventLoopHandle) -> impl Future + 'static { + fn navigate( + &mut self, + url: Url, + el: impl EventLoopHandle, + ) -> impl Future>> + 'static { let fetcher = self.fetcher.clone(); async move { info!("Navigating to {url}"); - let rt = match load_html_rendertree_fetcher::(url.clone(), &fetcher).await { + let (rt, handle) = match load_html_rendertree_fetcher::(url.clone(), &fetcher).await { Ok(rt) => rt, Err(e) => { error!("Failed to navigate to {url}: {e}"); - return; + return Err(e); } }; el.reload_from(rt); + + Ok(handle) } } diff --git a/crates/gosub_renderer/src/render_tree.rs b/crates/gosub_renderer/src/render_tree.rs index 329632e0..d1f4e832 100644 --- a/crates/gosub_renderer/src/render_tree.rs +++ b/crates/gosub_renderer/src/render_tree.rs @@ -14,15 +14,15 @@ use url::Url; pub async fn load_html_rendertree( url: Url, source: Option<&str>, -) -> gosub_shared::types::Result<(C::RenderTree, Fetcher)> { +) -> gosub_shared::types::Result<(C::RenderTree, DocumentHandle, Fetcher)> { let fetcher = Fetcher::new(url.clone()); - let rt = match source { + let (rt, handle) = match source { Some(source) => load_html_rendertree_source::(url, source)?, None => load_html_rendertree_fetcher::(url, &fetcher).await?, }; - Ok((rt, fetcher)) + Ok((rt, handle, fetcher)) } // Generate a render tree from the given source HTML. THe URL is needed to resolve relative URLs @@ -30,7 +30,7 @@ pub async fn load_html_rendertree( pub fn load_html_rendertree_source( url: Url, source_html: &str, -) -> gosub_shared::types::Result { +) -> gosub_shared::types::Result<(C::RenderTree, DocumentHandle)> { let mut stream = ByteStream::new(Encoding::UTF8, None); stream.read_from_str(source_html, Some(Encoding::UTF8)); stream.close(); @@ -48,14 +48,14 @@ pub fn load_html_rendertree_source( drop(doc); - generate_render_tree(DocumentHandle::clone(&doc_handle)) + Ok((generate_render_tree(DocumentHandle::clone(&doc_handle))?, doc_handle)) } /// Generates a render tree from the given URL. The complete HTML source is fetched from the URL async. pub async fn load_html_rendertree_fetcher( url: Url, fetcher: &Fetcher, -) -> gosub_shared::types::Result { +) -> gosub_shared::types::Result<(C::RenderTree, DocumentHandle)> { let html = if url.scheme() == "http" || url.scheme() == "https" { // Fetch the html from the url let response = fetcher.get(url.as_ref()).await?;