From aa56cac95890b0e568b4042f4f6a0866c080f597 Mon Sep 17 00:00:00 2001 From: Eduard Tolosa Date: Tue, 26 May 2026 21:32:56 -0500 Subject: [PATCH] deps+fix: upgrade zbus 5 / rusqlite 0.40 / dirs 6; daemon hardening Dependency major upgrades (zbus 4->5, rusqlite 0.31->0.40, dirs 5->6) and the migration + hardening that came with the review: - zbus 5: SignalContext -> SignalEmitter, signal_context() -> signal_emitter(). - Single-instance D-Bus name: request with DoNotQueue instead of ReplaceExisting|AllowReplacement. If the name is already owned the daemon now exits instead of running without owning it (zbus 5 returns InQueue as Ok) or stealing the name and orphaning the running instance (zbus does not terminate a replaced owner). The extension already skips spawning when the name is owned, so replacement was never needed. - Stop swallowing real SQLite errors: upsert_item's dedup SELECT and get_thumbnail/get_raw_item now use .optional().context()? so a missing row is Ok(None) and a genuine error propagates instead of masquerading as not-found. - clippy pedantic/nursery cleanup: uninlined format args, redundant mime clone, pass ObjectId/Connection by reference where not consumed, match->if/is_ok, doc backticks; #[allow] with rationale for the intentional lints (significant_drop_tightening on the single-writer lock, unused_async on zbus interface methods). Co-Authored-By: Claude Opus 4.7 --- strata-daemon/Cargo.lock | 499 +++++-------------------- strata-daemon/Cargo.toml | 6 +- strata-daemon/src/clipboard/monitor.rs | 16 +- strata-daemon/src/clipboard/writer.rs | 2 +- strata-daemon/src/db.rs | 87 +++-- strata-daemon/src/dbus_service.rs | 36 +- strata-daemon/src/main.rs | 42 ++- 7 files changed, 196 insertions(+), 492 deletions(-) diff --git a/strata-daemon/Cargo.lock b/strata-daemon/Cargo.lock index 892f72b..247cdfd 100644 --- a/strata-daemon/Cargo.lock +++ b/strata-daemon/Cargo.lock @@ -8,18 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -85,17 +73,6 @@ dependencies = [ "slab", ] -[[package]] -name = "async-fs" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - [[package]] name = "async-io" version = "2.6.0" @@ -111,7 +88,7 @@ dependencies = [ "polling", "rustix", "slab", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -169,7 +146,7 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -218,16 +195,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "cpufeatures 0.3.0", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", + "cpufeatures", ] [[package]] @@ -283,12 +251,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "color_quant" version = "1.1.0" @@ -310,15 +272,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "cpufeatures" version = "0.3.0" @@ -349,45 +302,25 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -436,7 +369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -521,6 +454,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "futures-core" version = "0.3.32" @@ -546,12 +485,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - [[package]] name = "futures-task" version = "0.3.32" @@ -565,24 +498,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", - "futures-io", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -628,22 +548,22 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", ] [[package]] @@ -654,11 +574,11 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.16.1", ] [[package]] @@ -773,9 +693,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.28.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +checksum = "a76001fb4daed01e5f2b518aac0b4dc592e7c734da63dbffcf0c64fa612a8d0c" dependencies = [ "cc", "pkg-config", @@ -845,7 +765,7 @@ checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -858,19 +778,6 @@ dependencies = [ "pxfm", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - [[package]] name = "nom" version = "8.0.0" @@ -886,7 +793,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -927,7 +834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1017,16 +924,7 @@ dependencies = [ "hermit-abi", "pin-project-lite", "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", + "windows-sys", ] [[package]] @@ -1093,36 +991,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1134,13 +1002,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -1161,10 +1029,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "rusqlite" -version = "0.31.0" +name = "rsqlite-vfs" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" +checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" +dependencies = [ + "hashbrown 0.16.1", + "thiserror", +] + +[[package]] +name = "rusqlite" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b3492ea85308705c3a5cc24fb9b9cf77273d30590349070db42991202b214c4" dependencies = [ "bitflags", "fallible-iterator", @@ -1172,6 +1050,7 @@ dependencies = [ "hashlink", "libsqlite3-sys", "smallvec", + "sqlite-wasm-rs", ] [[package]] @@ -1184,7 +1063,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1259,17 +1138,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -1320,14 +1188,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "sqlite-wasm-rs" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] [[package]] name = "strata-daemon" @@ -1372,16 +1246,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", + "windows-sys", ] [[package]] @@ -1390,18 +1255,7 @@ version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1453,7 +1307,7 @@ dependencies = [ "socket2", "tokio-macros", "tracing", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1569,12 +1423,6 @@ dependencies = [ "petgraph", ] -[[package]] -name = "typenum" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" - [[package]] name = "uds_windows" version = "1.2.1" @@ -1583,7 +1431,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1606,6 +1454,7 @@ checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", + "serde_core", "wasm-bindgen", ] @@ -1621,12 +1470,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1812,33 +1655,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -1848,127 +1664,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "winnow" version = "1.0.3" @@ -2082,7 +1777,7 @@ dependencies = [ "log", "os_pipe", "rustix", - "thiserror 2.0.18", + "thiserror", "tree_magic_mini", "wayland-backend", "wayland-client", @@ -2090,25 +1785,14 @@ dependencies = [ "wayland-protocols-wlr", ] -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "zbus" -version = "4.4.0" +version = "5.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" dependencies = [ "async-broadcast", "async-executor", - "async-fs", "async-io", "async-lock", "async-process", @@ -2119,21 +1803,19 @@ dependencies = [ "enumflags2", "event-listener", "futures-core", - "futures-sink", - "futures-util", + "futures-lite", "hex", - "nix", + "libc", "ordered-stream", - "rand", + "rustix", "serde", "serde_repr", - "sha1", - "static_assertions", "tokio", "tracing", "uds_windows", - "windows-sys 0.52.0", - "xdg-home", + "uuid", + "windows-sys", + "winnow", "zbus_macros", "zbus_names", "zvariant", @@ -2141,25 +1823,27 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.4.0" +version = "5.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" dependencies = [ "serde", - "static_assertions", + "winnow", "zvariant", ] @@ -2206,22 +1890,23 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.2.0" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" dependencies = [ "endi", "enumflags2", "serde", - "static_assertions", + "winnow", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.2.0" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2232,11 +1917,13 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "2.1.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" dependencies = [ "proc-macro2", "quote", + "serde", "syn", + "winnow", ] diff --git a/strata-daemon/Cargo.toml b/strata-daemon/Cargo.toml index 77aa26e..713f29d 100644 --- a/strata-daemon/Cargo.toml +++ b/strata-daemon/Cargo.toml @@ -13,7 +13,7 @@ path = "src/main.rs" tokio = { version = "1", features = ["full"] } # D-Bus (async, tokio-native) -zbus = { version = "4", features = ["tokio"] } +zbus = { version = "5", features = ["tokio"] } # Wayland clipboard monitoring (custom event loop) wayland-client = "0.31" @@ -25,7 +25,7 @@ wayland-protocols-wlr = { version = "0.3", features = ["client"] } wl-clipboard-rs = "0.9" # Storage -rusqlite = { version = "0.31", features = ["bundled"] } +rusqlite = { version = "0.40", features = ["bundled"] } serde = { version = "1", features = ["derive"] } serde_json = "1" uuid = { version = "1", features = ["v4"] } @@ -41,7 +41,7 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } # XDG paths -dirs = "5" +dirs = "6" # Error handling anyhow = "1" diff --git a/strata-daemon/src/clipboard/monitor.rs b/strata-daemon/src/clipboard/monitor.rs index d8e944a..1d6f9d4 100644 --- a/strata-daemon/src/clipboard/monitor.rs +++ b/strata-daemon/src/clipboard/monitor.rs @@ -1,7 +1,7 @@ /// Wayland clipboard monitor using the ext-data-control-v1 protocol with a /// zwlr-data-control-v1 fallback for wlroots-based compositors. GNOME's Mutter /// exposes neither, so on GNOME this monitor does not bind and clipboard -/// content arrives from the extension via Meta.Selection + SubmitItem. +/// content arrives from the extension via Meta.Selection + `SubmitItem`. /// /// Runs on a dedicated OS thread (NOT on the tokio runtime) to avoid blocking /// the async executor. Communicates clipboard change events to the tokio world @@ -59,9 +59,9 @@ impl MonitorState { self.offers.entry(id).or_default().push(mime); } - fn commit_selection(&mut self, offer_id: ObjectId) { + fn commit_selection(&mut self, offer_id: &ObjectId) { // Take the mime list for this offer (and discard stale in-flight offers). - let mimes = self.offers.remove(&offer_id).unwrap_or_default(); + let mimes = self.offers.remove(offer_id).unwrap_or_default(); self.offers.clear(); // discard any superseded offers if !mimes.is_empty() { let _ = self.tx.send(ClipboardChange { mime_types: mimes }); @@ -119,7 +119,7 @@ impl Dispatch for MonitorState { } ext_data_control_device_v1::Event::Selection { id: Some(offer) } => { let oid = offer.id(); - state.commit_selection(oid); + state.commit_selection(&oid); // Politely destroy the offer - the compositor will clean up // the Wayland object. offer.destroy(); @@ -183,7 +183,7 @@ impl Dispatch for MonitorState { } zwlr_data_control_device_v1::Event::Selection { id: Some(offer) } => { let oid = offer.id(); - state.commit_selection(oid); + state.commit_selection(&oid); offer.destroy(); } zwlr_data_control_device_v1::Event::Selection { id: None } => { @@ -233,7 +233,7 @@ pub fn spawn(tx: UnboundedSender) -> Result<()> { std::thread::Builder::new() .name("strata-wl-monitor".into()) .spawn(move || { - if let Err(e) = run_loop(conn, protocol, tx) { + if let Err(e) = run_loop(&conn, protocol, tx) { tracing::error!("Clipboard monitor exited with error: {e:#}"); } })?; @@ -278,11 +278,11 @@ fn probe_protocol(conn: &Connection) -> Result { } fn run_loop( - conn: Connection, + conn: &Connection, protocol: Protocol, tx: UnboundedSender, ) -> Result<()> { - let (globals, mut queue) = registry_queue_init::(&conn)?; + let (globals, mut queue) = registry_queue_init::(conn)?; let qh = queue.handle(); let mut state = MonitorState::new(tx); diff --git a/strata-daemon/src/clipboard/writer.rs b/strata-daemon/src/clipboard/writer.rs index 5f4ff5a..60972ad 100644 --- a/strata-daemon/src/clipboard/writer.rs +++ b/strata-daemon/src/clipboard/writer.rs @@ -22,7 +22,7 @@ pub fn write_to_clipboard(req: WriteRequest) -> Result<()> { vec![ MimeSource { source: Source::Bytes(bytes.clone().into()), - mime_type: MimeType::Specific(mime.clone()), + mime_type: MimeType::Specific(mime), }, MimeSource { source: Source::Bytes(bytes.into()), diff --git a/strata-daemon/src/db.rs b/strata-daemon/src/db.rs index 19ffef5..550d1f6 100644 --- a/strata-daemon/src/db.rs +++ b/strata-daemon/src/db.rs @@ -1,5 +1,11 @@ +// SQLite is single-writer, and `lock_conn`'s guard is intentionally held for +// each function's whole body -- the upsert's SELECT-then-INSERT must be atomic +// under one lock. `significant_drop_tightening` would have us drop the guard +// earlier, which would break that guarantee, so it is allowed for this module. +#![allow(clippy::significant_drop_tightening)] + use anyhow::{Context, Result}; -use rusqlite::{params, Connection}; +use rusqlite::{params, Connection, OptionalExtension}; use serde::{Deserialize, Serialize}; use std::path::Path; use std::sync::{Mutex, MutexGuard}; @@ -21,11 +27,11 @@ pub struct ItemMeta { pub content_text: Option, pub source_app: Option, pub created_at: i64, - /// True if this item has a stored thumbnail (clients should call get_thumbnail to fetch it). + /// True if this item has a stored thumbnail (clients should call `get_thumbnail` to fetch it). pub has_thumbnail: bool, } -/// A row as stored in SQLite (blob is raw bytes, not base64). +/// A row as stored in `SQLite` (blob is raw bytes, not base64). #[allow(dead_code)] pub struct RawItem { pub id: String, @@ -43,12 +49,12 @@ pub struct Db { /// Acquire the DB lock, transparently recovering from poison. /// -/// A mutex is "poisoned" when a thread panics while holding it. For our SQLite +/// A mutex is "poisoned" when a thread panics while holding it. For our `SQLite` /// connection this is safe to recover from because rusqlite uses RAII statements /// and transactions - any in-flight statement or transaction has already been /// rolled back by the time the panic unwinds past it. Without this recovery, /// a single panic anywhere in the daemon would permanently break ALL future -/// database access (every subsequent .lock().unwrap() would panic too). +/// database access (every subsequent .`lock().unwrap()` would panic too). fn lock_conn(m: &Mutex) -> MutexGuard<'_, Connection> { match m.lock() { Ok(g) => g, @@ -62,7 +68,7 @@ fn lock_conn(m: &Mutex) -> MutexGuard<'_, Connection> { impl Db { pub fn open(path: &Path) -> Result { let conn = Connection::open(path) - .with_context(|| format!("Opening SQLite database at {:?}", path))?; + .with_context(|| format!("Opening SQLite database at {}", path.display()))?; // Performance pragmas: WAL mode for concurrent reads, synchronous=NORMAL is safe // for a clipboard history (we can tolerate losing the last item on a crash). @@ -140,14 +146,18 @@ impl Db { let conn = lock_conn(&self.conn); let now_ms = chrono_now_ms(); - // Check for existing item with this hash. + // Check for existing item with this hash. optional() maps "no match" to + // None; a real read error propagates instead of being swallowed (which + // would make a duplicate look new and then fail the INSERT on the UNIQUE + // index with a confusing error). let existing: Option = conn .query_row( "SELECT id FROM clipboard_history WHERE content_hash = ?1", params![content_hash], |row| row.get(0), ) - .ok(); + .optional() + .context("Checking for existing item")?; if let Some(id) = existing { conn.execute( @@ -206,9 +216,9 @@ impl Db { Ok(items) } - /// Full-text search over content_text. Only text items can match - images + /// Full-text search over `content_text`. Only text items can match - images /// and other non-text content are NOT indexed and never appear in results. - /// Empty query returns []; callers should use get_history_page for that. + /// Empty query returns []; callers should use `get_history_page` for that. pub fn search_history(&self, query: &str, limit: usize) -> Result> { let conn = lock_conn(&self.conn); @@ -219,7 +229,7 @@ impl Db { .map(|t| { // Escape embedded double-quotes by doubling them per FTS5 syntax. let escaped = t.replace('"', "\"\""); - format!("\"{}\"*", escaped) + format!("\"{escaped}\"*") }) .collect(); @@ -258,39 +268,43 @@ impl Db { /// (text item, or doesn't exist). pub fn get_thumbnail(&self, id: &str) -> Result>> { let conn = lock_conn(&self.conn); - let blob: Option>> = conn + // thumbnail_blob is itself nullable, so the row yields Option>. + // optional() maps a missing row to Ok(None); real errors propagate. + let blob = conn .query_row( "SELECT thumbnail_blob FROM clipboard_history WHERE id = ?1", params![id], - |row| row.get(0), + |row| row.get::<_, Option>>(0), ) - .ok(); + .optional() + .context("Fetching thumbnail")?; Ok(blob.flatten()) } /// Fetch raw item content for clipboard write-back. Does not load - /// thumbnail_blob -- callers only need the original payload. + /// `thumbnail_blob` -- callers only need the original payload. pub fn get_raw_item(&self, id: &str) -> Result> { let conn = lock_conn(&self.conn); - let result = conn - .query_row( - "SELECT id, mime_type, content_text, content_blob, source_app, created_at + // optional() maps a missing row to Ok(None); real errors propagate + // instead of being silently swallowed as "not found". + conn.query_row( + "SELECT id, mime_type, content_text, content_blob, source_app, created_at FROM clipboard_history WHERE id = ?1", - params![id], - |row| { - Ok(RawItem { - id: row.get(0)?, - mime_type: row.get(1)?, - content_text: row.get(2)?, - content_blob: row.get(3)?, - thumbnail_blob: None, - source_app: row.get(4)?, - created_at: row.get(5)?, - }) - }, - ) - .ok(); - Ok(result) + params![id], + |row| { + Ok(RawItem { + id: row.get(0)?, + mime_type: row.get(1)?, + content_text: row.get(2)?, + content_blob: row.get(3)?, + thumbnail_blob: None, + source_app: row.get(4)?, + created_at: row.get(5)?, + }) + }, + ) + .optional() + .context("Fetching clipboard item") } pub fn delete_item(&self, id: &str) -> Result { @@ -306,7 +320,7 @@ impl Db { } /// Prune history to `max_history` most recent items. Returns the IDs of - /// items that were deleted, so the caller can emit ItemDeleted signals + /// items that were deleted, so the caller can emit `ItemDeleted` signals /// (lets clients clean up per-item caches like thumbnail files). pub fn prune(&self, max_history: usize) -> Result> { let conn = lock_conn(&self.conn); @@ -331,10 +345,7 @@ impl Db { } // Delete by collected IDs so the ORDER BY subquery runs only once. let placeholders = ids.iter().map(|_| "?").collect::>().join(", "); - let sql = format!( - "DELETE FROM clipboard_history WHERE id IN ({})", - placeholders - ); + let sql = format!("DELETE FROM clipboard_history WHERE id IN ({placeholders})"); conn.execute(&sql, rusqlite::params_from_iter(ids.iter()))?; Ok(ids) } diff --git a/strata-daemon/src/dbus_service.rs b/strata-daemon/src/dbus_service.rs index 68d3553..3ad2d13 100644 --- a/strata-daemon/src/dbus_service.rs +++ b/strata-daemon/src/dbus_service.rs @@ -1,22 +1,22 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; -use zbus::{interface, object_server::SignalContext}; +use zbus::{interface, object_server::SignalEmitter}; use crate::db::{Db, RawItem}; /// Maximum thumbnail dimension for images (px). Larger images are resized down. pub const THUMB_PX: u32 = 200; -/// Default maximum raw image size to accept (bytes). Overridable via SetConfig. +/// Default maximum raw image size to accept (bytes). Overridable via `SetConfig`. pub const DEFAULT_MAX_IMAGE_BYTES: usize = 5 * 1024 * 1024; -/// Default maximum text size to accept. Overridable via SetConfig. +/// Default maximum text size to accept. Overridable via `SetConfig`. pub const DEFAULT_MAX_TEXT_BYTES: usize = 1024 * 1024; -/// Default maximum history item count. Overridable via SetConfig. +/// Default maximum history item count. Overridable via `SetConfig`. pub const DEFAULT_MAX_HISTORY: usize = 200; /// Runtime-configurable limits shared between the D-Bus service and the /// clipboard processing tasks. All three are read on every ingest / prune -/// call, so updates via SetConfig take effect immediately. +/// call, so updates via `SetConfig` take effect immediately. #[derive(Clone)] pub struct Limits { pub max_history: Arc, @@ -67,6 +67,8 @@ impl StrataManager { /// hint is not forwarded, so this method cannot re-check it. Treat callers of /// `SubmitItem` as trusted (the session bus is per-user). Forwarding the /// sensitivity flag to enforce it here is left for a future contract change. + // async is required by the zbus #[interface] method signature, not by the body. + #[allow(clippy::unused_async)] async fn submit_item(&self, mime_type: String, content: Vec) -> zbus::fdo::Result<()> { self.submit_tx .send(SubmitRequest { @@ -76,8 +78,8 @@ impl StrataManager { .map_err(|e| zbus::fdo::Error::Failed(e.to_string())) } /// Return a page of recent items as JSON metadata (no inline thumbnail bytes, - /// content_text truncated to a preview). Clients call GetThumbnail(id) lazily - /// for items with has_thumbnail=true and GetItemContent(id) for full content. + /// `content_text` truncated to a preview). Clients call GetThumbnail(id) lazily + /// for items with `has_thumbnail=true` and GetItemContent(id) for full content. /// `offset` is from the most recent item (0 = newest). async fn get_history(&self, offset: u32, limit: u32) -> zbus::fdo::Result { let db = self.db.clone(); @@ -93,7 +95,7 @@ impl StrataManager { } /// Full-text search across the entire DB. Empty query returns []; callers - /// should fall back to GetHistory in that case. + /// should fall back to `GetHistory` in that case. async fn search_history(&self, query: String, limit: u32) -> zbus::fdo::Result { let db = self.db.clone(); let items = tokio::task::spawn_blocking(move || db.search_history(&query, limit as usize)) @@ -173,7 +175,7 @@ impl StrataManager { async fn delete_item( &self, id: String, - #[zbus(signal_context)] ctx: SignalContext<'_>, + #[zbus(signal_context)] ctx: SignalEmitter<'_>, ) -> zbus::fdo::Result<()> { let db = self.db.clone(); let id_clone = id.clone(); @@ -190,7 +192,7 @@ impl StrataManager { /// Remove all items from history. async fn clear_history( &self, - #[zbus(signal_context)] ctx: SignalContext<'_>, + #[zbus(signal_context)] ctx: SignalEmitter<'_>, ) -> zbus::fdo::Result<()> { let db = self.db.clone(); tokio::task::spawn_blocking(move || db.clear_history()) @@ -204,14 +206,14 @@ impl StrataManager { } /// Push runtime limits from the front-end. Takes effect immediately. - /// All three values are absolute (max_text and max_image are bytes, + /// All three values are absolute (`max_text` and `max_image` are bytes, /// not MB). 0 means "leave unchanged" for that field. async fn set_config( &self, max_history: u32, max_text_bytes: u32, max_image_bytes: u32, - #[zbus(signal_context)] ctx: SignalContext<'_>, + #[zbus(signal_context)] ctx: SignalEmitter<'_>, ) -> zbus::fdo::Result<()> { use std::sync::atomic::Ordering; if max_history > 0 { @@ -256,6 +258,8 @@ impl StrataManager { } /// Gracefully shut down the daemon. + // async is required by the zbus #[interface] method signature, not by the body. + #[allow(clippy::unused_async)] async fn shutdown(&self) { tracing::info!("Shutdown requested via D-Bus"); // Signal the main loop to exit. The reply is sent before the process exits @@ -268,12 +272,12 @@ impl StrataManager { // ----------------------------------------------------------------- /// Emitted when a new item is stored (after dedup + thumbnail generation). - /// `preview` is a text excerpt (≤ PREVIEW_CHARS) for text items, or empty for + /// `preview` is a text excerpt (≤ `PREVIEW_CHARS`) for text items, or empty for /// images and other binary types - clients should call GetThumbnail(id) to /// fetch image thumbnails lazily. #[zbus(signal)] pub async fn item_added( - ctx: &SignalContext<'_>, + ctx: &SignalEmitter<'_>, id: &str, mime_type: &str, preview: &str, @@ -281,9 +285,9 @@ impl StrataManager { /// Emitted when an item is removed. #[zbus(signal)] - pub async fn item_deleted(ctx: &SignalContext<'_>, id: &str) -> zbus::Result<()>; + pub async fn item_deleted(ctx: &SignalEmitter<'_>, id: &str) -> zbus::Result<()>; /// Emitted when the entire history is cleared. #[zbus(signal)] - pub async fn history_cleared(ctx: &SignalContext<'_>) -> zbus::Result<()>; + pub async fn history_cleared(ctx: &SignalEmitter<'_>) -> zbus::Result<()>; } diff --git a/strata-daemon/src/main.rs b/strata-daemon/src/main.rs index 07fa32b..a38b80f 100644 --- a/strata-daemon/src/main.rs +++ b/strata-daemon/src/main.rs @@ -54,19 +54,21 @@ async fn main() -> Result<()> { .await .context("Building D-Bus connection")?; - // Request the well-known name with ReplaceExisting (try to take it from any - // outgoing instance) AND AllowReplacement (let the next instance take it - // from us). Both are needed for a clean hand-off on extension reload: without - // AllowReplacement on the running instance, a new instance's ReplaceExisting - // would be refused. + // Single-instance daemon: request the name with DoNotQueue. The extension + // spawns exactly one daemon and skips spawning if the name is already owned, + // so if the name IS taken here, another instance is already serving - the + // request returns an error (rather than silently queuing, which would leave + // us running without owning the name while clients talk to the other one) + // and we exit. We deliberately do NOT use ReplaceExisting: stealing the name + // would orphan the running instance (zbus does not terminate a replaced + // owner), so we let the existing one keep it and bow out. dbus_conn .request_name_with_flags( "dev.edu4rdshl.Strata", - zbus::fdo::RequestNameFlags::ReplaceExisting - | zbus::fdo::RequestNameFlags::AllowReplacement, + zbus::fdo::RequestNameFlags::DoNotQueue.into(), ) .await - .context("Acquiring D-Bus name dev.edu4rdshl.Strata")?; + .context("Acquiring D-Bus name dev.edu4rdshl.Strata (is another instance running?)")?; tracing::info!("D-Bus service registered as dev.edu4rdshl.Strata"); @@ -76,11 +78,12 @@ async fn main() -> Result<()> { // so this fails to bind there and the extension feeds content via SubmitItem // instead. On wlroots compositors (Sway, Hyprland) the monitor is the path. // ----------------------------------------------------------------------- - match clipboard::monitor::spawn(clip_tx) { - Ok(()) => tracing::info!("Wayland clipboard monitor started"), - Err(_) => tracing::info!( + if clipboard::monitor::spawn(clip_tx).is_ok() { + tracing::info!("Wayland clipboard monitor started"); + } else { + tracing::info!( "Wayland clipboard monitor unavailable, using GJS Meta.Selection path (expected on GNOME)" - ), + ); } // ----------------------------------------------------------------------- @@ -198,12 +201,11 @@ async fn process_change( tracing::debug!("Skipping clipboard change marked as sensitive"); return Ok(()); } - let mime = match pick_mime(mime_types) { - Some(m) => m.to_string(), - None => { - tracing::debug!("No usable MIME type in {:?}", mime_types); - return Ok(()); - } + let mime = if let Some(m) = pick_mime(mime_types) { + m.to_string() + } else { + tracing::debug!("No usable MIME type in {:?}", mime_types); + return Ok(()); }; tracing::debug!("Processing Wayland clipboard change, MIME: {}", mime); @@ -316,12 +318,12 @@ async fn process_bytes( .await .context("Getting StrataManager interface ref")?; - StrataManager::item_added(iface.signal_context(), &id, &mime, &preview) + StrataManager::item_added(iface.signal_emitter(), &id, &mime, &preview) .await .context("Emitting ItemAdded signal")?; for pid in &pruned_ids { - if let Err(e) = StrataManager::item_deleted(iface.signal_context(), pid).await { + if let Err(e) = StrataManager::item_deleted(iface.signal_emitter(), pid).await { tracing::warn!("Emitting ItemDeleted for pruned id={}: {}", pid, e); } }