1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3use std::sync::Arc;
15
16use anyrender_vello::VelloWindowRenderer as WindowRenderer;
17use apace_dom::{DocumentConfig, UserAgentStylesheet};
18use apace_html::HtmlDocument;
19use apace_shell::{
20 ApaceApplication, ApaceShellProxy, Config, EventLoop, WindowConfig, create_default_event_loop,
21};
22use apace_traits::net::NetProvider;
23
24#[doc(inline)]
25pub use apace_dom as dom;
27#[doc(inline)]
28pub use apace_html as html;
30#[cfg(feature = "net")]
31#[doc(inline)]
32pub use apace_net as net;
34#[doc(inline)]
35pub use apace_paint as paint;
37#[doc(inline)]
38pub use apace_shell as shell;
40#[doc(inline)]
41pub use apace_traits as traits;
43
44#[cfg(feature = "net")]
45#[cfg(not(target_arch = "wasm32"))]
46pub fn launch_url(url: &str) {
47 #[cfg(feature = "tracing")]
49 tracing::info!("Launching {url}");
50 let url = url.to_owned();
51 let url = url::Url::parse(&url).expect("Invalid url");
52
53 let rt = tokio::runtime::Builder::new_multi_thread()
55 .enable_all()
56 .build()
57 .unwrap();
58 let _guard = rt.enter();
59
60 let event_loop = create_default_event_loop();
61 let (proxy, reciever) = ApaceShellProxy::new(event_loop.create_proxy());
62 let net_provider = create_net_provider(proxy.clone());
63 let application = ApaceApplication::new(proxy, reciever);
64
65 let (url, bytes) = rt
66 .block_on(net_provider.fetch_async(apace_traits::net::Request::get(url)))
67 .unwrap();
68 let html = std::str::from_utf8(bytes.as_ref()).unwrap();
69
70 launch_internal(
71 html,
72 Config {
73 stylesheets: Vec::new(),
74 base_url: Some(url),
75 },
76 event_loop,
77 application,
78 net_provider,
79 )
80}
81
82pub fn launch_static_html(html: &str) {
83 launch_static_html_cfg(html, Config::default())
84}
85
86pub fn launch_static_html_cfg(html: &str, cfg: Config) {
87 #[cfg(feature = "net")]
89 #[cfg(not(target_arch = "wasm32"))]
90 let rt = tokio::runtime::Builder::new_multi_thread()
91 .enable_all()
92 .build()
93 .unwrap();
94 #[cfg(feature = "net")]
95 #[cfg(not(target_arch = "wasm32"))]
96 let _guard = rt.enter();
97
98 let event_loop = create_default_event_loop();
99 let (proxy, reciever) = ApaceShellProxy::new(event_loop.create_proxy());
100 let net_provider = create_net_provider(proxy.clone());
101 let application = ApaceApplication::new(proxy, reciever);
102
103 launch_internal(html, cfg, event_loop, application, net_provider)
104}
105
106fn launch_internal(
107 html: &str,
108 cfg: Config,
109 event_loop: EventLoop,
110 mut application: ApaceApplication<WindowRenderer>,
111 net_provider: Arc<dyn NetProvider>,
112) {
113 let doc = HtmlDocument::from_html(
114 html,
115 DocumentConfig {
116 base_url: cfg.base_url,
117 ua_stylesheets: std::iter::once(UserAgentStylesheet::default_sheet())
118 .chain(
119 cfg.stylesheets
120 .iter()
121 .map(|css| UserAgentStylesheet::parse(css)),
122 )
123 .collect(),
124 net_provider: Some(net_provider),
125 ..Default::default()
126 },
127 );
128 let renderer = WindowRenderer::new();
129 let window = WindowConfig::new(Box::new(doc) as _, renderer);
130
131 application.add_window(window);
134
135 event_loop.run_app(application).unwrap()
137}
138
139#[cfg(feature = "net")]
140type EnabledNetProvider = apace_net::Provider;
141#[cfg(not(feature = "net"))]
142type EnabledNetProvider = apace_traits::net::DummyNetProvider;
143
144fn create_net_provider(proxy: ApaceShellProxy) -> Arc<EnabledNetProvider> {
145 #[cfg(feature = "net")]
146 let net_provider = Arc::new(apace_net::Provider::new(Some(Arc::new(proxy))));
147 #[cfg(not(feature = "net"))]
148 let net_provider = {
149 use apace_traits::net::DummyNetProvider;
150
151 let _ = event_loop;
154 Arc::new(DummyNetProvider::default())
155 };
156
157 net_provider
158}