diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 526ca331..c719d531 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -193,7 +193,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-protocols", - "zbus 5.1.1", + "zbus 5.2.0", ] [[package]] @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -800,9 +800,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -1137,18 +1137,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1165,18 +1165,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -2279,11 +2279,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2342,9 +2342,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -2875,9 +2875,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" @@ -3100,9 +3100,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", @@ -3546,9 +3546,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -3920,9 +3920,9 @@ dependencies = [ [[package]] name = "png" -version = "0.17.15" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -4892,9 +4892,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa 1.0.14", "memchr", @@ -5644,7 +5644,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.7", + "thiserror 2.0.9", "tokio", "tray-icon", "url", @@ -5697,7 +5697,7 @@ dependencies = [ "sha2", "syn 2.0.90", "tauri-utils", - "thiserror 2.0.7", + "thiserror 2.0.9", "time", "url", "uuid", @@ -5746,7 +5746,7 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.7", + "thiserror 2.0.9", ] [[package]] @@ -5778,7 +5778,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.7", + "thiserror 2.0.9", "url", ] @@ -5799,7 +5799,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.7", + "thiserror 2.0.9", "toml 0.8.19", "url", "uuid", @@ -5821,7 +5821,7 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.7", + "thiserror 2.0.9", "url", "windows", "zbus 4.4.0", @@ -5839,7 +5839,7 @@ dependencies = [ "serde_repr", "tauri", "tauri-plugin", - "thiserror 2.0.7", + "thiserror 2.0.9", ] [[package]] @@ -5859,7 +5859,7 @@ dependencies = [ "shared_child", "tauri", "tauri-plugin", - "thiserror 2.0.7", + "thiserror 2.0.9", "tokio", ] @@ -5877,7 +5877,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.7", + "thiserror 2.0.9", "url", "windows", ] @@ -5937,7 +5937,7 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.7", + "thiserror 2.0.9", "toml 0.8.19", "url", "urlpattern", @@ -6005,11 +6005,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.7" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" dependencies = [ - "thiserror-impl 2.0.7", + "thiserror-impl 2.0.9", ] [[package]] @@ -6025,9 +6025,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.7" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", @@ -6098,9 +6098,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -6400,9 +6400,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" @@ -7445,9 +7445,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.1.1" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1162094dc63b1629fcc44150bcceeaa80798cd28bcbe7fa987b65a034c258608" +checksum = "fb67eadba43784b6fb14857eba0d8fc518686d3ee537066eb6086dc318e2c8a1" dependencies = [ "async-broadcast", "async-recursion", @@ -7468,7 +7468,7 @@ dependencies = [ "windows-sys 0.59.0", "winnow 0.6.20", "xdg-home", - "zbus_macros 5.1.1", + "zbus_macros 5.2.0", "zbus_names 4.1.0", "zvariant 5.1.0", ] @@ -7488,9 +7488,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.1.1" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd2dcdce3e2727f7d74b7e33b5a89539b3cc31049562137faf7ae4eb86cd16d" +checksum = "2c9d49ebc960ceb660f2abe40a5904da975de6986f2af0d7884b39eec6528c57" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", diff --git a/src-tauri/common/Cargo.toml b/src-tauri/common/Cargo.toml index b60cd297..0be9ec40 100644 --- a/src-tauri/common/Cargo.toml +++ b/src-tauri/common/Cargo.toml @@ -12,4 +12,4 @@ entity = { path = "../entity" } global-hotkey = "0" sea-orm = { version = "1" } serde = { version = "1" } -serde_json = { version = "1" } +serde_json = { version = "1" } \ No newline at end of file diff --git a/src-tauri/common/src/language.rs b/src-tauri/common/src/language.rs index 0716967a..bbd5ee76 100644 --- a/src-tauri/common/src/language.rs +++ b/src-tauri/common/src/language.rs @@ -6,9 +6,15 @@ pub fn get_system_language() -> Language { if let Ok(lang) = std::env::var("LANG") { let lang = lang.to_lowercase(); match &lang[..2] { - s if s == Language::German.to_string() => Language::German, + s if s == Language::Mandarin.to_string() => Language::Mandarin, + s if s == Language::Hindi.to_string() => Language::Hindi, s if s == Language::Spanish.to_string() => Language::Spanish, s if s == Language::French.to_string() => Language::French, + s if s == Language::Arabic.to_string() => Language::Arabic, + s if s == Language::Bengali.to_string() => Language::Bengali, + s if s == Language::Portuguese.to_string() => Language::Portuguese, + s if s == Language::Russian.to_string() => Language::Russian, + s if s == Language::Urdu.to_string() => Language::Urdu, _ => Language::English, } } else { @@ -24,9 +30,15 @@ pub fn get_system_language() -> Language { if let Ok(lang) = std::str::from_utf8(&result.stdout) { let lang = lang.trim().to_lowercase(); match lang.as_str() { - s if s == Language::German.to_string() => Language::German, + s if s == Language::Mandarin.to_string() => Language::Mandarin, + s if s == Language::Hindi.to_string() => Language::Hindi, s if s == Language::Spanish.to_string() => Language::Spanish, s if s == Language::French.to_string() => Language::French, + s if s == Language::Arabic.to_string() => Language::Arabic, + s if s == Language::Bengali.to_string() => Language::Bengali, + s if s == Language::Portuguese.to_string() => Language::Portuguese, + s if s == Language::Russian.to_string() => Language::Russian, + s if s == Language::Urdu.to_string() => Language::Urdu, _ => Language::English, } } else { @@ -46,9 +58,15 @@ pub fn get_system_language() -> Language { if let Ok(lang) = std::str::from_utf8(&result.stdout) { let lang = lang.to_lowercase(); match &lang[..2] { - s if s == Language::German.to_string() => Language::German, + s if s == Language::Mandarin.to_string() => Language::Mandarin, + s if s == Language::Hindi.to_string() => Language::Hindi, s if s == Language::Spanish.to_string() => Language::Spanish, s if s == Language::French.to_string() => Language::French, + s if s == Language::Arabic.to_string() => Language::Arabic, + s if s == Language::Bengali.to_string() => Language::Bengali, + s if s == Language::Portuguese.to_string() => Language::Portuguese, + s if s == Language::Russian.to_string() => Language::Russian, + s if s == Language::Urdu.to_string() => Language::Urdu, _ => Language::English, } } else { diff --git a/src-tauri/common/src/types/enums.rs b/src-tauri/common/src/types/enums.rs index ca659528..265358bf 100644 --- a/src-tauri/common/src/types/enums.rs +++ b/src-tauri/common/src/types/enums.rs @@ -3,6 +3,43 @@ use sea_orm::{sea_query, EnumIter}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value as JsonValue}; +#[derive(Iden, EnumIter, PartialEq, Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "lowercase")] +pub enum ClippyPosition { + #[iden = "cursor"] + Cursor, + #[iden = "top_left"] + TopLeft, + #[iden = "top_right"] + TopRight, + #[iden = "bottom_left"] + BottomLeft, + #[iden = "bottom_right"] + BottomRight, + #[iden = "top_center"] + TopCenter, + #[iden = "bottom_center"] + BottomCenter, + #[iden = "left_center"] + LeftCenter, + #[iden = "right_center"] + RightCenter, + #[iden = "center"] + Center, + #[iden = "tray_left"] + TrayLeft, + #[iden = "tray_bottom_left"] + TrayBottomLeft, + #[iden = "tray_right"] + TrayRight, + #[iden = "tray_bottom_right"] + TrayBottomRight, + #[iden = "tray_center"] + TrayCenter, + #[iden = "tray_bottom_center"] + TrayBottomCenter, +} + #[derive(Iden, EnumIter, PartialEq, Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "lowercase")] pub enum FolderLocation { @@ -17,12 +54,24 @@ pub enum FolderLocation { pub enum Language { #[iden = "en"] English, + #[iden = "zh"] + Mandarin, + #[iden = "hi"] + Hindi, #[iden = "es"] Spanish, #[iden = "fr"] French, - #[iden = "de"] - German, + #[iden = "ar"] + Arabic, + #[iden = "bn"] + Bengali, + #[iden = "pt"] + Portuguese, + #[iden = "ru"] + Russian, + #[iden = "ur"] + Urdu, } #[derive(Iden, EnumIter, PartialEq, Serialize, Deserialize, Debug, Clone)] diff --git a/src-tauri/entity/src/settings.rs b/src-tauri/entity/src/settings.rs index 73e74023..c4e55d52 100644 --- a/src-tauri/entity/src/settings.rs +++ b/src-tauri/entity/src/settings.rs @@ -20,6 +20,7 @@ pub struct Model { pub synchronize: bool, pub dark_mode: bool, pub display_scale: f32, + pub position: String, pub max_file_size: i32, pub max_image_size: i32, pub max_text_size: i32, @@ -35,6 +36,7 @@ pub enum Column { Synchronize, DarkMode, DisplayScale, + Position, MaxFileSize, MaxImageSize, MaxTextSize, @@ -67,6 +69,7 @@ impl ColumnTrait for Column { Self::Synchronize => ColumnType::Boolean.def(), Self::DarkMode => ColumnType::Boolean.def(), Self::DisplayScale => ColumnType::Float.def(), + Self::Position => ColumnType::String(StringLen::None).def(), Self::MaxFileSize => ColumnType::Integer.def(), Self::MaxImageSize => ColumnType::Integer.def(), Self::MaxTextSize => ColumnType::Integer.def(), diff --git a/src-tauri/migration/src/m000007_create_settings.rs b/src-tauri/migration/src/m000007_create_settings.rs index ca81d7a9..20c50a2b 100644 --- a/src-tauri/migration/src/m000007_create_settings.rs +++ b/src-tauri/migration/src/m000007_create_settings.rs @@ -6,7 +6,9 @@ use common::{ MAX_TEXT_SIZE, MAX_TEXT_SIZE_MIN, }, language::get_system_language, + types::enums::{ClippyPosition, Language}, }; +use sea_orm::Iterable; use sea_orm_migration::{ prelude::*, schema::{boolean, float, integer, pk_auto, string}, @@ -22,6 +24,7 @@ enum Settings { Synchronize, DarkMode, DisplayScale, + Position, // MaxFileSize, MaxImageSize, @@ -45,7 +48,14 @@ impl MigrationTrait for Migration { .col( string(Settings::Language) .string_len(2) - .default(get_system_language().to_string()), + .default(get_system_language().to_string()) + .check( + Expr::col(Settings::Language).is_in( + Language::iter() + .map(|x| x.to_string()) + .collect::>(), + ), + ), ) .col(boolean(Settings::Startup).default(true)) .col(boolean(Settings::Synchronize).default(false)) @@ -62,6 +72,17 @@ impl MigrationTrait for Migration { ), ), ) + .col( + string(Settings::Position) + .default(ClippyPosition::Cursor.to_string()) + .check( + Expr::col(Settings::Position).is_in( + ClippyPosition::iter() + .map(|x| x.to_string()) + .collect::>(), + ), + ), + ) // 10MB default, 0 min, 100MB max .col( integer(Settings::MaxFileSize).default(MAX_FILE_SIZE).check( diff --git a/src-tauri/src/commands/clipboard.rs b/src-tauri/src/commands/clipboard.rs index d88144d1..1edbcf17 100644 --- a/src-tauri/src/commands/clipboard.rs +++ b/src-tauri/src/commands/clipboard.rs @@ -23,7 +23,17 @@ pub async fn get_clipboards( star: Option, img: Option, ) -> Result { - let clipboards = get_clipboards_db(cursor, search, star, img).await?; + printlog!( + "Getting clipboards with cursor: {:?}, search: {:?}, star: {:?}, img: {:?}", + cursor, + search, + star, + img + ); + let clipboards = get_clipboards_db(cursor, search.clone(), star, img) + .await + .expect("Error getting clipboards"); + let total = get_clipboard_count_db().await?; // Calculate if there are more items diff --git a/src-tauri/src/service/clipboard.rs b/src-tauri/src/service/clipboard.rs index e9e04d84..dd243ca5 100644 --- a/src-tauri/src/service/clipboard.rs +++ b/src-tauri/src/service/clipboard.rs @@ -4,8 +4,9 @@ use common::types::enums::{ClipboardTextType, ClipboardType}; use common::types::orm_query::{ClipboardManager, ClipboardWithRelations}; use entity::clipboard::{self, Model}; use entity::{clipboard_file, clipboard_html, clipboard_image, clipboard_rtf, clipboard_text}; +use sea_orm::RelationTrait; use sea_orm::{ - ActiveModelTrait, ColumnTrait, EntityTrait, LoaderTrait, PaginatorTrait, QueryFilter, + ActiveModelTrait, ColumnTrait, EntityTrait, JoinType, LoaderTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, QueryTrait, }; use tauri::Manager; @@ -162,6 +163,14 @@ pub async fn get_clipboards_db( let db = connection::db().await?; let query = clipboard::Entity::find() + .join(JoinType::LeftJoin, clipboard::Relation::ClipboardText.def()) + .join(JoinType::LeftJoin, clipboard::Relation::ClipboardHtml.def()) + .join( + JoinType::LeftJoin, + clipboard::Relation::ClipboardImage.def(), + ) + .join(JoinType::LeftJoin, clipboard::Relation::ClipboardRtf.def()) + .join(JoinType::LeftJoin, clipboard::Relation::ClipboardFile.def()) .apply_if(star, |q, s| q.filter(clipboard::Column::Star.eq(s))) .apply_if(img, |q, _| { q.filter(clipboard::Column::Types.contains(ClipboardType::Image.to_string())) @@ -184,7 +193,17 @@ pub async fn get_clipboards_db( .eq(ClipboardTextType::Hex.to_string()) .or(clipboard_text::Column::Type.eq(ClipboardTextType::Rgb.to_string())), t @ ("hex" | "rgb") => clipboard_text::Column::Type.eq(t.to_string()), - _ => clipboard_text::Column::Data.contains(s), + _ => clipboard_text::Column::Data + .contains(&s) + .or(clipboard_file::Column::Name.contains(&s)) + .or(clipboard_file::Column::Extension.contains(&s)) + .or(clipboard_file::Column::MimeType.contains(&s)) + .or(clipboard_file::Column::Name.contains(&s)) + .or(clipboard_file::Column::Extension.contains(&s)) + .or(clipboard_image::Column::Extension.contains(&s)) + .or(clipboard_text::Column::Type.contains(&s)) + .or(clipboard_html::Column::Data.contains(&s)) + .or(clipboard_rtf::Column::Data.contains(&s)), }; q.filter(f) }) @@ -192,7 +211,9 @@ pub async fn get_clipboards_db( .limit(25) .order_by_desc(clipboard::Column::Id); - Ok(load_clipboards_with_relations(query.all(&db).await?).await) + let clipboards = query.all(&db).await?; + // printlog!("clipboards: {:?}", clipboards); + Ok(load_clipboards_with_relations(clipboards).await) } pub async fn star_clipboard_db(id: i32, star: bool) -> Result { diff --git a/src-tauri/src/service/window.rs b/src-tauri/src/service/window.rs index db03de97..244347f5 100644 --- a/src-tauri/src/service/window.rs +++ b/src-tauri/src/service/window.rs @@ -9,11 +9,12 @@ use common::constants::{ ABOUT_WINDOW_X, ABOUT_WINDOW_Y, MAIN_WINDOW_X, MAIN_WINDOW_Y, MAX_IMAGE_DIMENSIONS, SETTINGS_WINDOW_X, SETTINGS_WINDOW_Y, }; -use common::types::enums::{HotkeyEvent, ListenEvent, WebWindow}; +use common::types::enums::{ClippyPosition, HotkeyEvent, ListenEvent, WebWindow}; use std::env; use std::process::Command; use tauri::{Emitter, LogicalSize, Manager, WebviewUrl}; use tauri::{PhysicalPosition, WebviewWindowBuilder}; +use tauri_plugin_positioner::{Position, WindowExt}; /// App pub fn init_window() { @@ -55,7 +56,15 @@ pub fn toggle_main_window() { ) .expect("Failed to emit set global hotkey event"); } else { - position_window_near_cursor(); + update_main_window_position(); + tokio::task::block_in_place(|| { + tokio::runtime::Handle::current().block_on(async { + let size = calculate_logical_size(MAIN_WINDOW_X, MAIN_WINDOW_Y).await; + get_main_window() + .set_size(size) + .expect("Failed to set window size"); + }) + }); get_main_window() .emit( ListenEvent::ChangeTab.to_string().as_str(), @@ -80,6 +89,46 @@ pub fn toggle_main_window() { } } +pub fn update_main_window_position() { + tokio::task::block_in_place(|| { + tokio::runtime::Handle::current().block_on(async { + let settings = get_settings_db().await.expect("Failed to get settings"); + + if settings.position == ClippyPosition::Cursor.to_string() { + position_window_near_cursor(); + return; + } + + let position = match settings.position.as_str() { + s if s == ClippyPosition::TopLeft.to_string() => Position::TopLeft, + s if s == ClippyPosition::TopRight.to_string() => Position::TopRight, + s if s == ClippyPosition::BottomLeft.to_string() => Position::BottomLeft, + s if s == ClippyPosition::BottomRight.to_string() => Position::BottomRight, + s if s == ClippyPosition::TopCenter.to_string() => Position::TopCenter, + s if s == ClippyPosition::BottomCenter.to_string() => Position::BottomCenter, + s if s == ClippyPosition::LeftCenter.to_string() => Position::LeftCenter, + s if s == ClippyPosition::RightCenter.to_string() => Position::RightCenter, + s if s == ClippyPosition::Center.to_string() => Position::Center, + s if s == ClippyPosition::TrayLeft.to_string() => Position::TrayLeft, + s if s == ClippyPosition::TrayBottomLeft.to_string() => Position::TrayBottomLeft, + s if s == ClippyPosition::TrayRight.to_string() => Position::TrayRight, + s if s == ClippyPosition::TrayBottomRight.to_string() => Position::TrayBottomRight, + s if s == ClippyPosition::TrayCenter.to_string() => Position::TrayCenter, + s if s == ClippyPosition::TrayBottomCenter.to_string() => { + Position::TrayBottomCenter + } + _ => Position::BottomRight, // default fallback + }; + + get_main_window() + .as_ref() + .window() + .move_window(position) + .expect("Failed to move window"); + }) + }); +} + pub fn position_window_near_cursor() { let window = get_main_window(); diff --git a/src/components/elements/input.tsx b/src/components/elements/input.tsx index f6dc1b6b..110492d1 100644 --- a/src/components/elements/input.tsx +++ b/src/components/elements/input.tsx @@ -1,27 +1,42 @@ -import { Component } from "solid-js"; +import { Component, JSX, createSignal } from "solid-js"; -interface InputProps { +type InputProps = JSX.InputHTMLAttributes & { + debounce?: number; className?: string; - value: string; - onChange: (value: string) => void; - placeholder?: string; - type?: string; -} +}; + +export const Input: Component = ({ className, debounce = 0, onInput, value: initialValue = "", ...props }) => { + let timeoutId: number; + const [value, setValue] = createSignal(initialValue as string); + + const handleInput: JSX.EventHandler = (e) => { + const target = e.currentTarget; + setValue(target.value); + + if (debounce > 0) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + // @ts-ignore + onInput?.(e); + }, debounce); + } else { + // @ts-ignore + onInput?.(e); + } + }; -export const Input: Component = (props) => { return (
props.onChange(e.currentTarget.value)} - placeholder={props.placeholder} + {...props} + onInput={handleInput} + value={value()} class="w-full appearance-none bg-transparent text-sm focus:outline-none focus:ring-0 dark:text-white" />
); -}; +}; \ No newline at end of file diff --git a/src/components/pages/app/clipboard/text-clipboard.tsx b/src/components/pages/app/clipboard/text-clipboard.tsx index d66f1af2..465d083e 100644 --- a/src/components/pages/app/clipboard/text-clipboard.tsx +++ b/src/components/pages/app/clipboard/text-clipboard.tsx @@ -1,11 +1,13 @@ import dayjs from "dayjs"; -import { IoText } from "solid-icons/io"; +import { FiCode, FiFileText, FiLink } from "solid-icons/fi"; import { Component } from "solid-js"; import { ClipboardWithRelations } from "../../../../types"; -import { ClipboardType } from "../../../../types/enums"; +import { ClipboardTextType, ClipboardType } from "../../../../types/enums"; import { InvokeCommand } from "../../../../types/tauri-invoke"; +import { rgbCompatible } from "../../../../utils/colors"; import { invokeCommand } from "../../../../utils/tauri"; import { ClipboardHeader } from "../../../utils/clipboard/clipboard-header"; +import { VsDebugRestartFrame } from "solid-icons/vs"; interface TextClipboardProps { data: ClipboardWithRelations; @@ -15,6 +17,7 @@ interface TextClipboardProps { export const TextClipboard: Component = (props) => { let type = ClipboardType.Text; let data = props.data.text?.data; + let textType = props.data.text?.type as ClipboardTextType; if (!props.data.text?.data && props.data.html?.data) { type = ClipboardType.Html; @@ -25,6 +28,36 @@ export const TextClipboard: Component = (props) => { data = props.data.rtf.data; } + const getIcon = () => { + if (type === ClipboardType.Html) { + return FiCode; + } + if (type === ClipboardType.Rtf) { + return VsDebugRestartFrame; + } + + switch (textType) { + case ClipboardTextType.Link: + return FiLink; + case ClipboardTextType.Hex: + return () => ( +
+ ); + case ClipboardTextType.Rgb: + return () => ( +
+ ); + default: + return FiFileText; + } + }; + const handleClick = async (e: MouseEvent) => { e.stopPropagation(); await invokeCommand(InvokeCommand.CopyClipboard, { @@ -35,7 +68,7 @@ export const TextClipboard: Component = (props) => { return (
+
+
+ +
Switch Theme
+
+
+ +
+
+ +
+
+ +
Change Window Position
+
+ + ({ value: value, label: key }))} + value={SettingsStore.settings()!.position} + onChange={(position) => { + SettingsStore.updateSettings({ ...SettingsStore.settings()!, position: position as ClippyPosition }); + }} + /> +
+
@@ -51,7 +81,6 @@ export const SettingsGeneral: Component = ({}) => {
({ value: value, label: key }))} value={SettingsStore.settings()!.language} onChange={(language) => { @@ -63,27 +92,25 @@ export const SettingsGeneral: Component = ({}) => {
-
Display Scale
+
Window Scale
{ - SettingsStore.updateSettings({ ...SettingsStore.settings()!, display_scale: parseInt(display_scale) }); + type="number" + step="0.01" + min={0.5} + max={2} + value={SettingsStore.settings()!.display_scale} + debounce={1000} + onInput={async (e) => { + SettingsStore.updateSettings({ + ...SettingsStore.settings()!, + display_scale: Number(parseFloat(e.target.value).toFixed(2)), + }); + await invokeCommand(InvokeCommand.OpenNewWindow, { windowName: WebWindow.Settings }); }} />
- -
-
- -
Switch Theme.
-
-
- -
-
); diff --git a/src/components/utils/clipboard/clipboard-footer.tsx b/src/components/utils/clipboard/clipboard-footer.tsx deleted file mode 100644 index 81f9b5ad..00000000 --- a/src/components/utils/clipboard/clipboard-footer.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import dayjs from "dayjs"; -import { Component } from "solid-js"; -import { ClipboardWithRelations } from "../../../types"; - -interface ClipboardFooterProps { - data: ClipboardWithRelations; - index: number; -} - -export const ClipboardFooter: Component = (props) => { - return ( - <> - - - ); -}; diff --git a/src/components/utils/clipboard/clipboard-header.tsx b/src/components/utils/clipboard/clipboard-header.tsx index d5b8de52..9af35fd1 100644 --- a/src/components/utils/clipboard/clipboard-header.tsx +++ b/src/components/utils/clipboard/clipboard-header.tsx @@ -10,12 +10,10 @@ interface ClipboardHeaderProps { } export const ClipboardHeader: Component = (props) => { - const { globalHotkeyEvent } = HotkeyStore; - return (
- +
{props.index + 1}
diff --git a/src/store/clipboard-store.ts b/src/store/clipboard-store.ts index ca630c2c..02544ed1 100644 --- a/src/store/clipboard-store.ts +++ b/src/store/clipboard-store.ts @@ -32,7 +32,7 @@ function createClipboardStore() { setWhere(initialWhere); const clipboards = await getClipboards(); setClipboards(clipboards); - ClipboardStore.clipboardRef()!.scrollTo(0, 0); + ClipboardStore.clipboardRef()?.scrollTo(0, 0); }; const resetClipboards = async () => { diff --git a/src/store/settings-store.ts b/src/store/settings-store.ts index 85b69fe5..077aed81 100644 --- a/src/store/settings-store.ts +++ b/src/store/settings-store.ts @@ -40,6 +40,7 @@ function createSettingsStore() { const initSettings = async () => { const settings = await invokeCommand(InvokeCommand.GetSettings); setSettings(settings); + console.log(settings); }; const syncClipboard = async () => invokeCommand(InvokeCommand.SyncClipboardHistory); diff --git a/src/types/enums.ts b/src/types/enums.ts index bc6d971f..a0f832b6 100644 --- a/src/types/enums.ts +++ b/src/types/enums.ts @@ -9,6 +9,25 @@ export enum FolderLocation { Config = "config", } +export enum ClippyPosition { + Cursor = "cursor", + TopLeft = "top_left", + TopRight = "top_right", + BottomLeft = "bottom_left", + BottomRight = "bottom_right", + TopCenter = "top_center", + BottomCenter = "bottom_center", + LeftCenter = "left_center", + RightCenter = "right_center", + Center = "center", + TrayLeft = "tray_left", + TrayBottomLeft = "tray_bottom_left", + TrayRight = "tray_right", + TrayBottomRight = "tray_bottom_right", + TrayCenter = "tray_center", + TrayBottomCenter = "tray_bottom_center", +} + export enum Language { // ~1.1 billion speakers English = "en", diff --git a/src/types/index.ts b/src/types/index.ts index 905f5726..c6bf9f06 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,6 +1,6 @@ import { IconTypes } from "solid-icons"; import { SettingsTabName, Tab, TabName } from "../utils/constants"; -import { ClipboardTextType, ClipboardType, HotkeyEvent, Language } from "./enums"; +import { ClipboardTextType, ClipboardType, ClippyPosition, HotkeyEvent, Language } from "./enums"; export type DatabaseInfo = { records: number; @@ -107,10 +107,13 @@ export type Hotkey = { export type Settings = { id: number; language: Language; + startup: boolean; synchronize: boolean; dark_mode: boolean; display_scale: number; + position: ClippyPosition; + max_file_size: number; max_image_size: number; max_text_size: number;