use crate::tauri_plugin::error::PluginError; use crate::tauri_plugin::state::{ApiState, BufferState}; use crate::types::identifier::FileIdentifier; use std::borrow::Cow; use std::collections::HashMap; use tauri::http::{Request, Response, ResponseBuilder}; use tauri::{AppHandle, Builder, Manager, Runtime}; use url::Url; type Result = std::result::Result>; pub fn register_custom_uri_schemes(builder: Builder) -> Builder { builder .register_uri_scheme_protocol("once", once_scheme) .register_uri_scheme_protocol("content", content_scheme) .register_uri_scheme_protocol("thumb", thumb_scheme) } fn once_scheme(app: &AppHandle, request: &Request) -> Result { let buf_state = app.state::(); let resource_key = request.uri().trim_start_matches("once://"); let buffer = buf_state.get_entry(resource_key); if let Some(buffer) = buffer { ResponseBuilder::new() .mimetype(&buffer.mime) .status(200) .body(buffer.buf) } else { ResponseBuilder::new() .mimetype("text/plain") .status(404) .body("Resource not found".as_bytes().to_vec()) } } fn content_scheme(app: &AppHandle, request: &Request) -> Result { let api_state = app.state::(); let buf_state = app.state::(); let hash = request.uri().trim_start_matches("content://"); if let Some(buffer) = buf_state.get_entry(hash) { ResponseBuilder::new() .status(200) .mimetype(&buffer.mime) .body(buffer.buf) } else { let api = api_state.api_sync()?; let file = futures::executor::block_on(api.file.get_file(FileIdentifier::Hash(hash.to_string())))?; let mime = file.mime_type.unwrap_or("image/png".to_string()); let bytes = futures::executor::block_on( api.file .read_file_by_hash(FileIdentifier::Hash(hash.to_string())), )?; buf_state.add_entry(hash.to_string(), mime.clone(), bytes.clone()); ResponseBuilder::new() .mimetype(&mime) .status(200) .body(bytes) } } fn thumb_scheme(app: &AppHandle, request: &Request) -> Result { let api_state = app.state::(); let buf_state = app.state::(); let url = Url::parse(request.uri())?; let hash = url .domain() .ok_or_else(|| PluginError::from("Missing Domain"))?; let query_pairs = url .query_pairs() .collect::, Cow<'_, str>>>(); let height = query_pairs .get("height") .and_then(|h| h.parse::().ok()) .unwrap_or(250); let width = query_pairs .get("width") .and_then(|w| w.parse::().ok()) .unwrap_or(250); if let Some(buffer) = buf_state.get_entry(request.uri()) { ResponseBuilder::new() .status(200) .mimetype(&buffer.mime) .body(buffer.buf) } else { let api = api_state.api_sync()?; let (thumb, bytes) = futures::executor::block_on(api.file.get_thumbnail_of_size( FileIdentifier::Hash(hash.to_string()), ((height as f32 * 0.8) as u32, (width as f32 * 0.8) as u32), ((height as f32 * 1.2) as u32, (width as f32 * 1.2) as u32), ))?; let mime = thumb.mime_type.unwrap_or(String::from("image/png")); buf_state.add_entry(request.uri().to_string(), mime.clone(), bytes.clone()); ResponseBuilder::new() .mimetype(&mime) .status(200) .body(bytes) } }