From 02e0309a41a223d6204e676372aeb2a11f416d4a Mon Sep 17 00:00:00 2001 From: reya Date: Wed, 31 Jan 2024 08:20:39 +0700 Subject: [PATCH] feat: refactor rust commands --- .../ark/src/components/note/preview/link.tsx | 21 ++- packages/utils/src/hooks/useOpenGraph.ts | 8 +- src-tauri/Cargo.lock | 5 +- src-tauri/Cargo.toml | 9 +- src-tauri/src/commands.rs | 143 +----------------- src-tauri/src/commands/folder.rs | 48 ++++++ src-tauri/src/commands/opg.rs | 50 ++++++ src-tauri/src/commands/secret.rs | 25 +++ src-tauri/src/main.rs | 26 ++-- 9 files changed, 169 insertions(+), 166 deletions(-) create mode 100644 src-tauri/src/commands/folder.rs create mode 100644 src-tauri/src/commands/opg.rs create mode 100644 src-tauri/src/commands/secret.rs diff --git a/packages/ark/src/components/note/preview/link.tsx b/packages/ark/src/components/note/preview/link.tsx index b2261878..0bc51dd9 100644 --- a/packages/ark/src/components/note/preview/link.tsx +++ b/packages/ark/src/components/note/preview/link.tsx @@ -7,12 +7,12 @@ function isImage(url: string) { export function LinkPreview({ url }: { url: string }) { const domain = new URL(url); - const { status, data } = useOpenGraph(url); + const { isLoading, isError, data } = useOpenGraph(url); - if (status === "pending") { + if (isLoading) { return (
-
+
@@ -37,6 +37,19 @@ export function LinkPreview({ url }: { url: string }) { ); } + if (isError) { + return ( + + {url} + + ); + } + return ( ) : null}
diff --git a/packages/utils/src/hooks/useOpenGraph.ts b/packages/utils/src/hooks/useOpenGraph.ts index 0944f27e..78a88ebe 100644 --- a/packages/utils/src/hooks/useOpenGraph.ts +++ b/packages/utils/src/hooks/useOpenGraph.ts @@ -3,10 +3,10 @@ import { useQuery } from "@tanstack/react-query"; import { invoke } from "@tauri-apps/api/core"; export function useOpenGraph(url: string) { - const { status, data, error } = useQuery({ + const { isLoading, isError, data } = useQuery({ queryKey: ["opg", url], queryFn: async () => { - const res: Opengraph = await invoke("opengraph", { url }); + const res: Opengraph = await invoke("fetch_opg", { url }); if (!res) { throw new Error("fetch preview failed"); } @@ -19,8 +19,8 @@ export function useOpenGraph(url: string) { }); return { - status, + isLoading, + isError, data, - error, }; } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5ae76b7f..cf50d1af 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6064,15 +6064,16 @@ dependencies = [ [[package]] name = "webpage" -version = "1.6.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8598785beeb5af95abe95e7bb20c7e747d1188347080d6811d5a56d2b9a5f368" +checksum = "3fb86b12e58d490a99867f561ce8466ffa7b73e24d015a8e7f5bc111d4424ba2" dependencies = [ "curl", "html5ever", "markup5ever_rcdom", "serde", "serde_json", + "url", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d799347c..3354383c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Ren Amamiya"] license = "GPL-3.0" repository = "https://github.com/luminous-devs/lume" edition = "2021" -rust-version = "1.66" +rust-version = "1.70" [build-dependencies] tauri-build = { version = "2.0.0-alpha", features = [] } @@ -40,9 +40,14 @@ tauri-plugin-sql = {version="2.0.0-alpha", features = [ sqlx-cli = { version = "0.7.0", default-features = false, features = [ "sqlite", ] } -webpage = { version = "1.6.0", features = ["serde"] } +webpage = { version = "2.0", features = ["serde"] } + +[target.'cfg(not(target_os = "linux"))'.dependencies] keyring = "2" +[target.'cfg(target_os = "linux")'.dependencies] +keyring = { version = "2", default_features = false, features = ["linux-secret-service"] } + [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 662d62f6..58ce6ede 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,140 +1,3 @@ -use keyring::Entry; -use std::process::Command; -use std::time::Duration; -use webpage::{Webpage, WebpageOptions}; - -#[tauri::command] -pub async fn show_in_folder(path: String) { - #[cfg(target_os = "windows")] - { - Command::new("explorer") - .args(["/select,", &path]) // The comma after select is not a typo - .spawn() - .unwrap(); - } - - #[cfg(target_os = "linux")] - { - use std::fs::metadata; - use std::path::PathBuf; - if path.contains(",") { - // see https://gitlab.freedesktop.org/dbus/dbus/-/issues/76 - let new_path = match metadata(&path).unwrap().is_dir() { - true => path, - false => { - let mut path2 = PathBuf::from(path); - path2.pop(); - path2.into_os_string().into_string().unwrap() - } - }; - Command::new("xdg-open").arg(&new_path).spawn().unwrap(); - } else { - Command::new("dbus-send") - .args([ - "--session", - "--dest=org.freedesktop.FileManager1", - "--type=method_call", - "/org/freedesktop/FileManager1", - "org.freedesktop.FileManager1.ShowItems", - format!("array:string:file://{path}").as_str(), - "string:\"\"", - ]) - .spawn() - .unwrap(); - } - } - - #[cfg(target_os = "macos")] - { - Command::new("open").args(["-R", &path]).spawn().unwrap(); - } -} - -#[derive(serde::Serialize)] -pub struct OpenGraphResponse { - title: String, - description: String, - url: String, - image: String, -} - -pub async fn fetch_opengraph(url: String) -> OpenGraphResponse { - let options = WebpageOptions { - allow_insecure: false, - max_redirections: 3, - timeout: Duration::from_secs(15), - useragent: "lume - desktop app".to_string(), - ..Default::default() - }; - - let result = match Webpage::from_url(&url, options) { - Ok(webpage) => webpage, - Err(_) => { - return OpenGraphResponse { - title: "".to_string(), - description: "".to_string(), - url: "".to_string(), - image: "".to_string(), - } - } - }; - - let html = result.html; - - return OpenGraphResponse { - title: html - .opengraph - .properties - .get("title") - .cloned() - .unwrap_or_default(), - description: html - .opengraph - .properties - .get("description") - .cloned() - .unwrap_or_default(), - url: html - .opengraph - .properties - .get("url") - .cloned() - .unwrap_or_default(), - image: html - .opengraph - .images - .get(0) - .and_then(|i| Some(i.url.clone())) - .unwrap_or_default(), - }; -} - -#[tauri::command] -pub async fn opengraph(url: String) -> OpenGraphResponse { - let result = fetch_opengraph(url).await; - return result; -} - -#[tauri::command] -pub fn secure_save(key: String, value: String) -> Result<(), ()> { - let entry = Entry::new("Lume", &key).expect("Failed to create entry"); - let _ = entry.set_password(&value); - Ok(()) -} - -#[tauri::command] -pub fn secure_load(key: String) -> Result { - let entry = Entry::new("Lume", &key).expect("Failed to create entry"); - if let Ok(password) = entry.get_password() { - Ok(password.into()) - } else { - Err("Not found".into()) - } -} - -#[tauri::command] -pub fn secure_remove(key: String) -> Result<(), ()> { - let entry = Entry::new("Lume", &key).expect("Failed to create entry"); - let _ = entry.delete_password(); - Ok(()) -} +pub mod folder; +pub mod opg; +pub mod secret; diff --git a/src-tauri/src/commands/folder.rs b/src-tauri/src/commands/folder.rs new file mode 100644 index 00000000..2bea7d0b --- /dev/null +++ b/src-tauri/src/commands/folder.rs @@ -0,0 +1,48 @@ +use std::process::Command; + +#[tauri::command] +pub async fn show_in_folder(path: String) { + #[cfg(target_os = "windows")] + { + Command::new("explorer") + .args(["/select,", &path]) // The comma after select is not a typo + .spawn() + .unwrap(); + } + + #[cfg(target_os = "linux")] + { + use std::fs::metadata; + use std::path::PathBuf; + if path.contains(",") { + // see https://gitlab.freedesktop.org/dbus/dbus/-/issues/76 + let new_path = match metadata(&path).unwrap().is_dir() { + true => path, + false => { + let mut path2 = PathBuf::from(path); + path2.pop(); + path2.into_os_string().into_string().unwrap() + } + }; + Command::new("xdg-open").arg(&new_path).spawn().unwrap(); + } else { + Command::new("dbus-send") + .args([ + "--session", + "--dest=org.freedesktop.FileManager1", + "--type=method_call", + "/org/freedesktop/FileManager1", + "org.freedesktop.FileManager1.ShowItems", + format!("array:string:file://{path}").as_str(), + "string:\"\"", + ]) + .spawn() + .unwrap(); + } + } + + #[cfg(target_os = "macos")] + { + Command::new("open").args(["-R", &path]).spawn().unwrap(); + } +} diff --git a/src-tauri/src/commands/opg.rs b/src-tauri/src/commands/opg.rs new file mode 100644 index 00000000..2d570e96 --- /dev/null +++ b/src-tauri/src/commands/opg.rs @@ -0,0 +1,50 @@ +use std::time::Duration; +use webpage::{Webpage, WebpageOptions}; + +#[derive(serde::Serialize)] +pub struct OpenGraphResponse { + title: String, + description: String, + url: String, + image: String, +} + +#[tauri::command] +pub fn fetch_opg(url: String) -> Result { + let mut options = WebpageOptions::default(); + options.allow_insecure = true; + options.max_redirections = 3; + options.timeout = Duration::from_secs(15); + + let info = Webpage::from_url(&url, options).expect("Failed"); + let html = info.html; + + let result = OpenGraphResponse { + title: html + .opengraph + .properties + .get("title") + .cloned() + .unwrap_or_default(), + description: html + .opengraph + .properties + .get("description") + .cloned() + .unwrap_or_default(), + url: html + .opengraph + .properties + .get("url") + .cloned() + .unwrap_or_default(), + image: html + .opengraph + .images + .get(0) + .and_then(|i| Some(i.url.clone())) + .unwrap_or_default(), + }; + + Ok(result.into()) +} diff --git a/src-tauri/src/commands/secret.rs b/src-tauri/src/commands/secret.rs new file mode 100644 index 00000000..71ba6c0d --- /dev/null +++ b/src-tauri/src/commands/secret.rs @@ -0,0 +1,25 @@ +use keyring::Entry; + +#[tauri::command] +pub fn secure_save(key: String, value: String) -> Result<(), ()> { + let entry = Entry::new("Lume", &key).expect("Failed to create entry"); + let _ = entry.set_password(&value); + Ok(()) +} + +#[tauri::command] +pub fn secure_load(key: String) -> Result { + let entry = Entry::new("Lume", &key).expect("Failed to create entry"); + if let Ok(password) = entry.get_password() { + Ok(password.into()) + } else { + Err("Not found".into()) + } +} + +#[tauri::command] +pub fn secure_remove(key: String) -> Result<(), ()> { + let entry = Entry::new("Lume", &key).expect("Failed to remove entry"); + let _ = entry.delete_password(); + Ok(()) +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 36bcecc7..0ce13303 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,7 +3,7 @@ windows_subsystem = "windows" )] -mod commands; +pub mod commands; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_sql::{Migration, MigrationKind}; @@ -23,14 +23,12 @@ fn main() { tauri_plugin_sql::Builder::default() .add_migrations( "sqlite:lume_v3.db", - vec![ - Migration { - version: 20230418013219, - description: "initial data", - sql: include_str!("../migrations/20230418013219_initial_data.sql"), - kind: MigrationKind::Up, - }, - ], + vec![Migration { + version: 20230418013219, + description: "initial data", + sql: include_str!("../migrations/20230418013219_initial_data.sql"), + kind: MigrationKind::Up, + }], ) .build(), ) @@ -50,11 +48,11 @@ fn main() { Some(vec![]), )) .invoke_handler(tauri::generate_handler![ - commands::opengraph, - commands::secure_save, - commands::secure_load, - commands::secure_remove, - commands::show_in_folder, + commands::secret::secure_save, + commands::secret::secure_load, + commands::secret::secure_remove, + commands::folder::show_in_folder, + commands::opg::fetch_opg, ]) .run(ctx) .expect("error while running tauri application");