From 57584d788e7383111dd106cb926468f98ecbfdf8 Mon Sep 17 00:00:00 2001 From: 0-don <70039285+0-don@users.noreply.github.com> Date: Fri, 14 Feb 2025 23:35:35 +0100 Subject: [PATCH] add text matchers & patterns --- package.json | 8 +- project.inlang/clippy-ui.babel | 752 ++++++++++++++++++ src-tauri/Cargo.lock | 527 ++++++++---- src-tauri/Cargo.toml | 4 +- src-tauri/common/Cargo.toml | 1 + src-tauri/common/src/constants.rs | 4 +- src-tauri/common/src/types/types.rs | 57 ++ src-tauri/entity/src/settings.rs | 3 + .../migration/src/m000007_create_settings.rs | 4 +- src-tauri/src/commands/settings.rs | 16 +- src-tauri/src/lib.rs | 1 + src-tauri/src/service/settings.rs | 23 +- src-tauri/src/utils/clipboard_manager.rs | 70 ++ src-tauri/tauri.conf.json | 2 +- src/components/elements/button.tsx | 31 +- src/components/elements/checkbox.tsx | 6 +- src/components/elements/input.tsx | 54 +- src/components/elements/toggle.tsx | 2 +- .../pages/settings/settings-backup.tsx | 4 +- .../pages/settings/settings-encryption.tsx | 4 +- .../pages/settings/settings-limits.tsx | 10 +- .../pages/settings/settings-patterns.tsx | 149 ++++ .../pages/settings/settings-tabs.tsx | 127 ++- src/components/utils/shortcut.tsx | 6 +- src/lib/i18n/ar.json | 13 +- src/lib/i18n/bn.json | 13 +- src/lib/i18n/de.json | 13 +- src/lib/i18n/en.json | 13 +- src/lib/i18n/es.json | 13 +- src/lib/i18n/fr.json | 13 +- src/lib/i18n/hi.json | 13 +- src/lib/i18n/it.json | 13 +- src/lib/i18n/ja.json | 13 +- src/lib/i18n/ko.json | 13 +- src/lib/i18n/nl.json | 13 +- src/lib/i18n/pl.json | 13 +- src/lib/i18n/pt.json | 13 +- src/lib/i18n/ru.json | 13 +- src/lib/i18n/th.json | 13 +- src/lib/i18n/tr.json | 13 +- src/lib/i18n/ur.json | 13 +- src/lib/i18n/vi.json | 13 +- src/lib/i18n/zh.json | 13 +- src/lib/utils.ts | 81 +- src/settings.tsx | 7 +- src/store/settings-store.ts | 7 +- src/types/index.ts | 7 + src/types/tauri-invoke.ts | 9 +- src/utils/constants.ts | 5 + 49 files changed, 1880 insertions(+), 348 deletions(-) create mode 100644 src/components/pages/settings/settings-patterns.tsx diff --git a/package.json b/package.json index eba7f1b6..a7e65d79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clippy", - "version": "1.4.0", + "version": "1.4.1", "description": "Clipboard Manager built with Rust & Typescript", "license": "MIT", "type": "module", @@ -24,12 +24,12 @@ "solid-js": "1.9.4" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.4", + "@tailwindcss/vite": "^4.0.6", "@tauri-apps/cli": "2.2.7", "cross-env": "7.0.3", - "prettier": "3.4.2", + "prettier": "3.5.1", "prettier-plugin-tailwindcss": "^0.6.11", - "tailwindcss": "^4.0.4", + "tailwindcss": "^4.0.6", "typescript": "5.7.3", "vite": "6.1.0", "vite-plugin-checker": "0.8.0", diff --git a/project.inlang/clippy-ui.babel b/project.inlang/clippy-ui.babel index b30f1d79..8cea6491 100644 --- a/project.inlang/clippy-ui.babel +++ b/project.inlang/clippy-ui.babel @@ -11048,6 +11048,675 @@ + + PATTERNS + + + ACTIONS + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + ADD + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + CHANGE_YOUR_TEXT_MATCHES + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + ENABLED + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + INFO + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + MATCH_EXPRESSION + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + REMOVE + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + SUBSTITUTION + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + + + SETTINGS @@ -11632,6 +12301,89 @@ + + PATTERNS + + + + + ar-SA + false + + + bn-IN + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + hi-IN + false + + + it-IT + false + + + ja-JP + false + + + ko-KR + false + + + nl-NL + false + + + pl-PL + false + + + pt-PT + false + + + ru-RU + false + + + th-TH + false + + + tr-TR + false + + + ur-PK + false + + + vi-VN + false + + + zh-CN + false + + + diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fbcb1fff..f259ebfc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -599,7 +599,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d59b4c170e16f0405a2e95aff44432a0d41aa97675f3d52623effe95792a037" +dependencies = [ + "objc2 0.6.0", ] [[package]] @@ -661,9 +670,9 @@ dependencies = [ [[package]] name = "built" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" +checksum = "73848a43c5d63a1251d17adf6c2bf78aa94830e60a335a95eeea45d6ba9e1e4d" [[package]] name = "bumpalo" @@ -789,9 +798,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.12" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" +checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" dependencies = [ "jobserver", "libc", @@ -854,9 +863,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.28" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" +checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" dependencies = [ "clap_builder", "clap_derive", @@ -864,9 +873,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" dependencies = [ "anstream", "anstyle", @@ -894,15 +903,16 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-rs" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c525d1554fa31abe88c8aa853d3cf0170320f6553dbc322642d4fe0a5cb2cda1" +checksum = "afede46921767868c5c7f8f55202bdd8bec0bab6bc9605174200f45924f93c62" dependencies = [ "clipboard-win", "image", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.6.0", + "objc2-app-kit 0.3.0", + "objc2-foundation 0.3.0", + "windows 0.59.0", "x11rb", ] @@ -918,10 +928,10 @@ dependencies = [ [[package]] name = "clippy" -version = "1.4.0" +version = "1.4.1" dependencies = [ "async-trait", - "base64 0.22.1", + "base64 0.21.7", "chrono", "common", "dotenvy", @@ -931,7 +941,7 @@ dependencies = [ "google-drive3", "http-body-util", "image", - "infer 0.19.0", + "infer", "migration", "mime_guess", "regex", @@ -1015,6 +1025,7 @@ dependencies = [ "entity", "global-hotkey", "google-drive3", + "regex", "sea-orm", "serde", "serde_json", @@ -1517,10 +1528,10 @@ dependencies = [ "foreign-types-shared", "libc", "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "windows", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "windows 0.58.0", "xkbcommon", "xkeysym", ] @@ -1556,9 +1567,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" @@ -2141,8 +2152,8 @@ checksum = "b00d88f1be7bf4cd2e61623ce08e84be2dfa4eab458e5d632d3dab95f16c1f64" dependencies = [ "crossbeam-channel", "keyboard-types", - "objc2", - "objc2-app-kit", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", "once_cell", "thiserror 1.0.69", "windows-sys 0.59.0", @@ -2743,15 +2754,6 @@ dependencies = [ "cfb", ] -[[package]] -name = "infer" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" -dependencies = [ - "cfb", -] - [[package]] name = "inherent" version = "1.0.11" @@ -3226,9 +3228,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" dependencies = [ "adler2", "simd-adler32", @@ -3255,9 +3257,9 @@ dependencies = [ "dpi", "gtk", "keyboard-types", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "once_cell", "png", "serde", @@ -3479,6 +3481,15 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +dependencies = [ + "objc2-encode", +] + [[package]] name = "objc2-app-kit" version = "0.2.2" @@ -3486,13 +3497,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.8.0", - "block2", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +dependencies = [ + "bitflags 2.8.0", + "block2 0.6.0", "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", + "objc2 0.6.0", + "objc2-cloud-kit 0.3.0", + "objc2-core-data 0.3.0", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.0", + "objc2-foundation 0.3.0", + "objc2-quartz-core 0.3.0", ] [[package]] @@ -3502,10 +3532,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c1948a9be5f469deadbd6bcb86ad7ff9e47b4f632380139722f7d9840c0d42c" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-foundation 0.3.0", ] [[package]] @@ -3514,9 +3555,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3526,9 +3567,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f860f8e841f6d32f754836f51e6bc7777cd7e7053cf18528233f6811d3eceb4" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-foundation 0.3.0", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -3537,22 +3611,32 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] +[[package]] +name = "objc2-core-image" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ffa6bea72bf42c78b0b34e89c0bafac877d5f80bf91e159a5d96ea7f693ca56" +dependencies = [ + "objc2 0.6.0", + "objc2-foundation 0.3.0", +] + [[package]] name = "objc2-core-location" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-contacts", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3568,10 +3652,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.8.0", - "block2", + "block2 0.5.1", "dispatch", "libc", - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +dependencies = [ + "bitflags 2.8.0", + "block2 0.6.0", + "libc", + "objc2 0.6.0", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161a8b87e32610086e1a7a9e9ec39f84459db7b3a0881c1f16ca5a2605581c19" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-core-foundation", ] [[package]] @@ -3580,10 +3688,10 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3593,9 +3701,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3605,20 +3713,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] +[[package]] +name = "objc2-quartz-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-foundation 0.3.0", +] + [[package]] name = "objc2-symbols" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3628,15 +3747,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-link-presentation", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", "objc2-symbols", "objc2-uniform-type-identifiers", "objc2-user-notifications", @@ -3648,9 +3767,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3660,10 +3779,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3673,10 +3792,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -4133,7 +4252,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.22.23", + "toml_edit 0.22.24", ] [[package]] @@ -4322,9 +4441,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" dependencies = [ "cfg_aliases", "libc", @@ -4642,7 +4761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a24763657bff09769a8ccf12c8b8a50416fb035fe199263b4c5071e4e3f006f" dependencies = [ "ashpd", - "block2", + "block2 0.5.1", "core-foundation", "core-foundation-sys", "glib-sys", @@ -4650,9 +4769,9 @@ dependencies = [ "gtk-sys", "js-sys", "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "raw-window-handle", "wasm-bindgen", "wasm-bindgen-futures", @@ -4668,15 +4787,14 @@ checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" [[package]] name = "ring" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -4782,9 +4900,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.22" +version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "once_cell", "ring", @@ -4919,9 +5037,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a93194430b419da0801f404baf3b986399d6a2a4f43bc79bc96dea83f92ca43" +checksum = "00733e5418e8ae3758cdb988c3654174e716230cc53ee2cb884207cf86a23029" dependencies = [ "async-stream", "async-trait", @@ -4947,9 +5065,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e6e0e741bfdf434e6f6aadab156ba4d439e78c9449048698d98fa377871224a" +checksum = "0646647444d3a0366e30f26ff39f1656cc062b3dbf1f2e3d70cd9dc244b62cf7" dependencies = [ "chrono", "clap", @@ -4964,9 +5082,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19e8f22fb474a8a622eb516c46885a080535d8d559386188f525977eaad32b3" +checksum = "a98408f82fb4875d41ef469a79944a7da29767c7b3e4028e22188a3dd613b10f" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -4978,9 +5096,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0bb76ba314552ce15e3a24778cf9c116fc1225fa406e48b0a36e5a3cdbc1e21" +checksum = "b97ed0bea0d92241722718e239d899c051066a5fb259ced9986b9f60e488e076" dependencies = [ "async-trait", "clap", @@ -5379,9 +5497,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" dependencies = [ "serde", ] @@ -5408,9 +5526,9 @@ dependencies = [ "foreign-types", "js-sys", "log", - "objc2", - "objc2-foundation", - "objc2-quartz-core", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", "raw-window-handle", "redox_syscall", "wasm-bindgen", @@ -5836,7 +5954,7 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows", + "windows 0.58.0", "windows-core 0.58.0", "windows-version", "x11-dl", @@ -5887,9 +6005,9 @@ dependencies = [ "log", "mime", "muda", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "percent-encoding", "plist", "raw-window-handle", @@ -5912,7 +6030,7 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows", + "windows 0.58.0", ] [[package]] @@ -6073,8 +6191,8 @@ checksum = "635ed7c580dc3cdc61c94097d38ef517d749ffc0141c806d904e68e4b0cf1c2a" dependencies = [ "dunce", "glob", - "objc2-app-kit", - "objc2-foundation", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "open", "schemars", "serde", @@ -6083,7 +6201,7 @@ dependencies = [ "tauri-plugin", "thiserror 2.0.11", "url", - "windows", + "windows 0.58.0", "zbus", ] @@ -6154,7 +6272,7 @@ dependencies = [ "tauri-utils", "thiserror 2.0.11", "url", - "windows", + "windows 0.58.0", ] [[package]] @@ -6167,9 +6285,9 @@ dependencies = [ "http", "jni", "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "percent-encoding", "raw-window-handle", "softbuffer", @@ -6179,7 +6297,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.58.0", "wry", ] @@ -6196,7 +6314,7 @@ dependencies = [ "glob", "html5ever", "http", - "infer 0.16.0", + "infer", "json-patch", "kuchikiki", "log", @@ -6471,7 +6589,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.23", + "toml_edit 0.22.24", ] [[package]] @@ -6509,15 +6627,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.23" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", - "winnow 0.7.1", + "winnow 0.7.2", ] [[package]] @@ -6605,9 +6723,9 @@ dependencies = [ "dirs 5.0.1", "libappindicator", "muda", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "once_cell", "png", "serde", @@ -7133,10 +7251,10 @@ checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows", + "windows 0.58.0", "windows-core 0.58.0", - "windows-implement", - "windows-interface", + "windows-implement 0.58.0", + "windows-interface 0.58.0", ] [[package]] @@ -7157,7 +7275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4" dependencies = [ "thiserror 1.0.69", - "windows", + "windows 0.58.0", "windows-core 0.58.0", ] @@ -7210,13 +7328,13 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window-vibrancy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea403deff7b51fff19e261330f71608ff2cdef5721d72b64180bb95be7c4150" +checksum = "831ad7678290beae36be6f9fad9234139c7f00f3b536347de7745621716be82d" dependencies = [ - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "raw-window-handle", "windows-sys 0.59.0", "windows-version", @@ -7232,6 +7350,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +dependencies = [ + "windows-core 0.59.0", + "windows-targets 0.53.0", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -7247,13 +7375,26 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-strings", + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" +dependencies = [ + "windows-implement 0.59.0", + "windows-interface 0.59.0", + "windows-result 0.3.0", + "windows-strings 0.3.0", + "windows-targets 0.53.0", +] + [[package]] name = "windows-implement" version = "0.58.0" @@ -7265,6 +7406,17 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "windows-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "windows-interface" version = "0.58.0" @@ -7276,14 +7428,25 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "windows-interface" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", - "windows-strings", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] @@ -7296,16 +7459,34 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34" +dependencies = [ + "windows-targets 0.53.0", +] + [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491" +dependencies = [ + "windows-targets 0.53.0", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -7613,9 +7794,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" dependencies = [ "memchr", ] @@ -7667,7 +7848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2e33c08b174442ff80d5c791020696f9f8b4e4a87b8cfc7494aad6167ec44e1" dependencies = [ "base64 0.22.1", - "block2", + "block2 0.5.1", "cookie", "crossbeam-channel", "dpi", @@ -7681,9 +7862,9 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "objc2-ui-kit", "objc2-web-kit", "once_cell", @@ -7697,7 +7878,7 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows", + "windows 0.58.0", "windows-core 0.58.0", "windows-version", "x11-dl", @@ -7836,9 +8017,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbddd8b6cb25d5d8ec1b23277b45299a98bfb220f1761ca11e186d5c702507f8" +checksum = "59c333f648ea1b647bc95dc1d34807c8e25ed7a6feff3394034dc4776054b236" dependencies = [ "async-broadcast", "async-executor", @@ -7853,7 +8034,7 @@ dependencies = [ "enumflags2", "event-listener 5.4.0", "futures-core", - "futures-util", + "futures-lite", "hex", "nix", "ordered-stream", @@ -7864,7 +8045,7 @@ dependencies = [ "tracing", "uds_windows", "windows-sys 0.59.0", - "winnow 0.7.1", + "winnow 0.7.2", "xdg-home", "zbus_macros", "zbus_names", @@ -7873,9 +8054,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac404d48b4e9cf193c8b49589f3280ceca5ff63519e7e64f55b4cf9c47ce146" +checksum = "f325ad10eb0d0a3eb060203494c3b7ec3162a01a59db75d2deee100339709fc0" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -7894,7 +8075,7 @@ checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" dependencies = [ "serde", "static_assertions", - "winnow 0.7.1", + "winnow 0.7.2", "zvariant", ] @@ -7994,25 +8175,25 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.3.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c951c21879c6e1d46ac5adfc34f698fefb465d498cf4ac87545849bd71bb5a" +checksum = "b2df9ee044893fcffbdc25de30546edef3e32341466811ca18421e3cd6c5a3ac" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", "url", - "winnow 0.7.1", + "winnow 0.7.2", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.3.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eeb539471af098d9e63faf428c71ac4cd4efe0b5baa3c8a6b991c5f2543b70e" +checksum = "74170caa85b8b84cc4935f2d56a57c7a15ea6185ccdd7eadb57e6edd90f94b2f" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -8032,5 +8213,5 @@ dependencies = [ "serde", "static_assertions", "syn 2.0.98", - "winnow 0.7.1", + "winnow 0.7.2", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cde239e7..9eb1ea12 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "1.4.0" +version = "1.4.1" description = "Clipboard Manager built with Rust & Typescript" authors = ["0-don"] license = "MIT" @@ -48,6 +48,8 @@ serde_json = "1" dotenvy = "0" chrono = "0" + +# text matchers regex = "1" # keyboard input diff --git a/src-tauri/common/Cargo.toml b/src-tauri/common/Cargo.toml index db246558..50f437b5 100644 --- a/src-tauri/common/Cargo.toml +++ b/src-tauri/common/Cargo.toml @@ -21,3 +21,4 @@ global-hotkey = "0" sea-orm = "1" tl = "0" chrono = "0" +regex = "1" \ No newline at end of file diff --git a/src-tauri/common/src/constants.rs b/src-tauri/common/src/constants.rs index 17006769..73ae729e 100644 --- a/src-tauri/common/src/constants.rs +++ b/src-tauri/common/src/constants.rs @@ -23,8 +23,8 @@ pub static MAIN_WINDOW_Y: i32 = 600; pub static ABOUT_WINDOW_X: i32 = 375; pub static ABOUT_WINDOW_Y: i32 = 600; -pub static SETTINGS_WINDOW_X: i32 = 580; -pub static SETTINGS_WINDOW_Y: i32 = 580; +pub static SETTINGS_WINDOW_X: i32 = 600; +pub static SETTINGS_WINDOW_Y: i32 = 600; pub static MAX_IMAGE_DIMENSIONS: u32 = 1280; pub static MAX_TEXT_PREVIEW: usize = 500; // Adjust preview length as needed diff --git a/src-tauri/common/src/types/types.rs b/src-tauri/common/src/types/types.rs index bbb030fa..c63b5b72 100644 --- a/src-tauri/common/src/types/types.rs +++ b/src-tauri/common/src/types/types.rs @@ -1,5 +1,6 @@ use global_hotkey::hotkey::HotKey; use serde::{Deserialize, Serialize}; +use serde_json::{json, Value as JsonValue}; #[derive(Serialize, Deserialize, Debug)] pub struct Config { @@ -64,3 +65,59 @@ impl From for CommandError { CommandError::Error(err.to_string()) } } + +#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Clone)] +pub struct TextMatcher { + match_expression: String, // or search_expression + substitution: String, // or replacement_text + enabled: bool, +} + +impl TextMatcher { + pub fn replace_matches(&self, text: &str) -> Option { + if !self.enabled { + return None; + } + + // Cant be empty else select all text + if self.match_expression.is_empty() { + return None; + } + + // Try as Regex first with case insensitive flag + if let Ok(regex) = regex::RegexBuilder::new(&self.match_expression) + .case_insensitive(true) + .build() + { + let replaced = regex.replace_all(text, &self.substitution); + if replaced != text { + return Some(replaced.into_owned()); + } + } + + // Try as glob pattern if regex doesn't match + let text_lower = text.to_lowercase(); + let pattern_lower = self.match_expression.to_lowercase(); + + if text_lower.contains(&pattern_lower) { + let mut result = text.to_string(); + let mut start = 0; + while let Some(pos) = text_lower[start..].find(&pattern_lower) { + let abs_pos = start + pos; + let end_pos = abs_pos + self.match_expression.len(); + result.replace_range(abs_pos..end_pos, &self.substitution); + start = abs_pos + self.substitution.len(); + } + return Some(result); + } + + None + } + + pub fn from_json_value(value: &JsonValue) -> Vec { + match value { + JsonValue::Array(arr) => serde_json::from_value(json!(arr)).unwrap_or_else(|_| vec![]), + _ => vec![], + } + } +} diff --git a/src-tauri/entity/src/settings.rs b/src-tauri/entity/src/settings.rs index 2bbc5973..b4b41805 100644 --- a/src-tauri/entity/src/settings.rs +++ b/src-tauri/entity/src/settings.rs @@ -18,6 +18,7 @@ impl EntityName for Entity { pub struct Model { pub id: i32, pub language: String, + pub text_matchers: Json, pub startup: bool, pub sync: bool, pub sync_limit: i32, @@ -39,6 +40,7 @@ pub struct Model { pub enum Column { Id, Language, + TextMatchers, Startup, Sync, SyncLimit, @@ -77,6 +79,7 @@ impl ColumnTrait for Column { match self { Self::Id => ColumnType::Integer.def(), Self::Language => ColumnType::String(StringLen::N(2u32)).def(), + Self::TextMatchers => ColumnType::Json.def(), Self::Startup => ColumnType::Boolean.def(), Self::Sync => ColumnType::Boolean.def(), Self::SyncLimit => ColumnType::Integer.def(), diff --git a/src-tauri/migration/src/m000007_create_settings.rs b/src-tauri/migration/src/m000007_create_settings.rs index 100ccaa5..540c0a97 100644 --- a/src-tauri/migration/src/m000007_create_settings.rs +++ b/src-tauri/migration/src/m000007_create_settings.rs @@ -12,7 +12,7 @@ use common::{ use sea_orm::Iterable; use sea_orm_migration::{ prelude::*, - schema::{boolean, float, integer, pk_auto, string}, + schema::{boolean, float, integer, json, pk_auto, string}, }; #[derive(Iden)] @@ -20,6 +20,7 @@ enum Settings { Table, Id, Language, + TextMatchers, // Startup, Sync, @@ -71,6 +72,7 @@ impl MigrationTrait for Migration { ), ), ) + .col(json(Settings::TextMatchers).default(Expr::value("[]"))) // TextMachters .col(boolean(Settings::Startup).default(true)) .col(boolean(Settings::Sync).default(false)) .col( diff --git a/src-tauri/src/commands/settings.rs b/src-tauri/src/commands/settings.rs index 04bbe5d0..c52add76 100644 --- a/src-tauri/src/commands/settings.rs +++ b/src-tauri/src/commands/settings.rs @@ -1,5 +1,10 @@ -use crate::{service::settings::{autostart, get_settings_db, update_settings_db}, tao::config::{change_clipboard_db_location_enable, reset_clipboard_db_location_disable}}; -use common::types::types::CommandError; +use crate::{ + service::settings::{ + autostart, get_settings_db, update_settings_db, update_settings_text_matchers, + }, + tao::config::{change_clipboard_db_location_enable, reset_clipboard_db_location_disable}, +}; +use common::types::types::{CommandError, TextMatcher}; use entity::settings::Model; #[tauri::command] @@ -14,6 +19,13 @@ pub async fn update_settings(settings: Model) { .expect("Failed to update settings"); } +#[tauri::command] +pub async fn change_settings_text_matchers(text_matchers: Vec) { + update_settings_text_matchers(text_matchers) + .await + .expect("Failed to update replace patterns"); +} + #[tauri::command] pub async fn toggle_autostart() { autostart() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 48ad54db..df9ff083 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -44,6 +44,7 @@ pub fn run() { // settings::get_settings, settings::update_settings, + settings::change_settings_text_matchers, settings::toggle_autostart, settings::change_clipboard_db_location, settings::reset_clipboard_db_location, diff --git a/src-tauri/src/service/settings.rs b/src-tauri/src/service/settings.rs index 37415672..d961dac1 100644 --- a/src-tauri/src/service/settings.rs +++ b/src-tauri/src/service/settings.rs @@ -8,9 +8,10 @@ use crate::tao::connection::db; use crate::tao::global::get_app; use common::io::language::get_system_language; use common::types::enums::{ListenEvent, PasswordAction}; -use common::types::types::CommandError; +use common::types::types::{CommandError, TextMatcher}; use entity::settings; use sea_orm::{ActiveModelTrait, EntityTrait}; +use serde_json::json; use std::collections::HashMap; use std::sync::Mutex; use tauri::Manager; @@ -106,6 +107,26 @@ pub fn setup_settings() { }); } +pub async fn update_settings_text_matchers( + text_matchers: Vec, +) -> Result, CommandError> { + let mut settings = get_global_settings(); + + settings.text_matchers = json!(text_matchers); + + let active_model: settings::ActiveModel = settings.into(); + + let settings = settings::Entity::update(active_model.reset_all()) + .exec(&db().await?) + .await?; + + set_global_settings(settings.clone()); + + init_settings_window(); + + Ok(text_matchers) +} + pub async fn update_settings_from_sync( remote_settings: HashMap, ) -> Result<(), Box> { diff --git a/src-tauri/src/utils/clipboard_manager.rs b/src-tauri/src/utils/clipboard_manager.rs index 595e3115..3ac97fb2 100644 --- a/src-tauri/src/utils/clipboard_manager.rs +++ b/src-tauri/src/utils/clipboard_manager.rs @@ -12,6 +12,7 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use chrono::DateTime; use common::types::enums::{ClipboardTextType, ClipboardType}; use common::types::orm_query::FullClipboardDbo; +use common::types::types::TextMatcher; use image::imageops; use regex::Regex; use sea_orm::prelude::Uuid; @@ -36,6 +37,7 @@ pub trait ClipboardManagerExt { ) -> (); fn parse_image_model(&mut self, img_bytes: Vec); fn parse_file_models(&mut self, file_paths: Vec) -> std::io::Result<()>; + fn apply_text_matchers(&mut self) -> bool; } impl ClipboardManagerExt for FullClipboardDbo { @@ -79,7 +81,22 @@ impl ClipboardManagerExt for FullClipboardDbo { } } + let content_changed = manager.apply_text_matchers(); + if !manager.check_if_last_is_same().await && manager.clipboard_model.types.is_set() { + if content_changed { + // Update system clipboard with modified content if pattern replacements were applied + if let sea_orm::ActiveValue::Set(text) = manager.clipboard_text_model.data { + return clipboard.write_text(text).expect("Failed to write text"); + } + if let sea_orm::ActiveValue::Set(html) = manager.clipboard_html_model.data { + return clipboard.write_html(html).expect("Failed to write html"); + } + if let sea_orm::ActiveValue::Set(rtf) = manager.clipboard_rtf_model.data { + return clipboard.write_rtf(rtf).expect("Failed to write rtf"); + } + } + // insert default not encrypted clipboard let clipboard = insert_clipboard_dbo(manager) .await @@ -389,4 +406,57 @@ impl ClipboardManagerExt for FullClipboardDbo { } Ok(()) } + + fn apply_text_matchers(&mut self) -> bool { + let text_matchers = TextMatcher::from_json_value(&get_global_settings().text_matchers); + let mut content_changed = false; + + // Handle text content + if let sea_orm::ActiveValue::Set(ref text) = self.clipboard_text_model.data { + let mut new_text = text.clone(); + for pattern in &text_matchers { + if let Some(replaced) = pattern.replace_matches(&new_text) { + new_text = replaced; + content_changed = true; + } + } + if content_changed { + self.clipboard_text_model.data = Set(new_text); + } + } + + // Handle HTML content + if let sea_orm::ActiveValue::Set(ref html) = self.clipboard_html_model.data { + let mut new_html = html.clone(); + let mut html_changed = false; + for pattern in &text_matchers { + if let Some(replaced) = pattern.replace_matches(&new_html) { + new_html = replaced; + html_changed = true; + } + } + if html_changed { + self.clipboard_html_model.data = Set(new_html); + content_changed = true; + } + } + + // Handle RTF content + if let sea_orm::ActiveValue::Set(ref rtf) = self.clipboard_rtf_model.data { + let mut new_rtf = rtf.clone(); + let mut rtf_changed = false; + for pattern in &text_matchers { + if let Some(replaced) = pattern.replace_matches(&new_rtf) { + new_rtf = replaced; + rtf_changed = true; + } + } + if rtf_changed { + self.clipboard_rtf_model.data = Set(new_rtf); + content_changed = true; + } + } + + content_changed + } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 26fb08fa..4b38961a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "clippy", - "version": "1.4.0", + "version": "1.4.1", "identifier": "clippy", "build": { "beforeDevCommand": "npm run dev", diff --git a/src/components/elements/button.tsx b/src/components/elements/button.tsx index 7c407bba..e9fcb553 100644 --- a/src/components/elements/button.tsx +++ b/src/components/elements/button.tsx @@ -1,32 +1,33 @@ import { IconTypes } from "solid-icons"; -import { Component, JSX } from "solid-js"; +import { Component, ComponentProps, splitProps } from "solid-js"; import { DictionaryKey } from "../../lib/i18n"; +import { cn } from "../../lib/utils"; import { useLanguage } from "../provider/language-provider"; -interface ButtonProps { +type ButtonProps = ComponentProps<"button"> & { label: DictionaryKey; - className?: string; iconClassName?: string; - type?: HTMLButtonElement["type"]; Icon?: IconTypes; - onClick?: JSX.EventHandlerUnion; - children?: JSX.Element; - disabled?: boolean; -} +}; export const Button: Component = (props) => { + const [local, buttonProps] = splitProps(props, ["label", "iconClassName", "Icon", "children", "class"]); + const { t } = useLanguage(); return ( ); }; diff --git a/src/components/elements/checkbox.tsx b/src/components/elements/checkbox.tsx index c3e5224e..2e530def 100644 --- a/src/components/elements/checkbox.tsx +++ b/src/components/elements/checkbox.tsx @@ -2,7 +2,7 @@ import { FiCheck } from "solid-icons/fi"; import { Component } from "solid-js"; interface CheckBoxProps { - text: string; + label?: string; checked: boolean; onChange: (check: boolean) => void; } @@ -10,7 +10,7 @@ interface CheckBoxProps { export const CheckBox: Component = (props) => { return ( ); }; diff --git a/src/components/elements/input.tsx b/src/components/elements/input.tsx index 71d70bbe..3f8e9205 100644 --- a/src/components/elements/input.tsx +++ b/src/components/elements/input.tsx @@ -1,47 +1,47 @@ -import { Component, JSX, createSignal } from "solid-js"; +import { Component, ComponentProps, JSX, splitProps } from "solid-js"; +import { cn } from "../../lib/utils"; -type InputProps = JSX.InputHTMLAttributes & { +type InputProps = ComponentProps<"input"> & { debounce?: number; - className?: string; }; -export const Input: Component = ({ - className, - debounce = 0, - onInput, - value: initialValue = "", - ...props -}) => { +export const Input: Component = (props) => { + const [local, inputProps] = splitProps(props, ["debounce", "onInput", "class"]); let timeoutId: number; - const [value, setValue] = createSignal(initialValue as string); - const handleInput: JSX.EventHandler = (e) => { - const target = e.currentTarget; - setValue(target.value); + const onInput: JSX.EventHandler = (e) => { + if (!local.onInput) return; - if (debounce > 0) { + const handler = typeof local.onInput === "function" ? local.onInput : local.onInput[0]; + + if (local.debounce) { clearTimeout(timeoutId); + const value = e.currentTarget.value; + const input = e.currentTarget; timeoutId = setTimeout(() => { - // @ts-ignore - onInput?.(e); - }, debounce); + input.value = value; + handler({ + ...e, + currentTarget: input, + target: input, + }); + }, local.debounce); } else { - // @ts-ignore - onInput?.(e); + handler(e); } }; return (
); diff --git a/src/components/elements/toggle.tsx b/src/components/elements/toggle.tsx index 5ee302bf..8b8eb780 100644 --- a/src/components/elements/toggle.tsx +++ b/src/components/elements/toggle.tsx @@ -5,7 +5,7 @@ import { cn } from "../../lib/utils"; type ToggleProps = { checked?: boolean; - onChange?: (val: boolean) => Promise | undefined; + onChange?: (val: boolean) => void; disabled?: boolean; }; diff --git a/src/components/pages/settings/settings-backup.tsx b/src/components/pages/settings/settings-backup.tsx index ae5696ce..5d72b5b4 100644 --- a/src/components/pages/settings/settings-backup.tsx +++ b/src/components/pages/settings/settings-backup.tsx @@ -9,12 +9,12 @@ import { HotkeyStore } from "../../../store/hotkey-store"; import { SettingsStore } from "../../../store/settings-store"; import { FolderLocation, HotkeyEvent } from "../../../types/enums"; import { InvokeCommand } from "../../../types/tauri-invoke"; +import { MAX_SYNC_LIMIT } from "../../../utils/constants"; import { Button } from "../../elements/button"; import { Input } from "../../elements/input"; import { TextBlock } from "../../elements/text-block"; import { Toggle } from "../../elements/toggle"; import { useLanguage } from "../../provider/language-provider"; -import { MAX_SYNC_LIMIT } from "../../../utils/constants"; interface SettingsBackupProps {} @@ -111,7 +111,7 @@ export const SettingsBackup: Component = ({}) => { - )} - - +
+ +
); }; diff --git a/src/components/utils/shortcut.tsx b/src/components/utils/shortcut.tsx index 23f5e407..62dc61d5 100644 --- a/src/components/utils/shortcut.tsx +++ b/src/components/utils/shortcut.tsx @@ -23,17 +23,17 @@ export const Shortcut: Component = (props) => { HotkeyStore.updateHotkey({ ...props.hotkey, ctrl })} - text={t("MAIN.KEYS.CTRL")} + label={t("MAIN.KEYS.CTRL")} /> HotkeyStore.updateHotkey({ ...props.hotkey, alt })} - text={t("MAIN.KEYS.ALT")} + label={t("MAIN.KEYS.ALT")} /> HotkeyStore.updateHotkey({ ...props.hotkey, shift })} - text={t("MAIN.KEYS.SHIFT")} + label={t("MAIN.KEYS.SHIFT")} /> => - value !== null && typeof value === "object" && !Array.isArray(value); - - // clsx functionality - function clsx(classes: ClassValue[]): string { - return classes - .flat() - .filter(Boolean) - .map((cls): string => { - if (typeof cls === "string") return cls; - if (isObject(cls)) { - return Object.entries(cls) - .filter(([_, value]) => Boolean(value)) - .map(([key]) => key) - .join(" "); - } - return ""; - }) - .join(" "); - } - - // Simplified tailwind-merge functionality - function twMerge(classString: string): string { - const classes = classString.split(" "); - const classMap = new Map(); - - const prefixes: readonly string[] = [ - "p-", - "m-", - "text-", - "bg-", - "border-", - "rounded-", - "flex-", - "grid-", - "w-", - "h-", - "min-", - "max-", - "font-", - "leading-", - ] as const; + return clsx(classLists); +} - classes.forEach((cls) => { - const prefix = prefixes.find((p) => cls.startsWith(p)); - if (prefix) { - classMap.set(prefix, cls); - } else { - classMap.set(cls, cls); +function clsx(classes: ClassValue[]): string { + return classes + .flat() + .filter(Boolean) + .map((cls): string => { + if (typeof cls === "string") return cls; + if (isObject(cls)) { + return Object.entries(cls) + .filter(([_, value]) => Boolean(value)) + .map(([key]) => key) + .join(" "); } - }); - - return Array.from(classMap.values()).join(" "); - } - - // Combine both functions - return twMerge(clsx(classLists)); + return ""; + }) + .join(" "); } + +const isObject = (value: any): value is Record => + value !== null && typeof value === "object" && !Array.isArray(value); diff --git a/src/settings.tsx b/src/settings.tsx index c0343c07..4a803ad2 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -6,6 +6,7 @@ import { SettingsGeneral } from "./components/pages/settings/settings-general"; import { SettingsHistory } from "./components/pages/settings/settings-history"; import { SettingsHotkeys } from "./components/pages/settings/settings-hotkeys"; import { SettingsLimits } from "./components/pages/settings/settings-limits"; +import { SettingsPatterns } from "./components/pages/settings/settings-patterns"; import { Tabs } from "./components/pages/settings/settings-tabs"; import LanguageProvider from "./components/provider/language-provider"; import { listenEvent } from "./lib/tauri"; @@ -25,7 +26,7 @@ const Settings = () => { }); return ( -
+
@@ -48,6 +49,10 @@ const Settings = () => { + + + + diff --git a/src/store/settings-store.ts b/src/store/settings-store.ts index 685ad075..10de0759 100644 --- a/src/store/settings-store.ts +++ b/src/store/settings-store.ts @@ -2,7 +2,7 @@ import { BsDatabaseFillGear, BsDatabaseLock } from "solid-icons/bs"; import { HiSolidCog8Tooth } from "solid-icons/hi"; import { RiDeviceKeyboardFill } from "solid-icons/ri"; import { TbResize } from "solid-icons/tb"; -import { VsHistory } from "solid-icons/vs"; +import { VsHistory, VsReplaceAll } from "solid-icons/vs"; import { createRoot, createSignal } from "solid-js"; import { invokeCommand } from "../lib/tauri"; import { Settings, SettingsTab } from "../types"; @@ -32,6 +32,11 @@ function createSettingsStore() { }, { name: SETTINGS_TAB[5], + Icon: VsReplaceAll, + current: false, + }, + { + name: SETTINGS_TAB[6], Icon: TbResize, current: false, }, diff --git a/src/types/index.ts b/src/types/index.ts index d8b29063..9a0ca621 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -119,6 +119,7 @@ export type Hotkey = { export type Settings = { id: number; language: Language; + text_matchers: TextMatcher[]; startup: boolean; sync: boolean; sync_limit: number; @@ -134,3 +135,9 @@ export type Settings = { max_rtf_size: number; max_html_size: number; }; + +export type TextMatcher = { + match_expression: string; + substitution: string; + enabled: boolean; +}; diff --git a/src/types/tauri-invoke.ts b/src/types/tauri-invoke.ts index 85725f09..dab4b28f 100644 --- a/src/types/tauri-invoke.ts +++ b/src/types/tauri-invoke.ts @@ -1,4 +1,4 @@ -import { ClipboardResponse, ClipboardWhere, DatabaseInfo, Hotkey, Settings } from "."; +import { ClipboardResponse, ClipboardWhere, DatabaseInfo, Hotkey, Settings, TextMatcher } from "."; import { ClipboardType, FolderLocation, PasswordAction, WebWindow } from "./enums"; export enum InvokeCommand { @@ -18,6 +18,7 @@ export enum InvokeCommand { // Settings commands GetSettings = "get_settings", UpdateSettings = "update_settings", + ChangeSettingsTextMatchers = "change_settings_text_matchers", ToggleAutostart = "toggle_autostart", ChangeClipboardDbLocation = "change_clipboard_db_location", ResetClipboardDbLocation = "reset_clipboard_db_location", @@ -94,6 +95,10 @@ export interface TauriInvokeCommands { args: { settings: Settings }; return: void; }; + [InvokeCommand.ChangeSettingsTextMatchers]: { + args: { textMatchers: TextMatcher[] }; + return: TextMatcher[]; + }; [InvokeCommand.ToggleAutostart]: { args: undefined; return: void; @@ -145,7 +150,7 @@ export interface TauriInvokeCommands { return: void; }; [InvokeCommand.PasswordUnlock]: { - args: { password: string, action: PasswordAction }; + args: { password: string; action: PasswordAction }; return: void; }; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 5575d1c1..340077b4 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -7,6 +7,10 @@ export const DEFAULT_SIZE = 10_485_760; export const MIN_PASSWORD_LENGTH = 1; export const MAX_PASSWORD_LENGTH = 128; +export const MIN_PATTERN_LENGTH = 1; +export const MAX_PATTERN_LENGTH = 128; +export const MIN_DESCRIPTION_LENGTH = 1; +export const MAX_DESCRIPTION_LENGTH = 128; export const MAX_SYNC_LIMIT = 250; @@ -16,6 +20,7 @@ export const SETTINGS_TAB = [ "SETTINGS.TAB.ENCRYPTION", "SETTINGS.TAB.HISTORY", "SETTINGS.TAB.HOTKEYS", + "SETTINGS.TAB.PATTERNS", "SETTINGS.TAB.LIMITS", ] as const satisfies readonly DictionaryKey[];