diff --git a/Cargo.lock b/Cargo.lock index fd698b1..e886fa9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,8 +305,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" dependencies = [ - "async-fs", - "async-net", "enumflags2", "futures-channel", "futures-util", @@ -332,6 +330,9 @@ dependencies = [ "serde_repr", "tokio", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", "zbus 4.4.0", ] @@ -452,17 +453,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-net" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" -dependencies = [ - "async-io 2.4.0", - "blocking", - "futures-lite 2.6.0", -] - [[package]] name = "async-process" version = "1.8.1" @@ -681,12 +671,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" version = "1.3.2" @@ -777,6 +761,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.10.0" @@ -811,9 +801,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.12" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" dependencies = [ "jobserver", "libc", @@ -870,7 +860,7 @@ dependencies = [ [[package]] name = "clipboard_macos" version = "0.1.0" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "objc", "objc-foundation", @@ -880,7 +870,7 @@ dependencies = [ [[package]] name = "clipboard_wayland" version = "0.2.2" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "dnd", "mime 0.1.0", @@ -890,7 +880,7 @@ dependencies = [ [[package]] name = "clipboard_x11" version = "0.4.2" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "thiserror 1.0.69", "x11rb", @@ -1004,26 +994,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "tiny-keccak", -] - [[package]] name = "constcat" version = "0.5.1" @@ -1070,21 +1040,33 @@ dependencies = [ "libc", ] +[[package]] +name = "cosmic-client-toolkit" +version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=29ab323#29ab32305c6457fccf0728caaaf79fcac4cca665" +dependencies = [ + "cosmic-protocols", + "libc", + "smithay-client-toolkit", + "wayland-client", + "wayland-protocols", +] + [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "atomicwrites", "cosmic-config-derive", "cosmic-settings-daemon", - "dirs", + "dirs 5.0.1", "futures-util", "iced_futures", "known-folders", "notify", "once_cell", - "ron", + "ron 0.9.0-alpha.1", "serde", "tokio", "tracing", @@ -1095,12 +1077,39 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "quote", "syn 1.0.109", ] +[[package]] +name = "cosmic-freedesktop-icons" +version = "0.3.0" +source = "git+https://github.com/pop-os/freedesktop-icons#98f78d49022c893be2e974e95d95aaea963a6833" +dependencies = [ + "dirs 5.0.1", + "ini_core", + "once_cell", + "thiserror 1.0.69", + "tracing", + "xdg", +] + +[[package]] +name = "cosmic-protocols" +version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=29ab323#29ab32305c6457fccf0728caaaf79fcac4cca665" +dependencies = [ + "bitflags 2.8.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "wayland-server", +] + [[package]] name = "cosmic-settings-daemon" version = "0.1.0" @@ -1134,15 +1143,15 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "almost", "cosmic-config", "csscolorparser", - "dirs", + "dirs 5.0.1", "lazy_static", "palette", - "ron", + "ron 0.9.0-alpha.1", "serde", "serde_json", "thiserror 1.0.69", @@ -1156,7 +1165,7 @@ dependencies = [ "chrono", "constcat", "directories", - "env_logger", + "env_logger 0.11.6", "futures", "futures-util", "i18n-embed", @@ -1167,6 +1176,7 @@ dependencies = [ "once_cell", "open", "paste", + "pretty_env_logger", "reqwest", "rust-embed", "serde", @@ -1218,25 +1228,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -1423,7 +1414,16 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys 0.3.7", ] [[package]] @@ -1432,7 +1432,18 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] @@ -1473,19 +1484,10 @@ dependencies = [ "libloading", ] -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - [[package]] name = "dnd" version = "0.1.0" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "bitflags 2.8.0", "mime 0.1.0", @@ -1614,6 +1616,19 @@ dependencies = [ "regex", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.11.6" @@ -1717,21 +1732,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "exr" -version = "1.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - [[package]] name = "fast-srgb8" version = "1.0.0" @@ -1970,24 +1970,14 @@ dependencies = [ ] [[package]] -name = "fraction" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" -dependencies = [ - "lazy_static", - "num", -] - -[[package]] -name = "freedesktop-icons" -version = "0.2.6" +name = "freedesktop-desktop-entry" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8ef34245e0540c9a3ce7a28340b98d2c12b75da0d446da4e8224923fcaa0c16" +checksum = "c201444ddafb5506fe85265b48421664ff4617e3b7090ef99e42a0070c1aead0" dependencies = [ - "dirs", - "once_cell", - "rust-ini", + "dirs 3.0.2", + "gettext-rs", + "memchr", "thiserror 1.0.69", "xdg", ] @@ -2173,6 +2163,26 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "gettext-rs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44e92f7dc08430aca7ed55de161253a22276dfd69c5526e5c5e95d1f7cf338a" +dependencies = [ + "gettext-sys", + "locale_config", +] + +[[package]] +name = "gettext-sys" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb45773f5b8945f12aecd04558f545964f943dacda1b1155b3d738f5469ef661" +dependencies = [ + "cc", + "temp-dir", +] + [[package]] name = "gif" version = "0.13.1" @@ -2640,7 +2650,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "dnd", "iced_accessibility", @@ -2658,7 +2668,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "accesskit", "accesskit_winit", @@ -2667,10 +2677,11 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "bitflags 2.8.0", "bytes", + "cosmic-client-toolkit", "dnd", "glam", "iced_accessibility", @@ -2691,7 +2702,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "futures", "iced_core", @@ -2717,7 +2728,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "bitflags 2.8.0", "bytemuck", @@ -2739,7 +2750,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2751,9 +2762,10 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "bytes", + "cosmic-client-toolkit", "dnd", "iced_accessibility", "iced_core", @@ -2766,7 +2778,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "bytemuck", "cosmic-text", @@ -2782,11 +2794,12 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "as-raw-xcb-connection", "bitflags 2.8.0", "bytemuck", + "cosmic-client-toolkit", "futures", "glam", "guillotiere", @@ -2799,7 +2812,6 @@ dependencies = [ "resvg", "rustc-hash 2.1.1", "rustix 0.38.44", - "smithay-client-toolkit", "thiserror 1.0.69", "tiny-xlib", "wayland-backend", @@ -2813,8 +2825,9 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ + "cosmic-client-toolkit", "dnd", "iced_accessibility", "iced_renderer", @@ -2831,22 +2844,31 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ + "cosmic-client-toolkit", "dnd", "iced_accessibility", "iced_futures", "iced_graphics", "iced_runtime", "log", + "raw-window-handle", "rustc-hash 2.1.1", + "rustix 0.38.44", "thiserror 1.0.69", "tracing", "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", "web-sys", "winapi", "window_clipboard", "winit", + "xkbcommon", + "xkbcommon-dl", + "xkeysym", ] [[package]] @@ -2996,20 +3018,16 @@ dependencies = [ [[package]] name = "image" -version = "0.24.9" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", + "byteorder-lite", "num-traits", "png", - "qoi", - "tiff", + "zune-core", + "zune-jpeg", ] [[package]] @@ -3056,6 +3074,15 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "ini_core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a467a31a9f439b5262fa99c17084537bff57f24703d5a09a2b5c9657ec73a61" +dependencies = [ + "cfg-if", +] + [[package]] name = "inotify" version = "0.9.6" @@ -3130,6 +3157,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is-terminal" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "is-wsl" version = "0.4.0" @@ -3188,9 +3226,6 @@ name = "jpeg-decoder" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] [[package]] name = "js-sys" @@ -3286,12 +3321,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "libc" version = "0.2.169" @@ -3301,18 +3330,19 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic?rev=953685a88267894ea3fa40f2b99139c3c4e784d6#953685a88267894ea3fa40f2b99139c3c4e784d6" +source = "git+https://github.com/pop-os/libcosmic#9426a985c62288e996827a3560770c19271b337a" dependencies = [ "apply", "ashpd 0.9.2", "chrono", + "cosmic-client-toolkit", "cosmic-config", + "cosmic-freedesktop-icons", "cosmic-settings-daemon", "cosmic-theme", "css-color", "derive_setters", - "fraction", - "freedesktop-icons", + "freedesktop-desktop-entry", "iced", "iced_accessibility", "iced_core", @@ -3323,11 +3353,17 @@ dependencies = [ "iced_wgpu", "iced_widget", "iced_winit", + "image", "lazy_static", + "libc", + "license", + "mime 0.3.17", "palette", "rfd", - "ron", + "ron 0.8.1", + "rustix 0.38.44", "serde", + "shlex", "slotmap", "taffy", "thiserror 1.0.69", @@ -3335,7 +3371,6 @@ dependencies = [ "tracing", "unicode-segmentation", "url", - "ustr", "zbus 4.4.0", ] @@ -3377,6 +3412,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "license" +version = "3.6.0+3.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b517725daf998729e5ef4c4881cdde19cd5bbdde09741ba1b0f1ba0ce018961" +dependencies = [ + "reword", + "serde", + "serde_json", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3573,7 +3619,7 @@ dependencies = [ [[package]] name = "mime" version = "0.1.0" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "smithay-clipboard", ] @@ -3744,30 +3790,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -3785,15 +3807,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -3820,17 +3833,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -4198,16 +4200,6 @@ dependencies = [ "libredox", ] -[[package]] -name = "ordered-multimap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - [[package]] name = "ordered-stream" version = "0.2.0" @@ -4546,6 +4538,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger 0.10.2", + "log", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -4615,15 +4617,6 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - [[package]] name = "quick-xml" version = "0.37.2" @@ -4690,26 +4683,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "read-fonts" version = "0.25.3" @@ -4853,6 +4826,15 @@ dependencies = [ "usvg", ] +[[package]] +name = "reword" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe272098dce9ed76b479995953f748d1851261390b08f8a0ff619c885a1f0765" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "rfd" version = "0.14.1" @@ -4912,6 +4894,19 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "ron" +version = "0.9.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7644a2a539ff7fa991c8f4652373cd722d387e39229415103243914249730836" +dependencies = [ + "base64 0.22.1", + "bitflags 2.8.0", + "serde", + "serde_derive", + "unicode-ident", +] + [[package]] name = "roxmltree" version = "0.20.0" @@ -4972,16 +4967,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "rust-ini" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -5808,6 +5793,12 @@ dependencies = [ "slotmap", ] +[[package]] +name = "temp-dir" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" + [[package]] name = "tempfile" version = "3.16.0" @@ -5871,17 +5862,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "time" version = "0.3.37" @@ -5915,15 +5895,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tiny-skia" version = "0.11.4" @@ -6326,19 +6297,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "ustr" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208" -dependencies = [ - "ahash", - "byteorder", - "lazy_static", - "parking_lot 0.12.3", - "serde", -] - [[package]] name = "usvg" version = "0.42.0" @@ -6598,6 +6556,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-scanner", + "wayland-server", ] [[package]] @@ -6624,6 +6583,7 @@ dependencies = [ "wayland-client", "wayland-protocols", "wayland-scanner", + "wayland-server", ] [[package]] @@ -6637,6 +6597,19 @@ dependencies = [ "quote", ] +[[package]] +name = "wayland-server" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fabd7ed68cff8e7657b8a8a1fbe90cb4a3f0c30d90da4bf179a7a23008a4cb" +dependencies = [ + "bitflags 2.8.0", + "downcast-rs", + "rustix 0.38.44", + "wayland-backend", + "wayland-scanner", +] + [[package]] name = "wayland-sys" version = "0.31.6" @@ -6831,7 +6804,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window_clipboard" version = "0.4.1" -source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13-2#6b9faab87bea9cebec6ae036906fd67fed254f5f" dependencies = [ "clipboard-win", "clipboard_macos", @@ -7585,12 +7558,18 @@ dependencies = [ ] [[package]] -name = "zune-inflate" -version = "0.2.54" +name = "zune-core" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" dependencies = [ - "simd-adler32", + "zune-core", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 699d2e5..5b16c53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4.22" once_cell = "1.19.0" open = "5.3.0" paste = "1.0.15" +pretty_env_logger = "0.5.0" reqwest = { version = "0.12.8", features = ["json"] } rust-embed = "8.5.0" serde = "1.0.210" @@ -28,23 +29,52 @@ tokio = { version = "1.40.0", features = ["full"] } version = "0.15" features = ["fluent-system", "desktop-requester"] -[dependencies.libcosmic] +[target.'cfg(target_os="macos")'.dependencies.libcosmic] git = "https://github.com/pop-os/libcosmic" default-features = false -# features = ["dbus-config", "tokio", "winit", "wgpu"] features = [ + # Native cosmic about drawer + "about", + # Accessibility support "a11y", + # Uses cosmic-settings-daemon to watch for config file changes "dbus-config", - # NOTE: (vkhitrin) this is a temporary workaround to set initial - # application title. + # Support creating additional application windows. "multi-window", + # On app startup, focuses an existing instance if the app is already open "single-instance", + # Uses tokio as the executor for the runtime "tokio", + # Windowing support for X11, Windows, Mac, & Redox "winit", + # GPU-accelerated rendering + "wgpu", +] +process = [] + +[target.'cfg(target_os="linux")'.dependencies.libcosmic] +git = "https://github.com/pop-os/libcosmic" +default-features = false +features = [ + # Native cosmic about drawer + "about", + # Accessibility support + "a11y", + # Uses cosmic-settings-daemon to watch for config file changes + "dbus-config", + # Support creating additional application windows. + "multi-window", + # On app startup, focuses an existing instance if the app is already open + "single-instance", + # Uses tokio as the executor for the runtime + "tokio", + # Windowing support for X11, Windows, Mac, & Redox + "winit", + # Add Wayland support to winit + "wayland", + # GPU-accelerated rendering "wgpu", ] -rev = "953685a88267894ea3fa40f2b99139c3c4e784d6" -version = "0.1.0" [build-dependencies] vergen = { version = "8", features = ["git", "gitcl"] } diff --git a/README.md b/README.md index 178a0a7..ad9aaf3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ cosmicding is a [linkding](https://github.com/sissbruecker/linkding) companion app for COSMIC™ Desktop Environment. It provides an alternative frontend to linkding based on [libcosmic](https://github.com/pop-os/libcosmic). -While cosmicding was designed for COSMIC™ Desktop Environment, it may "run" cross-platform (#24). +While cosmicding was designed for COSMIC™ Desktop Environment, it may "run" cross-platform ([#24](https://github.com/vkhitrin/cosmicding/issues/24)). Features: @@ -25,6 +25,9 @@ cosmicding was tested against linkding releases `1.31.0`, and `1.36.0`. ## Installation +> [!WARNING] +> macOS build are currently broken, `about` feature of `libcosmic` uses a dependency which is broken on macOS. + > [!NOTE] > Currently cosmicding is hard-codded to build Apple Silicon releases for macOS. diff --git a/res/screenshots/accounts.png b/res/screenshots/accounts.png index c8d248a..64bd907 100644 Binary files a/res/screenshots/accounts.png and b/res/screenshots/accounts.png differ diff --git a/res/screenshots/bookmarks.png b/res/screenshots/bookmarks.png index ff13059..993139b 100644 Binary files a/res/screenshots/bookmarks.png and b/res/screenshots/bookmarks.png differ diff --git a/src/app.rs b/src/app.rs index 7eb1f20..61b5b7b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,33 +1,43 @@ -use crate::config::{AppTheme, Config, SortOption, CONFIG_VERSION}; +use crate::app::{ + config::{AppTheme, CosmicConfig, SortOption}, + icons::load_icon, + menu as app_menu, + nav::AppNavPage, +}; use crate::db::{self}; use crate::fl; use crate::http::{self}; -use crate::key_binds::key_binds; use crate::models::account::{Account, LinkdingAccountApiResponse}; use crate::models::bookmarks::{Bookmark, DetailedResponse}; use crate::models::db_cursor::{AccountsPaginationCursor, BookmarksPaginationCursor, Pagination}; -use crate::nav::AppNavPage; use crate::pages::accounts::{add_account, edit_account, AppAccountsMessage, PageAccountsView}; use crate::pages::bookmarks::{ edit_bookmark, new_bookmark, view_notes, AppBookmarksMessage, PageBookmarksView, }; -use crate::utils::icons::load_icon; -use cosmic::app::{Core, Task}; -use cosmic::cosmic_config::{self, CosmicConfigEntry, Update}; +use cosmic::app::{context_drawer, Core, Task}; +use cosmic::cosmic_config::{self, Update}; use cosmic::cosmic_theme::{self, ThemeMode}; use cosmic::iced::{ event, futures::executor::block_on, - keyboard::{Event as KeyEvent, Key, Modifiers}, - Alignment, Event, Length, Subscription, + keyboard::Event as KeyEvent, + keyboard::{Key, Modifiers}, + Event, Length, Subscription, }; -use cosmic::widget::menu::action::MenuAction as _MenuAction; -use cosmic::widget::{self, icon, menu, nav_bar}; -use cosmic::{theme, Application, ApplicationExt, Element}; +use cosmic::widget::menu::{action::MenuAction as _MenuAction, key_bind::KeyBind}; +use cosmic::widget::{self, about::About, icon, nav_bar}; +use cosmic::{Application, ApplicationExt, Element}; +use key_bind::key_binds; use std::any::TypeId; use std::collections::{HashMap, VecDeque}; use std::time::Duration; +pub mod config; +pub mod icons; +mod key_bind; +pub mod menu; +pub mod nav; + pub const QUALIFIER: &str = "com"; pub const ORG: &str = "vkhitrin"; pub const APP: &str = "cosmicding"; @@ -35,19 +45,19 @@ pub const APPID: &str = constcat::concat!(QUALIFIER, ".", ORG, ".", APP); const REPOSITORY: &str = "https://github.com/vkhitrin/cosmicding"; -#[derive(Clone, Debug)] pub struct Flags { pub config_handler: Option, - pub config: Config, + pub config: CosmicConfig, } pub struct Cosmicding { core: Core, + about: About, context_page: ContextPage, nav: nav_bar::Model, dialog_pages: VecDeque, - key_binds: HashMap, - pub config: Config, + key_binds: HashMap, + pub config: CosmicConfig, config_handler: Option, modifiers: Modifiers, app_themes: Vec, @@ -91,9 +101,9 @@ pub enum Message { Modifiers(Modifiers), OpenAccountsPage, OpenExternalUrl(String), - OpenRemoveAccountDialog(i64), + OpenRemoveAccountDialog(Account), OpenRemoveBookmarkDialog(i64, Bookmark), - RemoveAccount(i64), + RemoveAccount(Account), RemoveBookmark(i64, Bookmark), SearchBookmarks(String), SetAccountAPIKey(String), @@ -116,9 +126,10 @@ pub enum Message { StartupCompleted, SystemThemeModeChange, ToggleContextPage(ContextPage), + ContextClose, UpdateAccount(Account), UpdateBookmark(Account, Bookmark), - UpdateConfig(Config), + UpdateConfig(CosmicConfig), ViewBookmarkNotes(Bookmark), } @@ -126,7 +137,7 @@ pub enum Message { #[derive(Clone, Debug, Eq, PartialEq)] #[allow(clippy::large_enum_variant)] pub enum DialogPage { - RemoveAccount(i64), + RemoveAccount(Account), RemoveBookmark(i64, Bookmark), } @@ -163,6 +174,30 @@ impl Application for Cosmicding { let mut nav = nav_bar::Model::default(); let app_themes = vec![fl!("match-desktop"), fl!("dark"), fl!("light")]; + let release = env!("CARGO_PKG_VERSION"); + let hash = env!("VERGEN_GIT_SHA"); + let short_hash: String = hash.chars().take(7).collect(); + let date = env!("VERGEN_GIT_COMMIT_DATE"); + + let about = About::default() + .name(fl!("cosmicding")) + .icon(Self::APP_ID) + .version(release) + .comments(fl!( + "git-description", + hash = short_hash.as_str(), + date = date + )) + .license("GPL-3.0") + .author("Vadim Khitrin") + .links([ + ("Repository", REPOSITORY), + ("Support", &format!("{REPOSITORY}/issues")), + ("Linkding Official Site", "https://linkding.link"), + ]) + .translators([("Luna Jernberg", "lunajernberg@gnome.org")]) + .developers([("Vadim Khitrin", "me@vkhitrin.com")]); + for &nav_page in AppNavPage::all() { let id = nav .insert() @@ -178,15 +213,11 @@ impl Application for Cosmicding { let mut app = Cosmicding { core, + about, context_page: ContextPage::default(), nav, key_binds: key_binds(), - config: cosmic_config::Config::new(Self::APP_ID, Config::VERSION) - .map(|context| match Config::get_entry(&context) { - Ok(config) => config, - Err((_errors, config)) => config, - }) - .unwrap_or_default(), + config: flags.config, config_handler: flags.config_handler, modifiers: Modifiers::empty(), app_themes, @@ -220,7 +251,7 @@ impl Application for Cosmicding { } fn header_start(&self) -> Vec> { - vec![crate::menu::menu_bar( + vec![app_menu::menu_bar( &self.key_binds, !self.accounts_view.accounts.is_empty(), !self.bookmarks_view.bookmarks.is_empty(), @@ -243,59 +274,89 @@ impl Application for Cosmicding { Task::none() } - fn context_drawer(&self) -> Option> { + fn context_drawer(&self) -> Option> { if !self.core.window.show_context { return None; } - Some(match self.context_page { - ContextPage::About => self.about(), - ContextPage::Settings => self.settings(), - ContextPage::AddAccountForm => add_account(self.placeholder_account.clone().unwrap()), - ContextPage::EditAccountForm => edit_account(self.placeholder_account.clone().unwrap()), - ContextPage::NewBookmarkForm => new_bookmark( - self.placeholder_bookmark.clone().unwrap(), - &self.placeholder_accounts_list, - self.placeholder_selected_account_index, + match self.context_page { + ContextPage::About => Some( + context_drawer::about(&self.about, Message::OpenExternalUrl, Message::ContextClose) + .title(self.context_page.title()), ), - - ContextPage::EditBookmarkForm => edit_bookmark( - self.placeholder_bookmark.clone().unwrap(), - self.placeholder_account.as_ref().unwrap(), + ContextPage::Settings => Some( + context_drawer::context_drawer(self.settings(), Message::ContextClose) + .title(self.context_page.title()), ), - ContextPage::ViewBookmarkNotes => { - view_notes(self.placeholder_bookmark.clone().unwrap()) - } - }) + ContextPage::AddAccountForm => Some( + context_drawer::context_drawer( + add_account(self.placeholder_account.clone().unwrap()), + Message::ContextClose, + ) + .title(self.context_page.title()), + ), + ContextPage::EditAccountForm => Some( + context_drawer::context_drawer( + edit_account(self.placeholder_account.clone().unwrap()), + Message::ContextClose, + ) + .title(self.context_page.title()), + ), + ContextPage::NewBookmarkForm => Some( + context_drawer::context_drawer( + new_bookmark( + self.placeholder_bookmark.clone().unwrap(), + &self.placeholder_accounts_list, + self.placeholder_selected_account_index, + ), + Message::ContextClose, + ) + .title(self.context_page.title()), + ), + ContextPage::EditBookmarkForm => Some( + context_drawer::context_drawer( + edit_bookmark( + self.placeholder_bookmark.clone().unwrap(), + self.placeholder_account.as_ref().unwrap(), + ), + Message::ContextClose, + ) + .title(self.context_page.title()), + ), + ContextPage::ViewBookmarkNotes => Some( + context_drawer::context_drawer( + view_notes(self.placeholder_bookmark.clone().unwrap()), + Message::ContextClose, + ) + .title(self.context_page.title()), + ), + } } fn dialog(&self) -> Option> { let dialog_page = self.dialog_pages.front()?; let dialog = match dialog_page { - DialogPage::RemoveAccount(account_id) => { - widget::dialog(fl!("remove") + " " + { &account_id.to_string() }) - .icon(icon::icon(load_icon("dialog-warning-symbolic")).size(58)) - .body(fl!("remove-account-confirm")) - .primary_action( - widget::button::destructive(fl!("yes")) - .on_press_maybe(Some(Message::CompleteRemoveDialog(*account_id, None))), - ) - .secondary_action( - widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), - ) - } - DialogPage::RemoveBookmark(account, bookmark) => { - widget::dialog(fl!("remove") + " " + { &bookmark.title }) - .icon(icon::icon(load_icon("dialog-warning-symbolic")).size(58)) - .body(fl!("remove-bookmark-confirm")) - .primary_action(widget::button::destructive(fl!("yes")).on_press_maybe(Some( - Message::CompleteRemoveDialog(*account, Some(bookmark.clone())), - ))) - .secondary_action( - widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), - ) - } + DialogPage::RemoveAccount(account) => widget::dialog() + .title(fl!("remove") + " " + { &account.display_name }) + .icon(icon::icon(load_icon("dialog-warning-symbolic")).size(58)) + .body(fl!("remove-account-confirm")) + .primary_action(widget::button::destructive(fl!("yes")).on_press_maybe(Some( + Message::CompleteRemoveDialog(account.id.unwrap(), None), + ))) + .secondary_action( + widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), + ), + DialogPage::RemoveBookmark(account, bookmark) => widget::dialog() + .icon(icon::icon(load_icon("dialog-warning-symbolic")).size(58)) + .title(fl!("remove") + " " + { &bookmark.title }) + .body(fl!("remove-bookmark-confirm")) + .primary_action(widget::button::destructive(fl!("yes")).on_press_maybe(Some( + Message::CompleteRemoveDialog(*account, Some(bookmark.clone())), + ))) + .secondary_action( + widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), + ), }; Some(dialog.into()) @@ -322,7 +383,6 @@ impl Application for Cosmicding { } fn subscription(&self) -> Subscription { - struct ConfigSubscription; struct ThemeSubscription; let subscriptions = vec![ @@ -336,21 +396,6 @@ impl Application for Cosmicding { } _ => None, }), - cosmic_config::config_subscription( - TypeId::of::(), - Self::APP_ID.into(), - CONFIG_VERSION, - ) - .map(|update: Update| { - if !update.errors.is_empty() { - log::info!( - "Errors loading config {:?}: {:?}", - update.keys, - update.errors - ); - } - Message::SystemThemeModeChange - }), cosmic_config::config_subscription::<_, cosmic_theme::ThemeMode>( TypeId::of::(), cosmic_theme::THEME_MODE_ID.into(), @@ -378,14 +423,23 @@ impl Application for Cosmicding { ($name: ident, $value: expr) => { match &self.config_handler { Some(config_handler) => { - if let Err(err) = - paste::paste! { self.config.[](config_handler, $value) } - { - log::warn!("Failed to save config {:?}: {}", stringify!($name), err); + match paste::paste! { self.config.[](config_handler, $value) } { + Ok(_) => {} + Err(err) => { + log::warn!( + "failed to save config {:?}: {}", + stringify!($name), + err + ); + } } } None => { self.config.$name = $value; + log::warn!( + "failed to save config {:?}: no config handler", + stringify!($name) + ); } } }; @@ -429,9 +483,9 @@ impl Application for Cosmicding { self.context_page = context_page; self.core.window.show_context = true; } - - self.set_context_title(context_page.title()); + //self.set_context_title(context_page.title()); } + Message::ContextClose => self.core.window.show_context = false, Message::AccountsView(message) => commands.push(self.accounts_view.update(message)), Message::LoadAccounts => { block_on(async { @@ -462,23 +516,26 @@ impl Application for Cosmicding { commands .push(self.update(Message::ToggleContextPage(ContextPage::EditAccountForm))); } - Message::RemoveAccount(account_id) => { + Message::RemoveAccount(account) => { if let Some(ref mut database) = &mut self.bookmarks_cursor.database { block_on(async { - db::SqliteDatabase::delete_all_bookmarks_of_account(database, account_id) - .await; + db::SqliteDatabase::delete_all_bookmarks_of_account( + database, + account.id.unwrap(), + ) + .await; }); block_on(async { - db::SqliteDatabase::delete_account(database, account_id).await; + db::SqliteDatabase::delete_account(database, account.id.unwrap()).await; }); self.bookmarks_view .bookmarks - .retain(|bkmrk| bkmrk.user_account_id != Some(account_id)); + .retain(|bkmrk| bkmrk.user_account_id != Some(account.id.unwrap())); commands.push( self.toasts .push(widget::toaster::Toast::new(fl!( "removed-account", - acc = account_id + acc = account.display_name ))) .map(cosmic::app::Message::App), ); @@ -487,6 +544,7 @@ impl Application for Cosmicding { self.accounts_cursor.fetch_next_results().await; }); self.accounts_view.accounts = self.accounts_cursor.result.clone().unwrap(); + commands.push(self.update(Message::LoadBookmarks)); } } Message::CompleteAddAccount(mut account) => { @@ -963,8 +1021,10 @@ impl Application for Cosmicding { } commands.push(self.update(Message::LoadBookmarks)); } - Message::OpenExternalUrl(url) => { - _ = open::that_detached(url); + Message::OpenExternalUrl(ref url) => { + if let Err(err) = open::that_detached(url) { + log::error!("Failed to open URL: {}", err); + } } Message::ViewBookmarkNotes(bookmark) => { self.placeholder_bookmark = Some(bookmark.clone()); @@ -984,10 +1044,10 @@ impl Application for Cosmicding { Message::UpdateConfig(config) => { self.config = config; } - Message::OpenRemoveAccountDialog(account_id) => { + Message::OpenRemoveAccountDialog(account) => { if self.dialog_pages.pop_front().is_none() { self.dialog_pages - .push_back(DialogPage::RemoveAccount(account_id)); + .push_back(DialogPage::RemoveAccount(account)); } } Message::OpenRemoveBookmarkDialog(account_id, bookmark) => { @@ -1103,37 +1163,6 @@ impl Application for Cosmicding { impl Cosmicding { #[allow(clippy::unused_self)] - pub fn about(&self) -> Element { - let spacing = theme::active().cosmic().spacing; - - let release = env!("CARGO_PKG_VERSION"); - let hash = env!("VERGEN_GIT_SHA"); - let short_hash: String = hash.chars().take(7).collect(); - let date = env!("VERGEN_GIT_COMMIT_DATE"); - - widget::column::with_children(vec![ - widget::text::title3(fl!("cosmicding")).into(), - widget::button::link(REPOSITORY) - .on_press(Message::OpenExternalUrl(REPOSITORY.to_string())) - .padding(spacing.space_none) - .into(), - widget::button::link(fl!( - "git-description", - hash = short_hash.as_str(), - date = date - )) - .on_press(Message::OpenExternalUrl(format!( - "{REPOSITORY}/commits/{hash}" - ))) - .padding(spacing.space_none) - .into(), - widget::text::caption(format!("v{release}")).into(), - ]) - .align_x(Alignment::Center) - .spacing(spacing.space_xxs) - .width(Length::Fill) - .into() - } fn settings(&self) -> Element { widget::settings::view_column(vec![ diff --git a/src/config.rs b/src/app/config.rs similarity index 57% rename from src/config.rs rename to src/app/config.rs index fa244c4..f354916 100644 --- a/src/config.rs +++ b/src/app/config.rs @@ -1,11 +1,59 @@ +use crate::app::Cosmicding; use cosmic::{ - cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry}, - theme, + cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, Config, CosmicConfigEntry}, + iced::Subscription, + theme, Application, }; use serde::{Deserialize, Serialize}; +use std::any::TypeId; pub const CONFIG_VERSION: u64 = 1; +#[derive(Debug, Clone, CosmicConfigEntry, Eq, PartialEq)] +#[version = 1] +pub struct CosmicConfig { + pub app_theme: AppTheme, + pub sort_option: SortOption, + pub items_per_page: u8, +} + +impl CosmicConfig { + pub fn config_handler() -> Option { + Config::new(Cosmicding::APP_ID, CONFIG_VERSION).ok() + } + + pub fn config() -> CosmicConfig { + match Self::config_handler() { + Some(config_handler) => { + CosmicConfig::get_entry(&config_handler).unwrap_or_else(|(errs, config)| { + log::info!("errors loading config: {:?}", errs); + config + }) + } + None => CosmicConfig::default(), + } + } + + pub fn subscription() -> Subscription> { + struct ConfigSubscription; + cosmic_config::config_subscription( + TypeId::of::(), + Cosmicding::APP_ID.into(), + CONFIG_VERSION, + ) + } +} + +impl Default for CosmicConfig { + fn default() -> Self { + Self { + app_theme: AppTheme::System, + sort_option: SortOption::BookmarksDateNewest, + items_per_page: 10, + } + } +} + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum AppTheme { Dark, @@ -39,21 +87,3 @@ pub enum SortOption { BookmarkAlphabeticalAscending, BookmarkAlphabeticalDescending, } - -#[derive(Debug, Clone, CosmicConfigEntry, Eq, PartialEq)] -#[version = 1] -pub struct Config { - pub app_theme: AppTheme, - pub sort_option: SortOption, - pub items_per_page: u8, -} - -impl Default for Config { - fn default() -> Self { - Self { - app_theme: AppTheme::System, - sort_option: SortOption::BookmarksDateNewest, - items_per_page: 10, - } - } -} diff --git a/src/utils/icons.rs b/src/app/icons.rs similarity index 94% rename from src/utils/icons.rs rename to src/app/icons.rs index 9bfa704..7485067 100644 --- a/src/utils/icons.rs +++ b/src/app/icons.rs @@ -2,6 +2,7 @@ use cosmic::widget::{self, icon::Handle}; #[cfg(target_os = "macos")] use std::env; +// NOTE: Consider caching icons in the future pub fn load_icon(icon: &str) -> Handle { // On Linux, we use the XDG desktop icons #[cfg(target_os = "linux")] diff --git a/src/key_binds.rs b/src/app/key_bind.rs similarity index 100% rename from src/key_binds.rs rename to src/app/key_bind.rs diff --git a/src/menu.rs b/src/app/menu.rs similarity index 82% rename from src/menu.rs rename to src/app/menu.rs index 4064ce4..94f8ed2 100644 --- a/src/menu.rs +++ b/src/app/menu.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::config::SortOption; +use crate::app::config::SortOption; use cosmic::widget::menu::key_bind::KeyBind; use cosmic::{ widget::menu::{items, root, Item, ItemHeight, ItemWidth, MenuBar, Tree}, @@ -26,17 +26,17 @@ pub fn menu_bar<'a>( items( key_binds, vec![ - Item::Button(fl!("add-account"), MenuAction::AddAccount), + Item::Button(fl!("add-account"), None, MenuAction::AddAccount), if accounts_present && matches!(app_state, ApplicationState::Normal) { - Item::Button(fl!("add-bookmark"), MenuAction::AddBookmark) + Item::Button(fl!("add-bookmark"), None, MenuAction::AddBookmark) } else { - Item::ButtonDisabled(fl!("add-bookmark"), MenuAction::AddBookmark) + Item::ButtonDisabled(fl!("add-bookmark"), None, MenuAction::AddBookmark) }, Item::Divider, if bookmarks_present && matches!(app_state, ApplicationState::Normal) { - Item::Button(fl!("refresh-bookmarks"), MenuAction::RefreshBookmarks) + Item::Button(fl!("refresh-bookmarks"), None, MenuAction::RefreshBookmarks) } else { - Item::ButtonDisabled(fl!("refresh-bookmarks"), MenuAction::Empty) + Item::ButtonDisabled(fl!("refresh-bookmarks"), None, MenuAction::Empty) }, ], ), @@ -46,8 +46,8 @@ pub fn menu_bar<'a>( items( key_binds, vec![ - Item::Button(fl!("about"), MenuAction::About), - Item::Button(fl!("settings"), MenuAction::Settings), + Item::Button(fl!("about"), None, MenuAction::About), + Item::Button(fl!("settings"), None, MenuAction::Settings), ], ), ), @@ -61,22 +61,26 @@ pub fn menu_bar<'a>( vec![ Item::CheckBox( fl!("bookmark-date-newest"), + None, matches!(sort_option, SortOption::BookmarksDateNewest), MenuAction::SetSortBookmarks(SortOption::BookmarksDateNewest), ), Item::CheckBox( fl!("bookmark-date-oldest"), + None, matches!(sort_option, SortOption::BookmarksDateOldest), MenuAction::SetSortBookmarks(SortOption::BookmarksDateOldest), ), Item::Divider, Item::CheckBox( fl!("bookmark-alphabetical-ascending"), + None, matches!(sort_option, SortOption::BookmarkAlphabeticalAscending), MenuAction::SetSortBookmarks(SortOption::BookmarkAlphabeticalAscending), ), Item::CheckBox( fl!("bookmark-alphabetical-descending"), + None, matches!(sort_option, SortOption::BookmarkAlphabeticalDescending), MenuAction::SetSortBookmarks( SortOption::BookmarkAlphabeticalDescending, @@ -85,15 +89,17 @@ pub fn menu_bar<'a>( ] } else { vec![ - Item::ButtonDisabled(fl!("bookmark-date-newest"), MenuAction::Empty), - Item::ButtonDisabled(fl!("bookmark-date-oldest"), MenuAction::Empty), + Item::ButtonDisabled(fl!("bookmark-date-newest"), None, MenuAction::Empty), + Item::ButtonDisabled(fl!("bookmark-date-oldest"), None, MenuAction::Empty), Item::Divider, Item::ButtonDisabled( fl!("bookmark-alphabetical-ascending"), + None, MenuAction::Empty, ), Item::ButtonDisabled( fl!("bookmark-alphabetical-descending"), + None, MenuAction::Empty, ), ] diff --git a/src/nav.rs b/src/app/nav.rs similarity index 97% rename from src/nav.rs rename to src/app/nav.rs index 815c42a..1ab9f76 100644 --- a/src/nav.rs +++ b/src/app/nav.rs @@ -1,4 +1,4 @@ -use crate::utils::icons::load_icon; +use crate::app::icons::load_icon; use cosmic::{widget::icon, Element}; use crate::{app, fl}; diff --git a/src/i18n.rs b/src/core/i18n.rs similarity index 60% rename from src/i18n.rs rename to src/core/i18n.rs index 7f0a935..37d6869 100644 --- a/src/i18n.rs +++ b/src/core/i18n.rs @@ -1,46 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, - unic_langid::LanguageIdentifier, DefaultLocalizer, LanguageLoader, Localizer, }; use once_cell::sync::Lazy; use rust_embed::RustEmbed; - -/// Applies the requested language(s) to requested translations from the `fl!()` macro. -pub fn init(requested_languages: &[LanguageIdentifier]) { - if let Err(why) = localizer().select(requested_languages) { - eprintln!("error while loading fluent localizations: {why}"); - } -} - -// Get the `Localizer` to be used for localizing this library. -#[must_use] -pub fn localizer() -> Box { - Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) -} - #[derive(RustEmbed)] #[folder = "i18n/"] struct Localizations; - pub static LANGUAGE_LOADER: Lazy = Lazy::new(|| { let loader: FluentLanguageLoader = fluent_language_loader!(); - loader .load_fallback_language(&Localizations) .expect("Error while loading fallback language"); - loader }); - -/// Request a localized string by ID from the i18n/ directory. #[macro_export] macro_rules! fl { ($message_id:literal) => {{ - i18n_embed_fl::fl!($crate::i18n::LANGUAGE_LOADER, $message_id) + i18n_embed_fl::fl!($crate::core::i18n::LANGUAGE_LOADER, $message_id) }}; - ($message_id:literal, $($args:expr),*) => {{ - i18n_embed_fl::fl!($crate::i18n::LANGUAGE_LOADER, $message_id, $($args), *) + i18n_embed_fl::fl!($crate::core::i18n::LANGUAGE_LOADER, $message_id, $($args), *) }}; } +// Get the `Localizer` to be used for localizing this library. +pub fn localizer() -> Box { + Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) +} +pub fn localize() { + let localizer = localizer(); + let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages(); + if let Err(error) = localizer.select(&requested_languages) { + eprintln!("Error while loading language for App List {}", error); + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..5399940 --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,2 @@ +pub mod i18n; +pub mod settings; diff --git a/src/core/settings.rs b/src/core/settings.rs new file mode 100644 index 0000000..e9d2837 --- /dev/null +++ b/src/core/settings.rs @@ -0,0 +1,24 @@ +use crate::core::i18n; + +pub fn settings() -> cosmic::app::Settings { + cosmic::app::Settings::default().size_limits( + cosmic::iced::Limits::NONE + .min_width(360.0) + .min_height(180.0), + ) +} + +pub fn flags() -> crate::app::Flags { + crate::app::Flags { + config_handler: crate::app::config::CosmicConfig::config_handler(), + config: crate::app::config::CosmicConfig::config(), + } +} + +pub fn init() { + i18n::localize(); + + std::env::set_var("RUST_LOG", "warn"); + pretty_env_logger::init(); + log::info!("such information"); +} diff --git a/src/db/mod.rs b/src/db/mod.rs index d83643d..fc77212 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,4 +1,4 @@ -use crate::config::SortOption; +use crate::app::config::SortOption; use anyhow::{anyhow, Result}; use std::path::Path; diff --git a/src/main.rs b/src/main.rs index 85593d4..7eb185c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,14 @@ mod app; -mod config; +mod core; mod db; mod http; -mod i18n; -mod key_binds; -mod menu; mod models; -mod nav; mod pages; -mod utils; +mod style; -use crate::config::{Config, CONFIG_VERSION}; -use app::{Flags, APPID}; -use cosmic::cosmic_config::{self, CosmicConfigEntry}; +use core::settings; fn main() -> cosmic::iced::Result { - let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages(); - i18n::init(&requested_languages); - env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); - let settings = cosmic::app::Settings::default(); - let (config_handler, config) = match cosmic_config::Config::new(APPID, CONFIG_VERSION) { - Ok(config_handler) => { - let config = match Config::get_entry(&config_handler) { - Ok(ok) => ok, - Err((errs, config)) => { - log::error!("{:?}", errs); - config - } - }; - (Some(config_handler), config) - } - Err(err) => { - log::error!("{:?}", err); - (None, Config::default()) - } - }; - let flags = Flags { - config_handler, - config, - }; - cosmic::app::run::(settings, flags) + settings::init(); + cosmic::app::run::(settings::settings(), settings::flags()) } diff --git a/src/models/db_cursor.rs b/src/models/db_cursor.rs index 5ca5a43..99b57d2 100644 --- a/src/models/db_cursor.rs +++ b/src/models/db_cursor.rs @@ -1,4 +1,4 @@ -use crate::config::SortOption; +use crate::app::config::SortOption; use crate::db::SqliteDatabase; use crate::models::account::Account; use crate::models::bookmarks::Bookmark; diff --git a/src/pages/accounts.rs b/src/pages/accounts.rs index bb8a4eb..d8679fa 100644 --- a/src/pages/accounts.rs +++ b/src/pages/accounts.rs @@ -1,15 +1,15 @@ -use crate::app::{ApplicationState, Message}; +use crate::app::{icons::load_icon, ApplicationState, Message}; use crate::fl; use crate::models::account::Account; use crate::models::db_cursor::AccountsPaginationCursor; -use crate::utils::{icons::load_icon, style::disabled_link_button}; +use crate::style::button::ButtonStyle; use chrono::{DateTime, Local}; use cosmic::iced::Length; use cosmic::iced_widget::tooltip; use cosmic::{ app::command::Task, cosmic_theme, - iced::{self, Alignment}, + iced::Alignment, theme, widget::{self}, Apply, Element, @@ -54,8 +54,8 @@ impl PageAccountsView { .spacing(20) .align_x(Alignment::Center), ) - .align_y(iced::alignment::Vertical::Center) - .align_x(iced::alignment::Horizontal::Center) + .align_y(Alignment::Center) + .align_x(Alignment::Center) .height(Length::Fill) .width(Length::Fill); widget::column::with_capacity(2) @@ -75,7 +75,7 @@ impl PageAccountsView { let refresh_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("refresh")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("refresh")).font_size(12).on_press( AppAccountsMessage::RefreshBookmarksForAccount(item.to_owned()), ), @@ -83,7 +83,7 @@ impl PageAccountsView { let edit_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("edit")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("edit")) .font_size(12) .on_press(AppAccountsMessage::EditAccount(item.to_owned())), @@ -91,7 +91,7 @@ impl PageAccountsView { let remove_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("remove")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("remove")) .font_size(12) .on_press(AppAccountsMessage::DeleteAccount(item.to_owned())), @@ -289,7 +289,7 @@ impl PageAccountsView { } AppAccountsMessage::DeleteAccount(account) => { commands.push(Task::perform(async {}, move |()| { - cosmic::app::Message::App(Message::OpenRemoveAccountDialog(account.id.unwrap())) + cosmic::app::Message::App(Message::OpenRemoveAccountDialog(account.clone())) })); } AppAccountsMessage::RefreshBookmarksForAccount(account) => { @@ -338,7 +338,7 @@ pub fn add_account<'a>(account: Account) -> Element<'a, Message> { widget::button::standard(fl!("save")).on_press(Message::CompleteAddAccount(account)), ) .width(Length::Fill) - .align_x(iced::alignment::Horizontal::Center); + .align_x(Alignment::Center); widget::column() .spacing(space_xxs) @@ -460,7 +460,7 @@ pub fn edit_account<'a>(account: Account) -> Element<'a, Message> { widget::button::standard(fl!("save")).on_press(Message::UpdateAccount(account)), ) .width(Length::Fill) - .align_x(iced::alignment::Horizontal::Center); + .align_x(Alignment::Center); widget::column() .spacing(space_xxs) diff --git a/src/pages/bookmarks.rs b/src/pages/bookmarks.rs index 131902c..e590b92 100644 --- a/src/pages/bookmarks.rs +++ b/src/pages/bookmarks.rs @@ -1,19 +1,18 @@ -use crate::app::{ApplicationState, Message}; +use crate::app::{icons::load_icon, ApplicationState, Message}; use crate::fl; use crate::models::account::Account; use crate::models::bookmarks::Bookmark; use crate::models::db_cursor::BookmarksPaginationCursor; -use crate::utils::{icons::load_icon, style::disabled_link_button}; +use crate::style::button::ButtonStyle; use chrono::{DateTime, Local}; use cosmic::iced::Length; use cosmic::{ app::command::Task, - iced::{self, Alignment}, + iced::Alignment, widget::{self}, Apply, Element, }; use cosmic::{cosmic_theme, theme}; -use iced::alignment::{Horizontal, Vertical}; #[derive(Debug, Default, Clone)] pub struct PageBookmarksView { @@ -61,8 +60,8 @@ impl PageBookmarksView { .spacing(20) .align_x(Alignment::Center), ) - .align_y(Vertical::Center) - .align_x(Horizontal::Center) + .align_y(Alignment::Center) + .align_x(Alignment::Center) .height(Length::Fill) .width(Length::Fill); widget::column::with_capacity(2) @@ -158,7 +157,7 @@ impl PageBookmarksView { let edit_bookmark_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("edit")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("edit")).font_size(12).on_press( AppBookmarksMessage::EditBookmark(bookmark_account_id, item.to_owned()), ), @@ -166,7 +165,7 @@ impl PageBookmarksView { let remove_bookmark_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("remove")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("remove")).font_size(12).on_press( AppBookmarksMessage::DeleteBookmark(bookmark_account_id, item.to_owned()), ), @@ -174,7 +173,7 @@ impl PageBookmarksView { let notes_button = match app_state { ApplicationState::Refreshing => widget::button::link(fl!("notes")) .font_size(12) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("notes")) .font_size(12) .on_press(AppBookmarksMessage::ViewNotes(item.clone())), @@ -186,7 +185,7 @@ impl PageBookmarksView { .font_size(12) .icon_size(11) .tooltip(item.web_archive_snapshot_url.clone()) - .class(disabled_link_button()), + .class(ButtonStyle::DisabledLink(false).into()), _ => widget::button::link(fl!("snapshot")) .spacing(spacing.space_xxxs) .trailing_icon(true) @@ -245,7 +244,7 @@ impl PageBookmarksView { columns.push( details_row .push(widget::horizontal_space()) - .align_y(iced::alignment::Vertical::Center) + .align_y(Alignment::Center) .spacing(spacing.space_xxs) .padding([ spacing.space_xxxs, @@ -479,7 +478,7 @@ where )), ) .width(Length::Fill) - .align_x(iced::alignment::Horizontal::Center); + .align_x(Alignment::Center); widget::column() .spacing(space_xxs) @@ -620,7 +619,7 @@ where .on_press(Message::UpdateBookmark(account.clone(), bookmark)), ) .width(Length::Fill) - .align_x(iced::alignment::Horizontal::Center); + .align_x(Alignment::Center); widget::column() .spacing(space_xxs) diff --git a/src/style/button.rs b/src/style/button.rs new file mode 100644 index 0000000..98d7621 --- /dev/null +++ b/src/style/button.rs @@ -0,0 +1,73 @@ +use cosmic::{iced, widget}; + +pub enum ButtonStyle { + DisabledLink(bool), +} + +impl From for cosmic::style::Button { + fn from(style: ButtonStyle) -> Self { + match style { + ButtonStyle::DisabledLink(is_selected) => Self::Custom { + active: Box::new(move |_, theme| { + let cosmic = theme.cosmic(); + let mut appearance = widget::button::Style::new(); + if is_selected { + appearance.background = + Some(iced::Background::Color(cosmic.accent.base.into())); + appearance.text_color = Some(cosmic.accent.on.into()); + } + appearance.border_radius = cosmic.radius_s().into(); + appearance + }), + + disabled: Box::new(move |theme| { + let cosmic = theme.cosmic(); + let mut appearance = widget::button::Style::new(); + if is_selected { + appearance.background = Some(iced::Background::Color( + cosmic.background.component.base.into(), + )); + appearance.text_color = Some(cosmic.accent.on.into()); + } else { + appearance.background = Some(iced::Background::Color( + cosmic.background.component.base.into(), + )); + appearance.text_color = Some(cosmic.button.on_disabled.into()); + } + + appearance + }), + hovered: Box::new(move |_, theme| { + let cosmic = theme.cosmic(); + let mut appearance = widget::button::Style::new(); + if is_selected { + appearance.background = + Some(iced::Background::Color(cosmic.accent.hover.into())); + appearance.text_color = Some(cosmic.accent.on.into()); + } else { + appearance.background = + Some(iced::Background::Color(cosmic.button.hover.into())); + appearance.text_color = Some(cosmic.button.on.into()); + } + appearance.border_radius = cosmic.radius_s().into(); + appearance + }), + pressed: Box::new(move |_, theme| { + let cosmic = theme.cosmic(); + let mut appearance = widget::button::Style::new(); + if is_selected { + appearance.background = + Some(iced::Background::Color(cosmic.accent.pressed.into())); + appearance.text_color = Some(cosmic.accent.on.into()); + } else { + appearance.background = + Some(iced::Background::Color(cosmic.button.pressed.into())); + appearance.text_color = Some(cosmic.button.on.into()); + } + appearance.border_radius = cosmic.radius_s().into(); + appearance + }), + }, + } + } +} diff --git a/src/style/mod.rs b/src/style/mod.rs new file mode 100644 index 0000000..aa200ca --- /dev/null +++ b/src/style/mod.rs @@ -0,0 +1 @@ +pub mod button; diff --git a/src/utils/mod.rs b/src/utils/mod.rs deleted file mode 100644 index db42ba3..0000000 --- a/src/utils/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod icons; -pub mod style; diff --git a/src/utils/style.rs b/src/utils/style.rs deleted file mode 100644 index b753e2b..0000000 --- a/src/utils/style.rs +++ /dev/null @@ -1,167 +0,0 @@ -use cosmic::{ - cosmic_theme::Component, - iced::{Background, Color}, - theme::{Button, TRANSPARENT_COMPONENT}, - widget::{self}, -}; - -pub fn disabled_link_button() -> Button { - Button::Custom { - active: Box::new(move |_, _| { - appearance(false, false, false, &Button::Link, |component| { - let text_color = Some(component.on.into()); - (component.hover.into(), text_color, text_color) - }) - }), - disabled: Box::new(move |_| { - appearance(false, false, true, &Button::Link, |component| { - let mut background = Color::from(component.base); - background.a *= 0.5; - ( - background, - Some(component.on_disabled.into()), - Some(component.on_disabled.into()), - ) - }) - }), - hovered: Box::new(move |_, _| { - appearance(false, false, false, &Button::Link, |component| { - let text_color = Some(component.on.into()); - - (component.hover.into(), text_color, text_color) - }) - }), - pressed: Box::new(move |_, _| { - appearance(false, false, false, &Button::Link, |component| { - let text_color = Some(component.on.into()); - - (component.pressed.into(), text_color, text_color) - }) - }), - } -} - -pub fn appearance( - focused: bool, - selected: bool, - disabled: bool, - style: &Button, - color: impl Fn(&Component) -> (Color, Option, Option), -) -> widget::button::Style { - let cosmic = cosmic::theme::active().cosmic().clone(); - let mut corner_radii = &cosmic.corner_radii.radius_xl; - let mut appearance = widget::button::Style::new(); - - match style { - Button::Standard - | Button::Text - | Button::Suggested - | Button::Destructive - | Button::Transparent => { - let style_component = match style { - Button::Standard => &cosmic.button, - Button::Text => &cosmic.text_button, - Button::Suggested => &cosmic.accent_button, - Button::Destructive => &cosmic.destructive_button, - Button::Transparent => &TRANSPARENT_COMPONENT, - _ => return appearance, - }; - - let (background, text, icon) = color(style_component); - appearance.background = Some(Background::Color(background)); - if !matches!(style, Button::Standard) { - appearance.text_color = text; - appearance.icon_color = icon; - } - } - - Button::Icon | Button::IconVertical | Button::HeaderBar => { - if matches!(style, Button::IconVertical) { - corner_radii = &cosmic.corner_radii.radius_m; - if selected { - appearance.overlay = Some(Background::Color(Color::from( - cosmic.icon_button.selected_state_color(), - ))); - } - } - - let (background, text, icon) = color(&cosmic.icon_button); - appearance.background = Some(Background::Color(background)); - // Only override icon button colors when it is disabled - appearance.icon_color = if disabled { icon } else { None }; - appearance.text_color = if disabled { text } else { None }; - } - - Button::Image => { - appearance.background = None; - appearance.text_color = Some(cosmic.accent.base.into()); - appearance.icon_color = Some(cosmic.accent.base.into()); - - corner_radii = &cosmic.corner_radii.radius_s; - appearance.border_radius = (*corner_radii).into(); - - if focused || selected { - appearance.border_width = 2.0; - appearance.border_color = cosmic.accent.base.into(); - } - - return appearance; - } - - Button::Link => { - appearance.background = None; - appearance.icon_color = Some(cosmic.accent.on_disabled.into()); - appearance.text_color = Some(cosmic.accent.on_disabled.into()); - corner_radii = &cosmic.corner_radii.radius_0; - } - - Button::Custom { .. } => (), - Button::AppletMenu => { - let (background, _, _) = color(&cosmic.text_button); - appearance.background = Some(Background::Color(background)); - - appearance.icon_color = Some(cosmic.background.on.into()); - appearance.text_color = Some(cosmic.background.on.into()); - corner_radii = &cosmic.corner_radii.radius_0; - } - Button::AppletIcon => { - let (background, _, _) = color(&cosmic.text_button); - appearance.background = Some(Background::Color(background)); - - appearance.icon_color = Some(cosmic.background.on.into()); - appearance.text_color = Some(cosmic.background.on.into()); - } - Button::MenuFolder => { - // Menu folders cannot be disabled, ignore customized icon and text color - let component = &cosmic.background.component; - let (background, _, _) = color(component); - appearance.background = Some(Background::Color(background)); - appearance.icon_color = Some(component.on.into()); - appearance.text_color = Some(component.on.into()); - corner_radii = &cosmic.corner_radii.radius_s; - } - Button::MenuItem => { - let (background, text, icon) = color(&cosmic.background.component); - appearance.background = Some(Background::Color(background)); - appearance.icon_color = icon; - appearance.text_color = text; - corner_radii = &cosmic.corner_radii.radius_s; - } - Button::MenuRoot => { - appearance.background = None; - appearance.icon_color = None; - appearance.text_color = None; - } - } - - appearance.border_radius = (*corner_radii).into(); - - if focused { - appearance.outline_width = 1.0; - appearance.outline_color = cosmic.accent.base.into(); - appearance.border_width = 2.0; - appearance.border_color = Color::TRANSPARENT; - } - - appearance -}