From e549e99c055619e52d2df66fbd0bdef7ec019084 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 24 Feb 2023 13:27:18 +0100 Subject: [PATCH] cache images locally --- src-tauri/Cargo.lock | 15 ++++++++++ src-tauri/Cargo.toml | 5 +++- src-tauri/src/main.rs | 58 +++++++++++++++++++++++++++++++++++++-- src-tauri/tauri.conf.json | 9 +++++- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4879d7f07..e2adbcc31 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1003,7 +1003,9 @@ dependencies = [ "filetime", "git2", "log", + "md5", "notify", + "reqwest", "sentry", "sentry-tauri", "serde", @@ -1014,6 +1016,7 @@ dependencies = [ "tauri-plugin-log", "tauri-plugin-window-state", "tempfile", + "urlencoding", "uuid 1.3.0", "walkdir", ] @@ -1756,6 +1759,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.5.0" @@ -3830,6 +3839,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + [[package]] name = "utf-8" version = "0.7.6" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3b3fadc8a..3eea0d762 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -15,7 +15,7 @@ tauri-build = { version = "1.2", features = [] } [dependencies] serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.2", features = ["dialog-open", "path-all", "shell-open", "system-tray", "window-start-dragging"] } +tauri = { version = "1.2", features = ["dialog-open", "path-all", "protocol-asset", "shell-open", "system-tray", "window-start-dragging"] } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" } tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev", features = ["colored"] } log = "0.4.17" @@ -31,6 +31,9 @@ sentry = "0.27" walkdir = "2.3.2" anyhow = "1.0.69" tempfile = "3.3.0" +reqwest = "0.11.14" +md5 = "0.7.0" +urlencoding = "2.1.2" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 2f9a4866a..86db9f562 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -35,6 +35,42 @@ fn app_title() -> String { } } +fn build_asset_url(path: &str) -> String { + format!("asset://localhost/{}", urlencoding::encode(path)) +} + +fn proxy_image(handle: tauri::AppHandle, src: &str) -> Result { + if src.starts_with("asset://") { + return Ok(src.to_string()); + } + + let images_dir = handle + .path_resolver() + .app_cache_dir() + .unwrap() + .join("images"); + + let hash = md5::compute(src); + let ext = src.split('.').last().unwrap_or("jpg"); + let save_to = images_dir.join(format!("{:X}.{}", hash, ext)); + + if save_to.exists() { + return Ok(build_asset_url(&save_to.display().to_string())); + } + + let resp = reqwest::blocking::get(src)?; + if !resp.status().is_success() { + log::error!("Failed to download picture {}", src); + return Ok(src.to_string()); + } + + let bytes = resp.bytes()?; + std::fs::create_dir_all(&images_dir)?; + std::fs::write(&save_to, bytes)?; + + Ok(build_asset_url(&save_to.display().to_string())) +} + #[tauri::command] fn list_sessions( handle: tauri::AppHandle, @@ -69,12 +105,30 @@ fn get_user(handle: tauri::AppHandle) -> Result, Error> { let storage = storage::Storage::from_path_resolver(&path_resolver); let users_storage = users::Storage::new(storage); - users_storage.get().map_err(|e| { + match users_storage.get().map_err(|e| { log::error!("{:#}", e); Error { message: "Failed to get user".to_string(), } - }) + })? { + Some(user) => { + let local_picture = match proxy_image(handle, &user.picture) { + Ok(picture) => picture, + Err(e) => { + log::error!("{:#}", e); + user.picture + } + }; + + let user = users::User { + picture: local_picture.to_string(), + ..user + }; + + Ok(Some(user)) + } + None => Ok(None), + } } #[tauri::command] diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 42e853e57..e2ab76357 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -20,6 +20,13 @@ "all": false, "open": true }, + "protocol": { + "all": false, + "asset": true, + "assetScope": [ + "$APPCACHE/images/*" + ] + }, "window": { "all": false, "startDragging": true @@ -43,7 +50,7 @@ "targets": ["dmg", "updater"] }, "security": { - "csp": null + "csp": "default-src 'self'; img-src 'self' asset: https://asset.localhost" }, "systemTray": { "iconPath": "icons/tray.png",