at main 221 lines 7.4 kB view raw
1use dioxus::prelude::*; 2#[cfg(all(target_family = "wasm", target_os = "unknown"))] 3use wasm_bindgen::prelude::*; 4 5#[cfg(all(target_family = "wasm", target_os = "unknown"))] 6use wasm_bindgen_futures::JsFuture; 7#[cfg(all(target_family = "wasm", target_os = "unknown"))] 8use web_sys::{RegistrationOptions, ServiceWorkerContainer, Window}; 9#[cfg(all(target_family = "wasm", target_os = "unknown"))] 10use jacquard::smol_str::format_smolstr; 11 12#[cfg(all(target_family = "wasm", target_os = "unknown"))] 13pub async fn register_service_worker() -> Result<(), JsValue> { 14 let window = web_sys::window().ok_or_else(|| JsValue::from_str("no window"))?; 15 let navigator = window.navigator(); 16 let sw_container = navigator.service_worker(); 17 tracing::debug!("Registering service worker"); 18 let promise = sw_container.register("/sw.js"); 19 JsFuture::from(promise).await?; 20 tracing::debug!("Service worker registered"); 21 22 Ok(()) 23} 24 25/// Register blob mappings from entry images with the service worker 26#[cfg(all(target_family = "wasm", target_os = "unknown"))] 27pub async fn register_entry_blobs( 28 ident: &jacquard::types::ident::AtIdentifier<'_>, 29 book_title: &str, 30 images: &weaver_api::sh_weaver::embed::images::Images<'_>, 31 fetcher: &crate::fetch::Fetcher, 32) -> Result<(), JsValue> { 33 use jacquard::prelude::IdentityResolver; 34 use std::collections::HashMap; 35 36 tracing::debug!("registering blobs for {}", book_title); 37 let mut blob_mappings = HashMap::new(); 38 39 // Resolve DID and PDS URL 40 let (did, pds_url) = match ident { 41 jacquard::types::ident::AtIdentifier::Did(d) => { 42 let pds = fetcher.client.pds_for_did(d).await.ok(); 43 (d.clone(), pds) 44 } 45 jacquard::types::ident::AtIdentifier::Handle(h) => { 46 if let Ok((did, pds)) = fetcher.client.pds_for_handle(h).await { 47 (did, Some(pds)) 48 } else { 49 return Ok(()); 50 } 51 } 52 }; 53 54 if let Some(pds_url) = pds_url { 55 for image in &images.images { 56 let cid = image.image.blob().cid(); 57 58 if let Some(name) = &image.name { 59 let blob_url = format_smolstr!( 60 "{}xrpc/com.atproto.sync.getBlob?did={}&cid={}", 61 pds_url.as_str(), 62 did.as_ref(), 63 cid.as_ref() 64 ); 65 blob_mappings.insert(name.as_ref().to_string(), blob_url); 66 } 67 } 68 } 69 70 // Send mappings to service worker 71 if !blob_mappings.is_empty() { 72 send_blob_mappings(book_title, blob_mappings)?; 73 } 74 //} 75 76 Ok(()) 77} 78 79/// Register blob mappings from entry images with the service worker 80#[cfg(all(target_family = "wasm", target_os = "unknown"))] 81pub async fn register_standalone_entry_blobs( 82 ident: &jacquard::types::ident::AtIdentifier<'_>, 83 rkey: &str, 84 images: &weaver_api::sh_weaver::embed::images::Images<'_>, 85 fetcher: &crate::fetch::Fetcher, 86) -> Result<(), JsValue> { 87 use jacquard::prelude::IdentityResolver; 88 use std::collections::HashMap; 89 90 tracing::debug!("registering blobs for {}", rkey); 91 let mut blob_mappings = HashMap::new(); 92 93 // Resolve DID and PDS URL 94 let (did, pds_url) = match ident { 95 jacquard::types::ident::AtIdentifier::Did(d) => { 96 let pds = fetcher.client.pds_for_did(d).await.ok(); 97 (d.clone(), pds) 98 } 99 jacquard::types::ident::AtIdentifier::Handle(h) => { 100 if let Ok((did, pds)) = fetcher.client.pds_for_handle(h).await { 101 (did, Some(pds)) 102 } else { 103 return Ok(()); 104 } 105 } 106 }; 107 108 if let Some(pds_url) = pds_url { 109 for image in &images.images { 110 let cid = image.image.blob().cid(); 111 112 if let Some(name) = &image.name { 113 let blob_url = format_smolstr!( 114 "{}xrpc/com.atproto.sync.getBlob?did={}&cid={}", 115 pds_url.as_str(), 116 did.as_ref(), 117 cid.as_ref() 118 ); 119 blob_mappings.insert(name.as_ref().to_string(), blob_url); 120 } 121 } 122 } 123 124 // Send mappings to service worker 125 if !blob_mappings.is_empty() { 126 send_blob_rkey_mappings(rkey, ident.as_str(), blob_mappings)?; 127 } 128 //} 129 130 Ok(()) 131} 132 133#[cfg(all(target_family = "wasm", target_os = "unknown"))] 134fn send_blob_mappings( 135 notebook: &str, 136 mappings: std::collections::HashMap<String, jacquard::smol_str::SmolStr>, 137) -> Result<(), JsValue> { 138 let window = web_sys::window().ok_or_else(|| JsValue::from_str("no window"))?; 139 let navigator = window.navigator(); 140 let sw_container = navigator.service_worker(); 141 142 tracing::debug!("sending blob mappings for {}", notebook); 143 let controller = sw_container 144 .controller() 145 .ok_or_else(|| JsValue::from_str("no service worker controller"))?; 146 147 // Build message object 148 let msg = js_sys::Object::new(); 149 js_sys::Reflect::set(&msg, &"type".into(), &"register_mappings".into())?; 150 js_sys::Reflect::set(&msg, &"notebook".into(), &notebook.into())?; 151 152 // Convert HashMap to JS Object 153 let blobs_obj = js_sys::Object::new(); 154 for (name, url) in mappings { 155 js_sys::Reflect::set(&blobs_obj, &name.into(), &url.as_str().into())?; 156 } 157 js_sys::Reflect::set(&msg, &"blobs".into(), &blobs_obj)?; 158 159 controller.post_message(&msg)?; 160 tracing::debug!("sent blob mappings for {}", notebook); 161 162 Ok(()) 163} 164 165#[cfg(all(target_family = "wasm", target_os = "unknown"))] 166fn send_blob_rkey_mappings( 167 rkey: &str, 168 ident: &str, 169 mappings: std::collections::HashMap<String, jacquard::smol_str::SmolStr>, 170) -> Result<(), JsValue> { 171 let window = web_sys::window().ok_or_else(|| JsValue::from_str("no window"))?; 172 let navigator = window.navigator(); 173 let sw_container = navigator.service_worker(); 174 175 tracing::debug!("sending blob mappings for {}", rkey); 176 let controller = sw_container 177 .controller() 178 .ok_or_else(|| JsValue::from_str("no service worker controller"))?; 179 180 // Build message object 181 let msg = js_sys::Object::new(); 182 js_sys::Reflect::set(&msg, &"type".into(), &"register_rkey_mappings".into())?; 183 js_sys::Reflect::set(&msg, &"rkey".into(), &rkey.into())?; 184 js_sys::Reflect::set(&msg, &"ident".into(), &ident.into())?; 185 186 // Convert HashMap to JS Object 187 let blobs_obj = js_sys::Object::new(); 188 for (name, url) in mappings { 189 js_sys::Reflect::set(&blobs_obj, &name.into(), &url.as_str().into())?; 190 } 191 js_sys::Reflect::set(&msg, &"blobs".into(), &blobs_obj)?; 192 193 controller.post_message(&msg)?; 194 tracing::debug!("sent blob mappings for {}", rkey); 195 196 Ok(()) 197} 198 199#[allow(unused)] 200#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] 201pub async fn register_service_worker() -> Result<(), String> { 202 Ok(()) 203} 204 205#[allow(unused)] 206#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] 207pub fn send_blob_mappings( 208 _notebook: &str, 209 _mappings: std::collections::HashMap<String, jacquard::smol_str::SmolStr>, 210) -> Result<(), String> { 211 Ok(()) 212} 213 214// #[used] 215// static BINDINGS_JS: Asset = asset!( 216// "/sw.js", 217// AssetOptions::js() 218// .with_hash_suffix(false) 219// .with_minify(false) 220// .with_preload(true) 221// );