diff --git a/CHANGELOG.md b/CHANGELOG.md index 3311adbc1..3f601593e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +Added: + +- Dynamically select dark or light theme based on OS appearance. See [configuartion](https://halloy.squidowl.org/configuration/themes/index.html). + # 2024.12 (2024-09-17) Added: diff --git a/Cargo.lock b/Cargo.lock index 444d2b0c5..a389ea926 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,24 @@ dependencies = [ "libloading", ] +[[package]] +name = "ashpd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01992ad7774250d5b7fe214e2676cb99bf92564436d8135ab44fe815e71769a9" +dependencies = [ + "async-fs 2.1.2", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand", + "serde", + "serde_repr", + "url", + "zbus 3.15.2", +] + [[package]] name = "ashpd" version = "0.8.1" @@ -204,7 +222,17 @@ dependencies = [ "serde_repr", "tokio", "url", - "zbus", + "zbus 4.4.0", +] + +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", ] [[package]] @@ -213,7 +241,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" dependencies = [ - "event-listener", + "event-listener 5.3.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -239,20 +267,32 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.1.1", + "futures-lite 2.3.0", "slab", ] +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "blocking", + "futures-lite 1.13.0", +] + [[package]] name = "async-fs" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" dependencies = [ - "async-lock", + "async-lock 3.4.0", "blocking", - "futures-lite", + "futures-lite 2.3.0", ] [[package]] @@ -267,36 +307,93 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + [[package]] name = "async-io" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.3.0", "parking", - "polling", - "rustix", + "polling 3.7.3", + "rustix 0.38.37", "slab", "tracing", "windows-sys 0.59.0", ] +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener", + "event-listener 5.3.1", "event-listener-strategy", "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.3.4", + "blocking", + "futures-lite 2.3.0", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.37", + "windows-sys 0.48.0", +] + [[package]] name = "async-process" version = "2.3.0" @@ -304,15 +401,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", - "async-io", - "async-lock", + "async-io 2.3.4", + "async-lock 3.4.0", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", - "rustix", + "event-listener 5.3.1", + "futures-lite 2.3.0", + "rustix 0.38.37", "tracing", ] @@ -333,13 +430,13 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io", - "async-lock", + "async-io 2.3.4", + "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix", + "rustix 0.38.37", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -491,7 +588,7 @@ dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.3.0", "piper", ] @@ -553,8 +650,8 @@ checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ "bitflags 2.6.0", "log", - "polling", - "rustix", + "polling 3.7.3", + "rustix 0.38.37", "slab", "thiserror", ] @@ -567,8 +664,8 @@ checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "bitflags 2.6.0", "log", - "polling", - "rustix", + "polling 3.7.3", + "rustix 0.38.37", "slab", "thiserror", ] @@ -580,7 +677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" dependencies = [ "calloop 0.12.4", - "rustix", + "rustix 0.38.37", "wayland-backend", "wayland-client", ] @@ -592,7 +689,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ "calloop 0.13.0", - "rustix", + "rustix 0.38.37", "wayland-backend", "wayland-client", ] @@ -778,6 +875,26 @@ dependencies = [ "crossbeam-utils", ] +[[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", + "once_cell", + "tiny-keccak", +] + [[package]] name = "const_format" version = "0.2.33" @@ -1036,13 +1153,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c" dependencies = [ "dconf_rs", - "detect-desktop-environment", + "detect-desktop-environment 0.2.0", "dirs", "objc", - "rust-ini", + "rust-ini 0.18.0", "web-sys", "winreg 0.10.1", - "zbus", + "zbus 4.4.0", +] + +[[package]] +name = "dark-light" +version = "1.1.1" +source = "git+https://github.com/frewsxcv/rust-dark-light?rev=77ae4349f11a556cef9c683803a832f171253479#77ae4349f11a556cef9c683803a832f171253479" +dependencies = [ + "anyhow", + "ashpd 0.7.0", + "dconf_rs", + "detect-desktop-environment 1.1.0", + "futures", + "objc", + "rust-ini 0.20.0", + "web-sys", + "winreg 0.52.0", + "xdg", + "zbus 3.15.2", ] [[package]] @@ -1105,6 +1240,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "1.0.0" @@ -1133,6 +1279,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21d8ad60dd5b13a4ee6bd8fa2d5d88965c597c67bce32b5fc49c94f55cb50810" +[[package]] +name = "detect-desktop-environment" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf27a1bbe31ac901a2350a6316b1f7056067118abe6bf1ff015d5950ac5e3eb3" + [[package]] name = "digest" version = "0.10.7" @@ -1205,6 +1357,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +[[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 = "document-features" version = "0.2.10" @@ -1235,7 +1396,7 @@ dependencies = [ "bytemuck", "drm-ffi", "drm-fourcc", - "rustix", + "rustix 0.38.37", ] [[package]] @@ -1245,7 +1406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" dependencies = [ "drm-sys", - "rustix", + "rustix 0.38.37", ] [[package]] @@ -1361,6 +1522,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener" version = "5.3.1" @@ -1378,7 +1556,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener", + "event-listener 5.3.1", "pin-project-lite", ] @@ -1418,6 +1596,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.1.1" @@ -1599,13 +1786,28 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-lite" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand", + "fastrand 2.1.1", "futures-core", "futures-io", "parking", @@ -1853,6 +2055,7 @@ version = "0.1.0" dependencies = [ "bytesize", "chrono", + "dark-light 1.1.1 (git+https://github.com/frewsxcv/rust-dark-light?rev=77ae4349f11a556cef9c683803a832f171253479)", "data", "embed-resource", "fern", @@ -2060,7 +2263,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -2111,7 +2314,7 @@ source = "git+https://github.com/iced-rs/iced?rev=88a2fac1f9171f162ecfe2a033cba5 dependencies = [ "bitflags 2.6.0", "bytes", - "dark-light", + "dark-light 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glam", "log", "num-traits", @@ -2324,6 +2527,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9" +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipc" version = "0.1.0" @@ -2573,6 +2787,12 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2659,6 +2879,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -2823,6 +3052,18 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", +] + [[package]] name = "nix" version = "0.29.0" @@ -2833,7 +3074,7 @@ dependencies = [ "cfg-if", "cfg_aliases 0.2.1", "libc", - "memoffset", + "memoffset 0.9.1", ] [[package]] @@ -2856,7 +3097,7 @@ dependencies = [ "mac-notification-sys", "serde", "tauri-winrt-notification", - "zbus", + "zbus 4.4.0", ] [[package]] @@ -2910,7 +3151,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 2.0.77", @@ -3265,10 +3506,20 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" dependencies = [ - "dlv-list", + "dlv-list 0.3.0", "hashbrown 0.12.3", ] +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list 0.5.2", + "hashbrown 0.14.5", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -3490,7 +3741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.1.1", "futures-io", ] @@ -3513,6 +3764,22 @@ dependencies = [ "miniz_oxide 0.7.4", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "polling" version = "3.7.3" @@ -3523,7 +3790,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix", + "rustix 0.38.37", "tracing", "windows-sys 0.59.0", ] @@ -3555,13 +3822,23 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + [[package]] name = "proc-macro-crate" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit", + "toml_edit 0.22.21", ] [[package]] @@ -3828,7 +4105,7 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" dependencies = [ - "ashpd", + "ashpd 0.8.1", "block", "dispatch", "js-sys", @@ -3887,7 +4164,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" dependencies = [ "cfg-if", - "ordered-multimap", + "ordered-multimap 0.4.3", +] + +[[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 0.7.3", ] [[package]] @@ -3917,6 +4204,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.37" @@ -4257,7 +4558,7 @@ dependencies = [ "libc", "log", "memmap2", - "rustix", + "rustix 0.38.37", "thiserror", "wayland-backend", "wayland-client", @@ -4282,7 +4583,7 @@ dependencies = [ "libc", "log", "memmap2", - "rustix", + "rustix 0.38.37", "thiserror", "wayland-backend", "wayland-client", @@ -4314,6 +4615,16 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.7" @@ -4335,7 +4646,7 @@ dependencies = [ "cfg_aliases 0.2.1", "core-graphics 0.24.0", "drm", - "fastrand", + "fastrand 2.1.1", "foreign-types 0.5.0", "js-sys", "log", @@ -4345,7 +4656,7 @@ dependencies = [ "objc2-quartz-core", "raw-window-handle", "redox_syscall 0.5.4", - "rustix", + "rustix 0.38.37", "tiny-xlib", "wasm-bindgen", "wayland-backend", @@ -4568,9 +4879,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.1.1", "once_cell", - "rustix", + "rustix 0.38.37", "windows-sys 0.59.0", ] @@ -4643,6 +4954,15 @@ dependencies = [ "isolang", ] +[[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" @@ -4716,7 +5036,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.7", "tokio-macros", "tracing", "windows-sys 0.52.0", @@ -4787,7 +5107,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.21", ] [[package]] @@ -4799,6 +5119,17 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.21" @@ -4809,7 +5140,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.18", ] [[package]] @@ -4906,7 +5237,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ - "memoffset", + "memoffset 0.9.1", "tempfile", "winapi", ] @@ -5045,6 +5376,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -5160,7 +5497,7 @@ checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 0.38.37", "scoped-tls", "smallvec", "wayland-sys", @@ -5173,7 +5510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" dependencies = [ "bitflags 2.6.0", - "rustix", + "rustix 0.38.37", "wayland-backend", "wayland-scanner", ] @@ -5195,7 +5532,7 @@ version = "0.31.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a94697e66e76c85923b0d28a0c251e8f0666f58fc47d316c0f4da6da75d37cb" dependencies = [ - "rustix", + "rustix 0.38.37", "wayland-client", "xcursor", ] @@ -5854,7 +6191,7 @@ dependencies = [ "pin-project", "raw-window-handle", "redox_syscall 0.4.1", - "rustix", + "rustix 0.38.37", "sctk-adwaita", "smithay-client-toolkit 0.18.1", "smol_str", @@ -5874,6 +6211,15 @@ dependencies = [ "xkbcommon-dl", ] +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winnow" version = "0.6.18" @@ -5924,7 +6270,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix", + "rustix 0.38.37", "x11rb-protocol", ] @@ -5993,29 +6339,70 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +[[package]] +name = "zbus" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +dependencies = [ + "async-broadcast 0.5.1", + "async-executor", + "async-fs 1.6.0", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process 1.8.1", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener 2.5.3", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.26.4", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros 3.15.2", + "zbus_names 2.6.1", + "zvariant 3.15.2", +] + [[package]] name = "zbus" version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" dependencies = [ - "async-broadcast", + "async-broadcast 0.7.1", "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", + "async-fs 2.1.2", + "async-io 2.3.4", + "async-lock 3.4.0", + "async-process 2.3.0", "async-recursion", "async-task", "async-trait", "blocking", "enumflags2", - "event-listener", + "event-listener 5.3.1", "futures-core", "futures-sink", "futures-util", "hex", - "nix", + "nix 0.29.0", "ordered-stream", "rand", "serde", @@ -6027,9 +6414,23 @@ dependencies = [ "uds_windows", "windows-sys 0.52.0", "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", + "zbus_macros 4.4.0", + "zbus_names 3.0.0", + "zvariant 4.2.0", +] + +[[package]] +name = "zbus_macros" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils 1.0.1", ] [[package]] @@ -6038,11 +6439,22 @@ version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 2.0.77", - "zvariant_utils", + "zvariant_utils 2.1.0", +] + +[[package]] +name = "zbus_names" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +dependencies = [ + "serde", + "static_assertions", + "zvariant 3.15.2", ] [[package]] @@ -6053,7 +6465,7 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" dependencies = [ "serde", "static_assertions", - "zvariant", + "zvariant 4.2.0", ] [[package]] @@ -6098,6 +6510,21 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "zvariant" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "url", + "zvariant_derive 3.15.2", +] + [[package]] name = "zvariant" version = "4.2.0" @@ -6109,7 +6536,20 @@ dependencies = [ "serde", "static_assertions", "url", - "zvariant_derive", + "zvariant_derive 4.2.0", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils 1.0.1", ] [[package]] @@ -6118,11 +6558,22 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 2.0.77", - "zvariant_utils", + "zvariant_utils 2.1.0", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 42611b9ff..a73816235 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ iced = { version = "0.14.0-dev", features = [ "lazy", "advanced", "image", - "multi-window" + "multi-window", ] } log = "0.4.16" once_cell = "1.18" @@ -41,6 +41,9 @@ rodio = "0.19.0" strum = { version = "0.26.3", features = ["derive"] } tokio-stream = {version = "0.1.16", features = ["fs"] } +# Using commit hash for dark-light as latest release didn't have async notify. +dark-light = { git = "https://github.com/frewsxcv/rust-dark-light", rev = "77ae4349f11a556cef9c683803a832f171253479" } + [dependencies.uuid] version = "1.0" features = ["v4"] diff --git a/book/src/configuration/themes/README.md b/book/src/configuration/themes/README.md index d122bccb2..d36b8dfd0 100644 --- a/book/src/configuration/themes/README.md +++ b/book/src/configuration/themes/README.md @@ -1,22 +1,34 @@ # Themes +**Example** + ```toml -theme = "" +# Static +theme = "ferra" + +# Dynamic +theme = { light = "ferra-light", dark = "ferra" } ``` -| Key | Description | Default | -| ----------- | ---------------------------- | -------- | -| `theme`[^1] | Name of the theme to use[^2] | `""`[^3] | -[^1]: `theme` is a root key, so it must be placed before any section. -[^2]: Name of theme file inside `themes` folder. -[^3]: Using [Ferra](https://github.com/casperstorm/ferra/) by default. +## `theme` + +Specify the theme name(s) to use. The theme must correspond to a file located in the `themes` folder, which can be found in the Halloy configuration directory. The default theme in Halloy is [Ferra](https://github.com/casperstorm/ferra/). + +When a dynamic theme is used, Halloy will match the appearance of the OS. + +- **type**: string or object +- **values**: `""`, `{ light = "", dark = "" }` +- **default**: `"ferra"` + +> 💡 See all community created themes [here](./community.md). ## Custom themes To create a custom theme for Halloy, simply place a theme file (with a `.toml` extension) inside the themes folder within the configuration directory. -> 💡 The configuration direction can be found [here](../../configuration/). +> 💡 Halloy has a built in theme editor which makes theme creation easier + Each `""` is expected to be a valid hex color. If invalid, or if the key is removed, the color will fallback to transparent. A custom theme is structured as follows: diff --git a/data/src/appearance.rs b/data/src/appearance.rs new file mode 100644 index 000000000..a25315c3e --- /dev/null +++ b/data/src/appearance.rs @@ -0,0 +1,40 @@ +pub use theme::Theme; + +pub mod theme; + +#[derive(Debug, Clone)] +pub struct Appearance { + pub selected: Selected, + pub all: Vec, +} + +impl Default for Appearance { + fn default() -> Self { + Self { + selected: Selected::default(), + all: vec![Theme::default()], + } + } +} + +#[derive(Debug, Clone)] +pub enum Selected { + Static(Theme), + Dynamic { light: Theme, dark: Theme }, +} + +impl Default for Selected { + fn default() -> Self { + Self::Static(Theme::default()) + } +} + +impl Selected { + pub fn dynamic(light: Theme, dark: Theme) -> Selected { + Selected::Dynamic { light, dark } + } + + pub fn specific(theme: Theme) -> Selected { + Selected::Static(theme) + } +} diff --git a/data/src/theme.rs b/data/src/appearance/theme.rs similarity index 99% rename from data/src/theme.rs rename to data/src/appearance/theme.rs index f3de2cf3b..f399d27ea 100644 --- a/data/src/theme.rs +++ b/data/src/appearance/theme.rs @@ -11,7 +11,7 @@ use thiserror::Error; use tokio::fs; const DEFAULT_THEME_NAME: &str = "Ferra"; -const DEFAULT_THEME_CONTENT: &str = include_str!("../../assets/themes/ferra.toml"); +const DEFAULT_THEME_CONTENT: &str = include_str!("../../../assets/themes/ferra.toml"); #[derive(Debug, Clone)] pub struct Theme { diff --git a/data/src/config.rs b/data/src/config.rs index bc8ff08c9..80b91d1d7 100644 --- a/data/src/config.rs +++ b/data/src/config.rs @@ -18,10 +18,12 @@ pub use self::notification::Notifications; pub use self::proxy::Proxy; pub use self::server::Server; pub use self::sidebar::Sidebar; + +use crate::appearance::theme::Colors; +use crate::appearance::{self, Appearance}; use crate::audio::{self, Sound}; use crate::environment::config_dir; use crate::server::Map as ServerMap; -use crate::theme::Colors; use crate::{environment, Theme}; pub mod buffer; @@ -34,11 +36,11 @@ pub mod server; pub mod sidebar; const CONFIG_TEMPLATE: &str = include_str!("../../config.toml"); -const DEFAULT_THEME_FILE_NAME: &str = "ferra.toml"; +const DEFAULT_THEME_NAME: &str = "ferra"; #[derive(Debug, Clone, Default)] pub struct Config { - pub themes: Themes, + pub appearance: Appearance, pub servers: ServerMap, pub proxy: Option, pub font: Font, @@ -78,21 +80,6 @@ pub struct Font { pub size: Option, } -#[derive(Debug, Clone)] -pub struct Themes { - pub default: Theme, - pub all: Vec, -} - -impl Default for Themes { - fn default() -> Self { - Self { - default: Theme::default(), - all: vec![Theme::default()], - } - } -} - impl Config { pub fn config_dir() -> PathBuf { let dir = environment::config_dir(); @@ -134,10 +121,32 @@ impl Config { pub async fn load() -> Result { use tokio::fs; + #[derive(Deserialize, Debug)] + #[serde(untagged)] + pub enum ThemeKeys { + Static(String), + Dynamic { light: String, dark: String }, + } + + impl Default for ThemeKeys { + fn default() -> Self { + Self::Static(Default::default()) + } + } + + impl ThemeKeys { + pub fn keys(&self) -> (&str, Option<&str>) { + match self { + ThemeKeys::Static(manual) => (manual, None), + ThemeKeys::Dynamic { light, dark } => (light, Some(dark)), + } + } + } + #[derive(Deserialize)] pub struct Configuration { #[serde(default)] - pub theme: String, + pub theme: ThemeKeys, pub servers: ServerMap, pub proxy: Option, #[serde(default)] @@ -181,10 +190,12 @@ impl Config { let loaded_notifications = notifications.load_sounds()?; - let themes = Self::load_themes(&theme).await.unwrap_or_default(); + let appearance = Self::load_appearance(theme.keys()) + .await + .unwrap_or_default(); Ok(Config { - themes, + appearance, servers, font, proxy, @@ -198,7 +209,7 @@ impl Config { }) } - async fn load_themes(default_key: &str) -> Result { + async fn load_appearance(theme_keys: (&str, Option<&str>)) -> Result { use tokio::fs; #[derive(Deserialize)] @@ -224,7 +235,8 @@ impl Config { }; let mut all = vec![]; - let mut default = Theme::default(); + let mut first_theme = Theme::default(); + let mut second_theme = theme_keys.1.map(|_| Theme::default()); let mut has_halloy_theme = false; let mut stream = ReadDirStream::new(fs::read_dir(Self::themes_dir()).await?); @@ -237,14 +249,17 @@ impl Config { continue; }; - if file_name.ends_with(".toml") { + if let Some(file_name) = file_name.strip_suffix(".toml") { if let Some(theme) = read_entry(entry).await { - if file_name.strip_suffix(".toml").unwrap_or_default() == default_key - || file_name == default_key - { - default = theme.clone(); + if file_name == theme_keys.0 { + first_theme = theme.clone(); + } + + if Some(file_name) == theme_keys.1 { + second_theme = Some(theme.clone()); } - if file_name == DEFAULT_THEME_FILE_NAME { + + if file_name.to_lowercase() == DEFAULT_THEME_NAME { has_halloy_theme = true; } @@ -257,7 +272,13 @@ impl Config { all.push(Theme::default()); } - Ok(Themes { default, all }) + let selected = if let Some(second_theme) = second_theme { + appearance::Selected::dynamic(first_theme, second_theme) + } else { + appearance::Selected::specific(first_theme) + }; + + Ok(Appearance { selected, all }) } pub fn create_initial_config() { diff --git a/data/src/lib.rs b/data/src/lib.rs index 5f54243a0..71fead202 100644 --- a/data/src/lib.rs +++ b/data/src/lib.rs @@ -10,12 +10,13 @@ pub use self::mode::Mode; pub use self::pane::Pane; pub use self::server::Server; pub use self::shortcut::Shortcut; -pub use self::theme::Theme; +pub use self::appearance::Theme; pub use self::url::Url; pub use self::user::User; pub use self::version::Version; pub use self::window::Window; +pub mod appearance; pub mod audio; pub mod buffer; pub mod channel; @@ -38,7 +39,6 @@ pub mod pane; pub mod server; pub mod shortcut; pub mod stream; -pub mod theme; pub mod time; pub mod url; pub mod user; diff --git a/data/src/message/formatting.rs b/data/src/message/formatting.rs index 7a5ef80b6..50372c47b 100644 --- a/data/src/message/formatting.rs +++ b/data/src/message/formatting.rs @@ -4,8 +4,9 @@ use iced_core::color; use itertools::PeekingNext; use serde::{Deserialize, Serialize}; +use crate::appearance::theme; + pub use self::encode::encode; -use crate::theme; pub mod encode; diff --git a/data/src/url.rs b/data/src/url.rs index 8cfa507f2..fe971fa92 100644 --- a/data/src/url.rs +++ b/data/src/url.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use log::warn; use regex::Regex; -use crate::{config, theme, Server}; +use crate::{appearance::theme, config, Server}; #[derive(Debug, Clone)] pub enum Url { diff --git a/data/src/user.rs b/data/src/user.rs index d4ab6df6c..f419caf49 100644 --- a/data/src/user.rs +++ b/data/src/user.rs @@ -6,7 +6,7 @@ use irc::proto; use itertools::sorted; use serde::{Deserialize, Serialize}; -use crate::{buffer, config::buffer::UsernameFormat, mode, theme::Colors}; +use crate::{appearance::theme::Colors, buffer, config::buffer::UsernameFormat, mode}; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(into = "String")] diff --git a/src/appearance.rs b/src/appearance.rs new file mode 100644 index 000000000..61a5cf090 --- /dev/null +++ b/src/appearance.rs @@ -0,0 +1,88 @@ +use data::appearance; +use futures::{stream::BoxStream, StreamExt}; +use iced::advanced::subscription::Hasher; +use iced::futures; +use iced::{advanced::graphics::futures::subscription, Subscription}; + +pub use theme::Theme; + +pub mod theme; + +#[derive(Debug, Clone, Copy)] +pub enum Mode { + Dark, + Light, +} + +impl TryFrom for Mode { + type Error = (); + + fn try_from(mode: dark_light::Mode) -> Result { + match mode { + dark_light::Mode::Dark => Ok(Mode::Dark), + dark_light::Mode::Light => Ok(Mode::Light), + // We ignore `Default` as it is defined as `Unspecified``. + dark_light::Mode::Default => Err(()), + } + } +} + +struct Appearance; + +impl subscription::Recipe for Appearance { + type Output = Mode; + + fn hash(&self, state: &mut Hasher) { + use std::hash::Hash; + + struct Marker; + std::any::TypeId::of::().hash(state); + } + + fn stream(self: Box, _input: subscription::EventStream) -> BoxStream<'static, Mode> { + let stream_future = async { + match dark_light::subscribe().await { + Ok(stream) => stream + .filter_map(|m| async move { + match Mode::try_from(m) { + Ok(mode) => Some(mode), + Err(_) => None, + } + }) + .boxed(), + Err(err) => { + println!("error: {:?}", err); + futures::stream::empty().boxed() + } + } + }; + + futures::stream::once(stream_future).flatten().boxed() + } +} + +pub fn subscription() -> Subscription { + subscription::from_recipe(Appearance) +} + +pub fn detect() -> Option { + Mode::try_from(dark_light::detect()).ok() +} + +pub fn theme(selected: &data::appearance::Selected) -> data::appearance::Theme { + match &selected { + appearance::Selected::Static(theme) => theme.clone(), + appearance::Selected::Dynamic { light, dark } => match detect() { + Some(mode) => match mode { + Mode::Dark => dark.clone(), + Mode::Light => light.clone(), + }, + None => { + log::warn!( + "[theme] couldn't determine the OS appearance, using the default theme." + ); + Default::default() + } + }, + } +} diff --git a/src/theme.rs b/src/appearance/theme.rs similarity index 98% rename from src/theme.rs rename to src/appearance/theme.rs index 44dd9e1e2..08f1f1c49 100644 --- a/src/theme.rs +++ b/src/appearance/theme.rs @@ -2,7 +2,7 @@ use iced::application; use crate::widget::combo_box; -pub use data::theme::{ +pub use data::appearance::theme::{ color_to_hex, hex_to_color, Buffer, Button, Buttons, Colors, General, ServerMessages, Text, }; diff --git a/src/theme/button.rs b/src/appearance/theme/button.rs similarity index 100% rename from src/theme/button.rs rename to src/appearance/theme/button.rs diff --git a/src/theme/checkbox.rs b/src/appearance/theme/checkbox.rs similarity index 100% rename from src/theme/checkbox.rs rename to src/appearance/theme/checkbox.rs diff --git a/src/theme/container.rs b/src/appearance/theme/container.rs similarity index 100% rename from src/theme/container.rs rename to src/appearance/theme/container.rs diff --git a/src/theme/context_menu.rs b/src/appearance/theme/context_menu.rs similarity index 100% rename from src/theme/context_menu.rs rename to src/appearance/theme/context_menu.rs diff --git a/src/theme/menu.rs b/src/appearance/theme/menu.rs similarity index 100% rename from src/theme/menu.rs rename to src/appearance/theme/menu.rs diff --git a/src/theme/pane_grid.rs b/src/appearance/theme/pane_grid.rs similarity index 100% rename from src/theme/pane_grid.rs rename to src/appearance/theme/pane_grid.rs diff --git a/src/theme/progress_bar.rs b/src/appearance/theme/progress_bar.rs similarity index 100% rename from src/theme/progress_bar.rs rename to src/appearance/theme/progress_bar.rs diff --git a/src/theme/rule.rs b/src/appearance/theme/rule.rs similarity index 100% rename from src/theme/rule.rs rename to src/appearance/theme/rule.rs diff --git a/src/theme/scrollable.rs b/src/appearance/theme/scrollable.rs similarity index 100% rename from src/theme/scrollable.rs rename to src/appearance/theme/scrollable.rs diff --git a/src/theme/selectable_text.rs b/src/appearance/theme/selectable_text.rs similarity index 100% rename from src/theme/selectable_text.rs rename to src/appearance/theme/selectable_text.rs diff --git a/src/theme/text.rs b/src/appearance/theme/text.rs similarity index 97% rename from src/theme/text.rs rename to src/appearance/theme/text.rs index 2f9f24c68..e85ed4867 100644 --- a/src/theme/text.rs +++ b/src/appearance/theme/text.rs @@ -1,5 +1,5 @@ use data::{ - theme::{alpha_color, randomize_color}, + appearance::theme::{alpha_color, randomize_color}, user::NickColor, }; use iced::{ diff --git a/src/theme/text_input.rs b/src/appearance/theme/text_input.rs similarity index 100% rename from src/theme/text_input.rs rename to src/appearance/theme/text_input.rs diff --git a/src/main.rs b/src/main.rs index b9bf5dd2a..727f5be9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![allow(clippy::large_enum_variant, clippy::too_many_arguments)] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +mod appearance; mod audio; mod buffer; mod event; @@ -11,7 +12,6 @@ mod modal; mod notification; mod screen; mod stream; -mod theme; mod url; mod widget; mod window; @@ -20,6 +20,7 @@ use std::collections::HashSet; use std::env; use std::time::{Duration, Instant}; +use appearance::{theme, Theme}; use chrono::Utc; use data::config::{self, Config}; use data::history::manager::Broadcast; @@ -33,7 +34,6 @@ use tokio::runtime; use self::event::{events, Event}; use self::modal::Modal; -use self::theme::Theme; use self::widget::Element; use self::window::Window; @@ -185,7 +185,7 @@ impl Halloy { Halloy { version: Version::new(), screen, - theme: config.themes.default.clone().into(), + theme: appearance::theme(&config.appearance.selected).into(), clients: Default::default(), servers: config.servers.clone(), config, @@ -207,7 +207,7 @@ pub enum Screen { #[derive(Debug)] pub enum Message { - ThemesReloaded(config::Themes), + AppearanceReloaded(data::appearance::Appearance), ScreenConfigReloaded(Result), Dashboard(dashboard::Message), Stream(stream::Update), @@ -219,6 +219,7 @@ pub enum Message { Version(Option), Modal(modal::Message), RouteReceived(String), + AppearanceChange(appearance::Mode), Window(window::Id, window::Event), WindowSettingsSaved(Result<(), window::Error>), } @@ -283,8 +284,8 @@ impl Halloy { fn update(&mut self, message: Message) -> Task { match message { - Message::ThemesReloaded(updated) => { - self.config.themes = updated; + Message::AppearanceReloaded(appearance) => { + self.config.appearance = appearance; Task::none() } Message::ScreenConfigReloaded(updated) => { @@ -321,7 +322,7 @@ impl Halloy { .collect::>(); self.servers = updated.servers.clone(); - self.theme = updated.themes.default.clone().into(); + self.theme = appearance::theme(&updated.appearance.selected).into(); self.config = updated; for server in removed_servers { @@ -335,8 +336,8 @@ impl Halloy { Task::none() } Some(dashboard::Event::ReloadThemes) => Task::future(Config::load()) - .and_then(|config| Task::done(config.themes)) - .map(Message::ThemesReloaded), + .and_then(|config| Task::done(config.appearance)) + .map(Message::AppearanceReloaded), Some(dashboard::Event::QuitServer(server)) => { self.clients.quit(&server, None); Task::none() @@ -880,6 +881,18 @@ impl Halloy { log::error!("window settings failed to save: {:?}", err) } + Task::none() + } + Message::AppearanceChange(mode) => { + if let data::appearance::Selected::Dynamic { light, dark } = + &self.config.appearance.selected + { + self.theme = match mode { + appearance::Mode::Dark => dark.clone().into(), + appearance::Mode::Light => light.clone().into(), + } + } + Task::none() } } @@ -964,6 +977,7 @@ impl Halloy { url::listen().map(Message::RouteReceived), events().map(|(window, event)| Message::Event(window, event)), window::events().map(|(window, event)| Message::Window(window, event)), + appearance::subscription().map(Message::AppearanceChange), tick, streams, ]) diff --git a/src/screen/dashboard/command_bar.rs b/src/screen/dashboard/command_bar.rs index bf40931c1..c341a0242 100644 --- a/src/screen/dashboard/command_bar.rs +++ b/src/screen/dashboard/command_bar.rs @@ -250,7 +250,7 @@ impl Theme { fn list(config: &Config) -> Vec { Some(Self::OpenEditor) .into_iter() - .chain(config.themes.all.iter().cloned().map(Self::Switch)) + .chain(config.appearance.all.iter().cloned().map(Self::Switch)) .collect() } } diff --git a/src/widget/color_picker.rs b/src/widget/color_picker.rs index 37da13fbd..324b020fa 100644 --- a/src/widget/color_picker.rs +++ b/src/widget/color_picker.rs @@ -299,7 +299,7 @@ fn picker<'a, Message: 'a>( height: impl Into, handle_radius: f32, ) -> Element<'a, Message> { - let color = data::theme::to_hsva(color); + let color = data::appearance::theme::to_hsva(color); decorate(Space::new(width, height)) .state::>() @@ -329,7 +329,7 @@ fn picker<'a, Message: 'a>( picker.handle_from_cursor(position, bounds, handle_radius); let color = picker.color_at_handle(color, new_handle, bounds); - shell.publish((on_color)(data::theme::from_hsva(color))); + shell.publish((on_color)(data::appearance::theme::from_hsva(color))); *state = Some(new_handle); } @@ -341,7 +341,7 @@ fn picker<'a, Message: 'a>( if let Some(last_handle) = state.take() { let color = picker.color_at_handle(color, last_handle, bounds); - shell.publish((on_color)(data::theme::from_hsva(color))); + shell.publish((on_color)(data::appearance::theme::from_hsva(color))); } } iced::Event::Mouse(mouse::Event::CursorMoved { position }) @@ -367,7 +367,7 @@ fn picker<'a, Message: 'a>( let color = picker.color_at_handle(color, *last_handle, bounds); - shell.publish((on_color)(data::theme::from_hsva(color))); + shell.publish((on_color)(data::appearance::theme::from_hsva(color))); } } _ => {} @@ -447,7 +447,7 @@ fn picker<'a, Message: 'a>( border: Default::default(), shadow: Default::default(), }, - data::theme::from_hsva(color), + data::appearance::theme::from_hsva(color), ); }); diff --git a/src/widget/message_content.rs b/src/widget/message_content.rs index 037596ebb..33b2b66e9 100644 --- a/src/widget/message_content.rs +++ b/src/widget/message_content.rs @@ -1,4 +1,4 @@ -use data::theme::randomize_color; +use data::appearance::theme::randomize_color; use data::user::NickColor; use data::{message, Config}; use iced::widget::span;