🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2024-01-13 20:58:00.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-13 21:28:13.0 +00:00:00
commit
dc2edeb8639289ee7e094799892a46a6885d89d6 [patch]
tree
569f220dc79dfda6557bc5f02f61f52351d6fc47
parent
7b288167d76fcb7fe1be5c00b15eab388e88e086
download
dc2edeb8639289ee7e094799892a46a6885d89d6.tar.gz

Move to tracking master branch of iced



Diff

 Cargo.lock                             | 374 ++++++++++++++++++++--------------
 iced                                   |   2 +-
 shalom/src/magic/header_search.rs      | 129 +++++-------
 shalom/src/main.rs                     |   4 +-
 shalom/src/pages/room.rs               |   2 +-
 shalom/src/pages/room/listen.rs        |  32 +--
 shalom/src/widgets/blackhole_event.rs  |   5 +-
 shalom/src/widgets/cards/weather.rs    | 149 +++++++-------
 shalom/src/widgets/context_menu.rs     |  46 ++--
 shalom/src/widgets/forced_rounded.rs   |  27 +--
 shalom/src/widgets/image_background.rs |  40 ++--
 shalom/src/widgets/image_card.rs       |  46 ++--
 shalom/src/widgets/spinner.rs          |  22 +--
 13 files changed, 481 insertions(+), 397 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 16ababb..b5c66a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -384,7 +384,7 @@ dependencies = [
 "cocoa-foundation",
 "core-foundation",
 "core-graphics",
 "foreign-types",
 "foreign-types 0.3.2",
 "libc",
 "objc",
]
@@ -450,7 +450,7 @@ dependencies = [
 "bitflags 1.3.2",
 "core-foundation",
 "core-graphics-types",
 "foreign-types",
 "foreign-types 0.3.2",
 "libc",
]

@@ -467,16 +467,17 @@ dependencies = [

[[package]]
name = "cosmic-text"
version = "0.9.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0b68966c2543609f8d92f9d33ac3b719b2a67529b0c6c0b3e025637b477eef9"
checksum = "75acbfb314aeb4f5210d379af45ed1ec2c98c7f1790bf57b8a4c562ac0c51b71"
dependencies = [
 "aliasable",
 "fontdb 0.14.1",
 "fontdb 0.15.0",
 "libm",
 "log",
 "rangemap",
 "rustybuzz 0.8.0",
 "rustc-hash",
 "rustybuzz 0.11.0",
 "self_cell",
 "swash",
 "sys-locale",
 "unicode-bidi",
@@ -554,12 +555,12 @@ dependencies = [

[[package]]
name = "d3d12"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da"
checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20"
dependencies = [
 "bitflags 1.3.2",
 "libloading 0.7.4",
 "bitflags 2.4.1",
 "libloading 0.8.1",
 "winapi",
]

@@ -606,12 +607,6 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"

[[package]]
name = "data-url"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5"

[[package]]
name = "data-url"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
@@ -714,7 +709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "279d3efcc55e19917fff7ab3ddd6c14afb6a90881a0078465196fe2f99d08c56"
dependencies = [
 "bit_field",
 "flume",
 "flume 0.10.14",
 "half",
 "lebe",
 "miniz_oxide",
@@ -786,6 +781,18 @@ dependencies = [
]

[[package]]
name = "flume"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
dependencies = [
 "futures-core",
 "futures-sink",
 "nanorand",
 "spin",
]

[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -802,13 +809,13 @@ dependencies = [

[[package]]
name = "fontdb"
version = "0.14.1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e"
checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38"
dependencies = [
 "fontconfig-parser",
 "log",
 "memmap2 0.6.2",
 "memmap2 0.8.0",
 "slotmap",
 "tinyvec",
 "ttf-parser 0.19.2",
@@ -834,7 +841,28 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
 "foreign-types-shared",
 "foreign-types-shared 0.1.1",
]

[[package]]
name = "foreign-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
 "foreign-types-macros",
 "foreign-types-shared 0.3.1",
]

[[package]]
name = "foreign-types-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
 "proc-macro2",
 "quote",
 "syn 2.0.38",
]

[[package]]
@@ -844,6 +872,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"

[[package]]
name = "foreign-types-shared"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"

[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -992,6 +1026,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"

[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
 "khronos_api",
 "log",
 "xml-rs",
]

[[package]]
name = "glam"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -999,9 +1044,9 @@ checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"

[[package]]
name = "glow"
version = "0.12.3"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728"
checksum = "886c2a30b160c4c6fec8f987430c26b526b7988ca71f664e6a699ddf6f9601e4"
dependencies = [
 "js-sys",
 "slotmap",
@@ -1010,10 +1055,18 @@ dependencies = [
]

[[package]]
name = "glutin_wgl_sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
dependencies = [
 "gl_generator",
]

[[package]]
name = "glyphon"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e87caa7459145f5e5f167bf34db4532901404c679e62339fb712a0e3ccf722a"
source = "git+https://github.com/grovesNL/glyphon.git?rev=2caa9fc5e5923c1d827d177c3619cab7e9885b85#2caa9fc5e5923c1d827d177c3619cab7e9885b85"
dependencies = [
 "cosmic-text",
 "etagere",
@@ -1023,31 +1076,32 @@ dependencies = [

[[package]]
name = "gpu-alloc"
version = "0.5.4"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62"
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
dependencies = [
 "bitflags 1.3.2",
 "bitflags 2.4.1",
 "gpu-alloc-types",
]

[[package]]
name = "gpu-alloc-types"
version = "0.2.0"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5"
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
dependencies = [
 "bitflags 1.3.2",
 "bitflags 2.4.1",
]

[[package]]
name = "gpu-allocator"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8"
checksum = "40fe17c8a05d60c38c0a4e5a3c802f2f1ceb66b76c67d96ffb34bef0475a7fad"
dependencies = [
 "backtrace",
 "log",
 "presser",
 "thiserror",
 "winapi",
 "windows",
@@ -1267,7 +1321,7 @@ dependencies = [

[[package]]
name = "iced"
version = "0.10.0"
version = "0.12.0"
dependencies = [
 "iced_core",
 "iced_futures",
@@ -1280,19 +1334,21 @@ dependencies = [

[[package]]
name = "iced_core"
version = "0.10.0"
version = "0.12.0"
dependencies = [
 "bitflags 1.3.2",
 "instant",
 "log",
 "num-traits",
 "palette",
 "raw-window-handle",
 "thiserror",
 "twox-hash",
 "xxhash-rust",
]

[[package]]
name = "iced_futures"
version = "0.7.0"
version = "0.12.0"
dependencies = [
 "futures",
 "iced_core",
@@ -1304,10 +1360,11 @@ dependencies = [

[[package]]
name = "iced_graphics"
version = "0.9.0"
version = "0.12.0"
dependencies = [
 "bitflags 1.3.2",
 "bytemuck",
 "cosmic-text",
 "glam",
 "half",
 "iced_core",
@@ -1315,13 +1372,17 @@ dependencies = [
 "kamadak-exif",
 "log",
 "lyon_path",
 "once_cell",
 "raw-window-handle",
 "rustc-hash",
 "thiserror",
 "unicode-segmentation",
 "xxhash-rust",
]

[[package]]
name = "iced_renderer"
version = "0.1.0"
version = "0.12.0"
dependencies = [
 "iced_graphics",
 "iced_tiny_skia",
@@ -1333,7 +1394,7 @@ dependencies = [

[[package]]
name = "iced_runtime"
version = "0.1.1"
version = "0.12.0"
dependencies = [
 "iced_core",
 "iced_futures",
@@ -1342,7 +1403,7 @@ dependencies = [

[[package]]
name = "iced_style"
version = "0.9.0"
version = "0.12.0"
dependencies = [
 "iced_core",
 "once_cell",
@@ -1351,7 +1412,7 @@ dependencies = [

[[package]]
name = "iced_tiny_skia"
version = "0.1.0"
version = "0.12.0"
dependencies = [
 "bytemuck",
 "cosmic-text",
@@ -1362,13 +1423,13 @@ dependencies = [
 "resvg",
 "rustc-hash",
 "softbuffer",
 "tiny-skia 0.10.0",
 "twox-hash",
 "tiny-skia 0.11.3",
 "xxhash-rust",
]

[[package]]
name = "iced_wgpu"
version = "0.11.1"
version = "0.12.0"
dependencies = [
 "bitflags 1.3.2",
 "bytemuck",
@@ -1382,14 +1443,12 @@ dependencies = [
 "once_cell",
 "raw-window-handle",
 "resvg",
 "rustc-hash",
 "twox-hash",
 "wgpu",
]

[[package]]
name = "iced_widget"
version = "0.1.3"
version = "0.12.0"
dependencies = [
 "iced_renderer",
 "iced_runtime",
@@ -1403,14 +1462,14 @@ dependencies = [

[[package]]
name = "iced_winit"
version = "0.10.1"
version = "0.12.0"
dependencies = [
 "iced_graphics",
 "iced_runtime",
 "iced_style",
 "log",
 "raw-window-handle",
 "thiserror",
 "tracing",
 "web-sys",
 "winapi",
 "window_clipboard",
@@ -1603,16 +1662,22 @@ dependencies = [

[[package]]
name = "khronos-egl"
version = "4.1.0"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
dependencies = [
 "libc",
 "libloading 0.7.4",
 "libloading 0.8.1",
 "pkg-config",
]

[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"

[[package]]
name = "kurbo"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1777,9 +1842,9 @@ dependencies = [

[[package]]
name = "memmap2"
version = "0.6.2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872"
checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
dependencies = [
 "libc",
]
@@ -1822,16 +1887,17 @@ dependencies = [

[[package]]
name = "metal"
version = "0.24.0"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060"
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
dependencies = [
 "bitflags 1.3.2",
 "bitflags 2.4.1",
 "block",
 "core-graphics-types",
 "foreign-types",
 "foreign-types 0.5.0",
 "log",
 "objc",
 "paste",
]

[[package]]
@@ -1882,15 +1948,15 @@ checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b"

[[package]]
name = "naga"
version = "0.12.3"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbcc2e0513220fd2b598e6068608d4462db20322c0e77e47f6f488dfcfc279cb"
checksum = "ae585df4b6514cf8842ac0f1ab4992edc975892704835b549cf818dc0191249e"
dependencies = [
 "bit-set",
 "bitflags 1.3.2",
 "bitflags 2.4.1",
 "codespan-reporting",
 "hexf-parse",
 "indexmap 1.9.3",
 "indexmap 2.0.2",
 "log",
 "num-traits",
 "rustc-hash",
@@ -2282,6 +2348,12 @@ dependencies = [
]

[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"

[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2399,6 +2471,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"

[[package]]
name = "presser"
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"
@@ -2624,9 +2702,9 @@ dependencies = [

[[package]]
name = "resvg"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6554f47c38eca56827eea7f285c2a3018b4e12e0e195cc105833c008be338f1"
checksum = "cc7980f653f9a7db31acff916a262c3b78c562919263edea29bf41a056e20497"
dependencies = [
 "gif",
 "jpeg-decoder",
@@ -2634,9 +2712,9 @@ dependencies = [
 "pico-args",
 "png",
 "rgb",
 "svgtypes 0.11.0",
 "tiny-skia 0.10.0",
 "usvg 0.35.0",
 "svgtypes 0.12.0",
 "tiny-skia 0.11.3",
 "usvg 0.36.0",
]

[[package]]
@@ -2740,34 +2818,34 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"

[[package]]
name = "rustybuzz"
version = "0.7.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162bdf42e261bee271b3957691018634488084ef577dddeb6420a9684cab2a6a"
checksum = "71cd15fef9112a1f94ac64b58d1e4628192631ad6af4dc69997f995459c874e7"
dependencies = [
 "bitflags 1.3.2",
 "bytemuck",
 "smallvec",
 "ttf-parser 0.18.1",
 "ttf-parser 0.19.2",
 "unicode-bidi-mirroring",
 "unicode-ccc",
 "unicode-general-category",
 "unicode-properties",
 "unicode-script",
]

[[package]]
name = "rustybuzz"
version = "0.8.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82eea22c8f56965eeaf3a209b3d24508256c7b920fb3b6211b8ba0f7c0583250"
checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa"
dependencies = [
 "bitflags 1.3.2",
 "bytemuck",
 "libm",
 "smallvec",
 "ttf-parser 0.19.2",
 "ttf-parser 0.20.0",
 "unicode-bidi-mirroring",
 "unicode-ccc",
 "unicode-general-category",
 "unicode-properties",
 "unicode-script",
]

@@ -2861,6 +2939,12 @@ dependencies = [
]

[[package]]
name = "self_cell"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"

[[package]]
name = "serde"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3089,7 +3173,7 @@ dependencies = [
 "cocoa",
 "core-graphics",
 "fastrand",
 "foreign-types",
 "foreign-types 0.3.2",
 "log",
 "nix 0.26.4",
 "objc",
@@ -3201,9 +3285,9 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"

[[package]]
name = "svgtypes"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed4b0611e7f3277f68c0fa18e385d9e2d26923691379690039548f867cef02a7"
checksum = "d71499ff2d42f59d26edb21369a308ede691421f79ebc0f001e2b1fd3a7c9e52"
dependencies = [
 "kurbo",
 "siphasher",
@@ -3378,9 +3462,9 @@ dependencies = [

[[package]]
name = "tiny-skia"
version = "0.10.0"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7db11798945fa5c3e5490c794ccca7c6de86d3afdd54b4eb324109939c6f37bc"
checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d"
dependencies = [
 "arrayref",
 "arrayvec",
@@ -3388,7 +3472,7 @@ dependencies = [
 "cfg-if",
 "log",
 "png",
 "tiny-skia-path 0.10.0",
 "tiny-skia-path 0.11.3",
]

[[package]]
@@ -3404,17 +3488,6 @@ dependencies = [

[[package]]
name = "tiny-skia-path"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f60aa35c89ac2687ace1a2556eaaea68e8c0d47408a2e3e7f5c98a489e7281c"
dependencies = [
 "arrayref",
 "bytemuck",
 "strict-num",
]

[[package]]
name = "tiny-skia-path"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541"
@@ -3576,10 +3649,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
 "pin-project-lite",
 "tracing-attributes",
 "tracing-core",
]

[[package]]
name = "tracing-attributes"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn 2.0.38",
]

[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3596,12 +3681,6 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"

[[package]]
name = "ttf-parser"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633"

[[package]]
name = "ttf-parser"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1"
@@ -3633,17 +3712,6 @@ dependencies = [
]

[[package]]
name = "twox-hash"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
 "cfg-if",
 "rand",
 "static_assertions",
]

[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3668,12 +3736,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1"

[[package]]
name = "unicode-general-category"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7"

[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3755,16 +3817,16 @@ dependencies = [

[[package]]
name = "usvg"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d09ddfb0d93bf84824c09336d32e42f80961a9d1680832eb24fdf249ce11e6"
checksum = "c51daa774fe9ee5efcf7b4fec13019b8119cda764d9a8b5b06df02bb1445c656"
dependencies = [
 "base64",
 "log",
 "pico-args",
 "usvg-parser 0.35.0",
 "usvg-text-layout 0.35.0",
 "usvg-tree 0.35.0",
 "usvg-parser 0.36.0",
 "usvg-text-layout 0.36.0",
 "usvg-tree 0.36.0",
 "xmlwriter",
]

@@ -3785,11 +3847,11 @@ dependencies = [

[[package]]
name = "usvg-parser"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19bf93d230813599927d88557014e0908ecc3531666d47c634c6838bc8db408"
checksum = "45c88a5ffaa338f0e978ecf3d4e00d8f9f493e29bed0752e1a808a1db16afc40"
dependencies = [
 "data-url 0.2.0",
 "data-url",
 "flate2",
 "imagesize",
 "kurbo",
@@ -3797,8 +3859,8 @@ dependencies = [
 "roxmltree 0.18.1",
 "simplecss",
 "siphasher",
 "svgtypes 0.11.0",
 "usvg-tree 0.35.0",
 "svgtypes 0.12.0",
 "usvg-tree 0.36.0",
]

[[package]]
@@ -3807,7 +3869,7 @@ version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd4e3c291f45d152929a31f0f6c819245e2921bfd01e7bd91201a9af39a2bdc"
dependencies = [
 "data-url 0.3.1",
 "data-url",
 "flate2",
 "imagesize",
 "kurbo",
@@ -3821,18 +3883,18 @@ dependencies = [

[[package]]
name = "usvg-text-layout"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "035044604e89652c0a2959b8b356946997a52649ba6cade45928c2842376feb4"
checksum = "4d2374378cb7a3fb8f33894e0fdb8625e1bbc4f25312db8d91f862130b541593"
dependencies = [
 "fontdb 0.14.1",
 "fontdb 0.15.0",
 "kurbo",
 "log",
 "rustybuzz 0.7.0",
 "rustybuzz 0.10.0",
 "unicode-bidi",
 "unicode-script",
 "unicode-vo",
 "usvg-tree 0.35.0",
 "usvg-tree 0.36.0",
]

[[package]]
@@ -3853,14 +3915,14 @@ dependencies = [

[[package]]
name = "usvg-tree"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7939a7e4ed21cadb5d311d6339730681c3e24c3e81d60065be80e485d3fc8b92"
checksum = "6cacb0c5edeaf3e80e5afcf5b0d4004cc1d36318befc9a7c6606507e5d0f4062"
dependencies = [
 "rctree",
 "strict-num",
 "svgtypes 0.11.0",
 "tiny-skia-path 0.10.0",
 "svgtypes 0.12.0",
 "tiny-skia-path 0.11.3",
]

[[package]]
@@ -4136,12 +4198,13 @@ checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"

[[package]]
name = "wgpu"
version = "0.16.3"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "480c965c9306872eb6255fa55e4b4953be55a8b64d57e61d7ff840d3dcc051cd"
checksum = "30e7d227c9f961f2061c26f4cb0fbd4df0ef37e056edd0931783599d6c94ef24"
dependencies = [
 "arrayvec",
 "cfg-if",
 "flume 0.11.0",
 "js-sys",
 "log",
 "naga",
@@ -4160,9 +4223,9 @@ dependencies = [

[[package]]
name = "wgpu-core"
version = "0.16.1"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2"
checksum = "ef91c1d62d1e9e81c79e600131a258edf75c9531cbdbde09c44a011a47312726"
dependencies = [
 "arrayvec",
 "bit-vec",
@@ -4183,9 +4246,9 @@ dependencies = [

[[package]]
name = "wgpu-hal"
version = "0.16.2"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecb3258078e936deee14fd4e0febe1cfe9bbb5ffef165cb60218d2ee5eb4448"
checksum = "b84ecc802da3eb67b4cf3dd9ea6fe45bbb47ef13e6c49c5c3240868a9cc6cdd9"
dependencies = [
 "android_system_properties",
 "arrayvec",
@@ -4195,8 +4258,8 @@ dependencies = [
 "block",
 "core-graphics-types",
 "d3d12",
 "foreign-types",
 "glow",
 "glutin_wgl_sys",
 "gpu-alloc",
 "gpu-allocator",
 "gpu-descriptor",
@@ -4209,6 +4272,7 @@ dependencies = [
 "metal",
 "naga",
 "objc",
 "once_cell",
 "parking_lot 0.12.1",
 "profiling",
 "range-alloc",
@@ -4225,9 +4289,9 @@ dependencies = [

[[package]]
name = "wgpu-types"
version = "0.16.1"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a"
checksum = "0d5ed5f0edf0de351fe311c53304986315ce866f394a2e6df0c4b3c70774bcdd"
dependencies = [
 "bitflags 2.4.1",
 "js-sys",
@@ -4296,11 +4360,12 @@ dependencies = [

[[package]]
name = "windows"
version = "0.44.0"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
dependencies = [
 "windows-targets 0.42.2",
 "windows-core",
 "windows-targets 0.48.5",
]

[[package]]
@@ -4446,9 +4511,8 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

[[package]]
name = "winit"
version = "0.28.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94"
version = "0.28.6"
source = "git+https://github.com/iced-rs/winit.git?rev=c52db2045d0a2f1b8d9923870de1d4ab1994146e#c52db2045d0a2f1b8d9923870de1d4ab1994146e"
dependencies = [
 "android-activity",
 "bitflags 1.3.2",
@@ -4574,6 +4638,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"

[[package]]
name = "xxhash-rust"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61"

[[package]]
name = "yazi"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/iced b/iced
index f8a73b7..01e07d6 160000
--- a/iced
+++ b/iced
@@ -1 +1 @@
Subproject commit f8a73b7de909d72a90f9908b61fbdde88e0debcb
Subproject commit 01e07d6a2851d707cd98d9aa7f25f525343a4f71
diff --git a/shalom/src/magic/header_search.rs b/shalom/src/magic/header_search.rs
index 094dede..4e2ea41 100644
--- a/shalom/src/magic/header_search.rs
+++ b/shalom/src/magic/header_search.rs
@@ -43,12 +43,9 @@ where
        }));
    }

    let current_search_box_size = if open { BoxSize::Fill } else { BoxSize::Min };

    HeaderSearch {
        original_header: header.clone(),
        header,
        current_search_box_size,
        open,
        open_state_toggle,
        input: iced::widget::text_input("Search...", search_query)
@@ -62,17 +59,9 @@ where
    }
}

#[derive(Debug)]
pub enum BoxSize {
    Fill,
    Min,
    Fixed(Size),
}

pub struct HeaderSearch<'a, M> {
    original_header: Text<'a, Renderer>,
    header: Text<'a, Renderer>,
    current_search_box_size: BoxSize,
    input: Element<'a, M, Renderer>,
    search_icon: Element<'a, M, Renderer>,
    close_icon: Element<'a, M, Renderer>,
@@ -85,56 +74,70 @@ impl<'a, M> Widget<M, Renderer> for HeaderSearch<'a, M>
where
    M: Clone + 'a,
{
    fn width(&self) -> Length {
        Length::Fill
    fn size(&self) -> Size<Length> {
        Size::new(Length::Shrink, Length::Shrink)
    }

    fn height(&self) -> Length {
        Length::Shrink
    }

    fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node {
    fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
        let text_node = <iced::advanced::widget::Text<'_, Renderer> as Widget<M, Renderer>>::layout(
            &self.original_header,
            &mut tree.children[0],
            renderer,
            limits,
        );

        let size = limits.height(Length::Fixed(text_node.size().height)).max();

        let current_search_box_size = match self.current_search_box_size {
            BoxSize::Fixed(size) => size,
            BoxSize::Min => INITIAL_SEARCH_BOX_SIZE,
            BoxSize::Fill => Size {
        let state = tree.state.downcast_mut::<State>();
        match (&state, self.open) {
            (State::Open, false) => {
                *state = State::close();
            }
            (State::Closed, true) => {
                *state = State::open();
            }
            _ => {}
        }

        let current_search_box_size = match &state {
            State::Animate {
                search_box_size, ..
            } => Size {
                width: INITIAL_SEARCH_BOX_SIZE.width
                    + ((size.width - INITIAL_SEARCH_BOX_SIZE.width) * search_box_size.now()),
                ..INITIAL_SEARCH_BOX_SIZE
            },
            State::Closed => INITIAL_SEARCH_BOX_SIZE,
            State::Open => Size {
                width: limits.max().width,
                ..INITIAL_SEARCH_BOX_SIZE
            },
        };

        let search_icon_size = Size::new(36., 36.);
        let mut search_icon_node = Node::new(search_icon_size).translate(Vector {
            x: -(INITIAL_SEARCH_BOX_SIZE.width - search_icon_size.width) / 2.0,
            y: 0.0,
        });
        search_icon_node.align(Alignment::End, Alignment::Center, current_search_box_size);

        let mut search_input = self
        let search_icon_node = Node::new(search_icon_size)
            .translate(Vector {
                x: -(INITIAL_SEARCH_BOX_SIZE.width - search_icon_size.width) / 2.0,
                y: 0.0,
            })
            .align(Alignment::End, Alignment::Center, current_search_box_size);

        let search_input = self
            .input
            .as_widget()
            .layout(
                &mut tree.children[1],
                renderer,
                &limits
                    .width(current_search_box_size.width)
                    .pad([0, 20, 0, 60].into()),
                &limits.width(current_search_box_size.width).shrink([80, 20]),
            )
            .translate(Vector { x: 20.0, y: 0.0 });
        search_input.align(Alignment::Start, Alignment::Center, current_search_box_size);
            .translate(Vector { x: 20.0, y: 0.0 })
            .align(Alignment::Start, Alignment::Center, current_search_box_size);

        let mut search_box = Node::with_children(
        let search_box = Node::with_children(
            current_search_box_size,
            vec![search_icon_node, search_input],
        );
        search_box.align(Alignment::End, Alignment::Center, size);
        )
        .align(Alignment::End, Alignment::Center, size);

        Node::with_children(size, vec![text_node, search_box])
    }
@@ -157,7 +160,7 @@ where

        <iced::advanced::widget::Text<'_, Renderer> as Widget<M, Renderer>>::draw(
            &self.header,
            state,
            &state.children[0],
            renderer,
            theme,
            style,
@@ -166,7 +169,7 @@ where
            viewport,
        );

        let border_radius = if matches!(self.current_search_box_size, BoxSize::Fill) {
        let border_radius = if matches!(local_state, State::Open) {
            100.0 * (1.0 - self.dy_mult)
        } else {
            100.0
@@ -186,7 +189,7 @@ where

        if !matches!(local_state, State::Open) {
            self.search_icon.as_widget().draw(
                &state.children[1],
                &state.children[2],
                renderer,
                theme,
                style,
@@ -198,7 +201,7 @@ where

        if !matches!(local_state, State::Closed) {
            self.close_icon.as_widget().draw(
                &state.children[2],
                &state.children[3],
                renderer,
                theme,
                style,
@@ -210,7 +213,7 @@ where

        if !matches!(local_state, State::Closed) {
            self.input.as_widget().draw(
                &state.children[0],
                &state.children[1],
                renderer,
                theme,
                style,
@@ -267,7 +270,7 @@ where

                Status::Captured
            }
            iced::Event::Window(iced::window::Event::RedrawRequested(_)) => {
            iced::Event::Window(_, iced::window::Event::RedrawRequested(_)) => {
                let State::Animate {
                    last_draw,
                    next_state,
@@ -294,12 +297,6 @@ where
                    .size(60.0 - (2.0 * (1.0 - text_opacity.now())));

                search_box_size.advance_by(elapsed);
                self.current_search_box_size = BoxSize::Fixed(Size {
                    width: INITIAL_SEARCH_BOX_SIZE.width
                        + ((layout.bounds().width - INITIAL_SEARCH_BOX_SIZE.width)
                            * search_box_size.now()),
                    ..INITIAL_SEARCH_BOX_SIZE
                });

                search_icon.advance_by(elapsed);
                self.search_icon = Element::from(Icon::Search.canvas(Color {
@@ -315,16 +312,6 @@ where

                if text_opacity.finished() && search_box_size.finished() {
                    *state = std::mem::take(next_state);

                    match &state {
                        State::Open => {
                            self.current_search_box_size = BoxSize::Fill;
                        }
                        State::Closed => {
                            self.current_search_box_size = BoxSize::Min;
                        }
                        State::Animate { .. } => {}
                    }
                }

                shell.request_redraw(RedrawRequest::NextFrame);
@@ -336,7 +323,7 @@ where

        if status == Status::Ignored {
            self.input.as_widget_mut().on_event(
                &mut tree_state.children[0],
                &mut tree_state.children[1],
                event,
                layout.children().nth(1).unwrap().children().nth(1).unwrap(),
                cursor,
@@ -359,7 +346,7 @@ where
        renderer: &Renderer,
    ) -> Interaction {
        self.input.as_widget().mouse_interaction(
            &state.children[0],
            &state.children[1],
            layout.children().nth(1).unwrap().children().nth(1).unwrap(),
            cursor,
            viewport,
@@ -368,13 +355,11 @@ where
    }

    fn state(&self) -> iced::advanced::widget::tree::State {
        iced::advanced::widget::tree::State::new(
            if matches!(self.current_search_box_size, BoxSize::Fill) {
                State::Open
            } else {
                State::Closed
            },
        )
        iced::advanced::widget::tree::State::new(if self.open {
            State::Open
        } else {
            State::Closed
        })
    }

    fn tag(&self) -> Tag {
@@ -383,6 +368,7 @@ where

    fn children(&self) -> Vec<Tree> {
        vec![
            Tree::new(&Element::<'_, M, _>::from(self.header.clone())),
            Tree::new(&self.input),
            Tree::new(&self.search_icon),
            Tree::new(&self.close_icon),
@@ -390,7 +376,12 @@ where
    }

    fn diff(&self, tree: &mut Tree) {
        tree.diff_children(&[&self.input, &self.search_icon, &self.close_icon]);
        tree.diff_children(&[
            &Element::from(self.header.clone()),
            &self.input,
            &self.search_icon,
            &self.close_icon,
        ]);
    }
}

diff --git a/shalom/src/main.rs b/shalom/src/main.rs
index e7821f2..e723102 100644
--- a/shalom/src/main.rs
+++ b/shalom/src/main.rs
@@ -16,7 +16,7 @@ use std::sync::Arc;
use iced::{
    alignment::{Horizontal, Vertical},
    widget::{container, Column},
    window, Application, Command, Element, Length, Renderer, Settings, Subscription, Theme,
    window, Application, Command, Element, Length, Renderer, Settings, Size, Subscription, Theme,
};

use crate::{
@@ -340,7 +340,7 @@ fn main() {
    Shalom::run(Settings {
        antialiasing: true,
        window: window::Settings {
            min_size: Some((600, 600)),
            min_size: Some(Size::new(600.0, 600.0)),
            ..window::Settings::default()
        },
        ..Settings::default()
diff --git a/shalom/src/pages/room.rs b/shalom/src/pages/room.rs
index f80add8..9c97745 100644
--- a/shalom/src/pages/room.rs
+++ b/shalom/src/pages/room.rs
@@ -129,7 +129,7 @@ impl Room {

            (
                self.listen
                    .header_magic(header.clone(), padding_mult)
                    .header_magic(header, padding_mult)
                    .map(Message::Listen),
                padding_mult,
            )
diff --git a/shalom/src/pages/room/listen.rs b/shalom/src/pages/room/listen.rs
index 0d3df6e..3708673 100644
--- a/shalom/src/pages/room/listen.rs
+++ b/shalom/src/pages/room/listen.rs
@@ -5,7 +5,7 @@ use std::{borrow::Cow, convert::identity, iter, sync::Arc, time::Duration};
use iced::{
    futures::{future, future::Either, stream, stream::FuturesUnordered, FutureExt, StreamExt},
    subscription,
    widget::{container, image::Handle, lazy, Column, Text},
    widget::{container, image::Handle, Column, Text},
    Element, Length, Renderer, Subscription, Theme,
};
use itertools::Itertools;
@@ -57,25 +57,19 @@ impl Listen {
    }

    pub fn header_magic(&self, text: Text<'static>, dy_mult: f32) -> Element<'static, Message> {
        lazy(
            (self.search.clone(), dy_mult.to_be_bytes()),
            move |(search, dy_mult)| {
                let dy_mult = f32::from_be_bytes(*dy_mult);
                let (open, query) = if let Some(v) = search.search() {
                    (true, v)
                } else {
                    (false, "")
                };
        let (open, query) = if let Some(v) = self.search.search() {
            (true, v)
        } else {
            (false, "")
        };

                header_search(
                    Message::OnSearchTerm,
                    Message::OnSearchVisibleToggle,
                    open,
                    query,
                    text.clone(),
                    dy_mult,
                )
            },
        header_search(
            Message::OnSearchTerm,
            Message::OnSearchVisibleToggle,
            open,
            query,
            text,
            dy_mult,
        )
        .into()
    }
diff --git a/shalom/src/widgets/blackhole_event.rs b/shalom/src/widgets/blackhole_event.rs
index b70543e..740fe21 100644
--- a/shalom/src/widgets/blackhole_event.rs
+++ b/shalom/src/widgets/blackhole_event.rs
@@ -62,12 +62,13 @@ impl<Message, Renderer: iced::advanced::Renderer> overlay::Overlay<Message, Rend
    }

    fn layout(
        &self,
        &mut self,
        renderer: &Renderer,
        bounds: iced::Size,
        _position: iced::Point,
        translation: Vector,
    ) -> iced::advanced::layout::Node {
        self.overlay.layout(renderer, bounds, Vector::ZERO)
        self.overlay.layout(renderer, bounds, translation)
    }

    fn draw(
diff --git a/shalom/src/widgets/cards/weather.rs b/shalom/src/widgets/cards/weather.rs
index ee359aa..a7ac979 100644
--- a/shalom/src/widgets/cards/weather.rs
+++ b/shalom/src/widgets/cards/weather.rs
@@ -1,16 +1,18 @@
use iced::{
    advanced::{
        graphics::text::Paragraph,
        layout::{Limits, Node},
        renderer::{Quad, Style},
        svg::Renderer as SvgRenderer,
        text::{LineHeight, Renderer as TextRenderer, Shaping},
        widget::Tree,
        Layout, Renderer as AdvancedRenderer, Text, Widget,
        text::{LineHeight, Shaping},
        widget::{tree::Tag, Tree},
        Layout, Renderer as AdvancedRenderer, Widget,
    },
    alignment::{Horizontal, Vertical},
    font::Weight,
    gradient::Linear,
    mouse::Cursor,
    widget::{text, text::Appearance},
    Alignment, Background, Color, Degrees, Element, Font, Gradient, Length, Rectangle, Renderer,
    Size, Theme,
};
@@ -47,54 +49,62 @@ impl<M> WeatherCard<M> {
}

impl<M: Clone> Widget<M, Renderer> for WeatherCard<M> {
    fn width(&self) -> Length {
        Length::Fixed(192.)
    fn size(&self) -> Size<Length> {
        Size::new(Length::Fixed(192.0), Length::Fixed(192.0))
    }

    fn height(&self) -> Length {
        Length::Fixed(192.)
    }

    fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node {
        let padding = 16.into();

    fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
        let limits = limits
            .height(self.height())
            .width(self.width())
            .pad(padding);
        let container_size = limits.resolve(Size::ZERO);

        let mut header_node = Node::new(renderer.measure(
            .height(self.size().height)
            .width(self.size().width)
            .shrink([32, 32]);
        let container_size = limits.resolve(self.size().width, self.size().height, Size::ZERO);

        let local_state = tree.state.downcast_mut::<State>();
        let header_node = text::layout(
            &mut local_state.header,
            renderer,
            &limits,
            Length::Shrink,
            Length::Shrink,
            &self.build_temperature(),
            42.,
            LineHeight::default(),
            Font {
            Some(42.0.into()),
            Some(Font {
                weight: Weight::Normal,
                ..Font::with_name("Helvetica Neue")
            },
            container_size,
            }),
            Horizontal::Left,
            Vertical::Top,
            Shaping::Basic,
        ));
        header_node.move_to([padding.top, padding.left].into());
        header_node.align(Alignment::Start, Alignment::Start, container_size);
        )
        .move_to([16., 16.])
        .align(Alignment::Start, Alignment::Start, container_size);

        let mut icon_node =
            Node::new(Size::new(16., 16.)).translate([padding.left, -padding.bottom - 32.].into());
        icon_node.align(Alignment::Start, Alignment::End, container_size);
        let icon_node = Node::new(Size::new(16., 16.)).translate([16., -48.]).align(
            Alignment::Start,
            Alignment::End,
            container_size,
        );

        let mut conditions_node = Node::new(renderer.measure(
        let conditions_node = text::layout(
            &mut local_state.conditions,
            renderer,
            &limits,
            Length::Shrink,
            Length::Shrink,
            &self.build_conditions(),
            12.,
            LineHeight::default(),
            Font {
            Some(12.0.into()),
            Some(Font {
                weight: Weight::Bold,
                ..Font::with_name("Helvetica Neue")
            },
            container_size,
            }),
            Horizontal::Left,
            Vertical::Bottom,
            Shaping::Basic,
        ))
        .translate([padding.left, -padding.bottom].into());
        conditions_node.align(Alignment::Start, Alignment::End, container_size);
        )
        .move_to([16., -16.]);

        Node::with_children(
            container_size,
@@ -104,16 +114,17 @@ impl<M: Clone> Widget<M, Renderer> for WeatherCard<M> {

    fn draw(
        &self,
        _state: &Tree,
        state: &Tree,
        renderer: &mut Renderer,
        _theme: &Theme,
        _style: &Style,
        style: &Style,
        layout: Layout<'_>,
        _cursor: Cursor,
        _viewport: &Rectangle,
        viewport: &Rectangle,
    ) {
        // TODO: get sunrise/sunset from somewhere reasonable
        let day_time = matches!(OffsetDateTime::now_utc().hour(), 5..=19);
        let local_state = state.state.downcast_ref::<State>();

        let gradient = if day_time {
            Linear::new(Degrees(90.))
@@ -137,41 +148,49 @@ impl<M: Clone> Widget<M, Renderer> for WeatherCard<M> {

        let mut children = layout.children();

        renderer.fill_text(Text {
            content: &self.build_temperature(),
            bounds: children.next().unwrap().bounds(),
            size: 42.,
            line_height: LineHeight::default(),
            color: Color::WHITE,
            font: Font {
                weight: Weight::Normal,
                ..Font::with_name("Helvetica Neue")
        let header_layout = children.next().unwrap();
        text::draw(
            renderer,
            style,
            header_layout,
            &local_state.header,
            Appearance {
                color: Some(Color::WHITE),
            },
            horizontal_alignment: Horizontal::Left,
            vertical_alignment: Vertical::Top,
            shaping: Shaping::Basic,
        });
            viewport,
        );

        let icon_bounds = children.next().unwrap().bounds();
        if let Some(icon) = self.current_weather.weather_condition().icon(day_time) {
            renderer.draw(icon.handle(), None, icon_bounds);
        }

        renderer.fill_text(Text {
            content: &self.build_conditions(),
            bounds: children.next().unwrap().bounds(),
            size: 12.,
            line_height: LineHeight::default(),
            color: Color::WHITE,
            font: Font {
                weight: Weight::Bold,
                ..Font::with_name("Helvetica Neue")
        let conditions_layout = children.next().unwrap();
        text::draw(
            renderer,
            style,
            conditions_layout,
            &local_state.conditions,
            Appearance {
                color: Some(Color::WHITE),
            },
            horizontal_alignment: Horizontal::Left,
            vertical_alignment: Vertical::Top,
            shaping: Shaping::Basic,
        });
            viewport,
        );
    }

    fn state(&self) -> iced::advanced::widget::tree::State {
        iced::advanced::widget::tree::State::new(State::default())
    }

    fn tag(&self) -> Tag {
        Tag::of::<State>()
    }
}

#[derive(Default)]
pub struct State {
    header: text::State<Paragraph>,
    conditions: text::State<Paragraph>,
}

impl<'a, M> From<WeatherCard<M>> for Element<'a, M>
diff --git a/shalom/src/widgets/context_menu.rs b/shalom/src/widgets/context_menu.rs
index a43a8ee..e1494bf 100644
--- a/shalom/src/widgets/context_menu.rs
+++ b/shalom/src/widgets/context_menu.rs
@@ -17,7 +17,7 @@ use iced::{
    window,
    window::RedrawRequest,
    Alignment, BorderRadius, Color, Element, Event, Length, Point, Rectangle, Renderer, Size,
    Theme,
    Theme, Vector,
};
use keyframe::{functions::EaseOutQuint, keyframes, AnimationSequence};

@@ -50,16 +50,12 @@ impl<'a, M> ContextMenu<'a, M> {
}

impl<'a, M: Clone> Widget<M, Renderer> for ContextMenu<'a, M> {
    fn width(&self) -> Length {
        self.base.as_widget().width()
    fn size(&self) -> Size<Length> {
        self.base.as_widget().size()
    }

    fn height(&self) -> Length {
        self.base.as_widget().height()
    }

    fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node {
        self.base.as_widget().layout(renderer, limits)
    fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
        self.base.as_widget().layout(tree, renderer, limits)
    }

    fn draw(
@@ -303,22 +299,28 @@ impl<'a, 'b, M: Clone> Overlay<'a, 'b, M> {
}

impl<'a, 'b, M: Clone> overlay::Overlay<M, Renderer> for Overlay<'a, 'b, M> {
    fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> Node {
    fn layout(
        &mut self,
        renderer: &Renderer,
        bounds: Size,
        position: Point,
        _translation: Vector,
    ) -> Node {
        let limits = Limits::new(Size::ZERO, bounds)
            .width(Length::Fill)
            .height(Length::Fill);

        let mut child = self.content.as_widget().layout(renderer, &limits);
        child.align(Alignment::Start, Alignment::Start, limits.max());
        child.move_to(Point {
            x: 0.0,
            y: bounds.height - self.state.height,
        });

        let mut node = Node::with_children(bounds, vec![child]);
        node.move_to(position);

        node
        let child = self
            .content
            .as_widget()
            .layout(self.tree, renderer, &limits)
            .align(Alignment::Start, Alignment::Start, limits.max())
            .move_to(Point {
                x: 0.0,
                y: bounds.height - self.state.height,
            });

        Node::with_children(bounds, vec![child]).move_to(position)
    }

    fn draw(
@@ -421,7 +423,7 @@ impl<'a, 'b, M: Clone> overlay::Overlay<M, Renderer> for Overlay<'a, 'b, M> {
                    shell.request_redraw(RedrawRequest::NextFrame);
                }
            }
        } else if let Event::Window(window::Event::RedrawRequested(_)) = &event {
        } else if let Event::Window(_, window::Event::RedrawRequested(_)) = &event {
            self.handle_redraw(shell, cursor);
        }

diff --git a/shalom/src/widgets/forced_rounded.rs b/shalom/src/widgets/forced_rounded.rs
index 7e2790f..8b91539 100644
--- a/shalom/src/widgets/forced_rounded.rs
+++ b/shalom/src/widgets/forced_rounded.rs
@@ -12,7 +12,7 @@ use iced::{
    },
    event::Status,
    mouse::{Cursor, Interaction},
    Background, Color, Event, Length, Point, Rectangle, Size,
    Background, Color, Event, Length, Point, Rectangle, Size, Vector,
};

pub fn forced_rounded<'a, M: 'a, R>(
@@ -28,16 +28,12 @@ pub struct ForcedRounded<'a, M, R> {
}

impl<'a, M, R: Renderer> Widget<M, R> for ForcedRounded<'a, M, R> {
    fn width(&self) -> Length {
        self.element.as_widget().width()
    fn size(&self) -> Size<Length> {
        self.element.as_widget().size()
    }

    fn height(&self) -> Length {
        self.element.as_widget().height()
    }

    fn layout(&self, renderer: &R, limits: &Limits) -> Node {
        self.element.as_widget().layout(renderer, limits)
    fn layout(&self, tree: &mut Tree, renderer: &R, limits: &Limits) -> Node {
        self.element.as_widget().layout(tree, renderer, limits)
    }

    fn draw(
@@ -144,11 +140,14 @@ pub struct Overlay {
}

impl<M, R: Renderer> overlay::Overlay<M, R> for Overlay {
    fn layout(&self, _renderer: &R, _bounds: Size, position: Point) -> Node {
        let mut node = Node::new(self.size);
        node.move_to(self.position.unwrap_or(position));

        node
    fn layout(
        &mut self,
        _renderer: &R,
        _bounds: Size,
        position: Point,
        _translation: Vector,
    ) -> Node {
        Node::new(self.size).move_to(self.position.unwrap_or(position))
    }

    fn draw(
diff --git a/shalom/src/widgets/image_background.rs b/shalom/src/widgets/image_background.rs
index 13e65f5..4e8fa53 100644
--- a/shalom/src/widgets/image_background.rs
+++ b/shalom/src/widgets/image_background.rs
@@ -9,7 +9,7 @@ use iced::{
    },
    event::Status,
    mouse::{Cursor, Interaction},
    widget::image,
    widget::{image, image::FilterMethod},
    Alignment, ContentFit, Element, Event, Length, Point, Rectangle, Size, Vector,
};

@@ -53,17 +53,13 @@ impl<
            + iced::advanced::image::Renderer<Handle = iced::advanced::image::Handle>,
    > Widget<M, R> for ImageBackground<'a, M, R>
{
    fn width(&self) -> Length {
        self.width
    fn size(&self) -> Size<Length> {
        Size::new(self.width, self.height)
    }

    fn height(&self) -> Length {
        self.height
    }

    fn layout(&self, _renderer: &R, limits: &Limits) -> Node {
    fn layout(&self, _state: &mut Tree, _renderer: &R, limits: &Limits) -> Node {
        let limits = limits.width(self.width).height(self.height);
        let size = limits.resolve(Size::ZERO);
        let size = limits.resolve(self.width, self.height, Size::ZERO);

        Node::new(size)
    }
@@ -102,7 +98,11 @@ impl<
                ..bounds
            };

            renderer.draw(self.image_handle.clone(), drawing_bounds + offset);
            renderer.draw(
                self.image_handle.clone(),
                FilterMethod::Linear,
                drawing_bounds + offset,
            );
        });
    }

@@ -140,18 +140,24 @@ struct Overlay<'a, 'b, M, R> {
impl<'a, 'b, M: Clone, R: iced::advanced::Renderer> overlay::Overlay<M, R>
    for Overlay<'a, 'b, M, R>
{
    fn layout(&self, renderer: &R, _bounds: Size, position: Point) -> Node {
    fn layout(
        &mut self,
        renderer: &R,
        _bounds: Size,
        position: Point,
        _translation: Vector,
    ) -> Node {
        let limits = Limits::new(Size::ZERO, self.size)
            .width(Length::Fill)
            .height(Length::Fill);

        let mut child = self.el.as_widget().layout(renderer, &limits);
        child.align(Alignment::Start, Alignment::Start, limits.max());

        let mut node = Node::with_children(self.size, vec![child]);
        node.move_to(position);
        let child = self
            .el
            .as_widget()
            .layout(self.tree, renderer, &limits)
            .align(Alignment::Start, Alignment::Start, limits.max());

        node
        Node::with_children(self.size, vec![child]).move_to(position)
    }

    fn draw(
diff --git a/shalom/src/widgets/image_card.rs b/shalom/src/widgets/image_card.rs
index 2f82ea5..bcfd03e 100644
--- a/shalom/src/widgets/image_card.rs
+++ b/shalom/src/widgets/image_card.rs
@@ -14,7 +14,7 @@ use iced::{
    mouse::{Button, Cursor},
    theme::Text,
    touch,
    widget::{image, text},
    widget::{image, image::FilterMethod, text},
    Alignment, Background, Color, ContentFit, Degrees, Element, Event, Font, Gradient, Length,
    Point, Rectangle, Renderer, Size, Theme, Vector,
};
@@ -55,17 +55,13 @@ impl<'a, M> ImageCard<'a, M> {
}

impl<'a, M: Clone> Widget<M, Renderer> for ImageCard<'a, M> {
    fn width(&self) -> Length {
        self.width
    fn size(&self) -> Size<Length> {
        Size::new(self.width, self.height)
    }

    fn height(&self) -> Length {
        self.height
    }

    fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node {
    fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node {
        let limits = limits.width(self.width).height(self.height);
        let size = limits.resolve(Size::ZERO);
        let size = limits.resolve(self.width, self.height, Size::ZERO);

        Node::new(size)
    }
@@ -104,7 +100,11 @@ impl<'a, M: Clone> Widget<M, Renderer> for ImageCard<'a, M> {
                ..bounds
            };

            renderer.draw(self.image_handle.clone(), drawing_bounds + offset);
            renderer.draw(
                self.image_handle.clone(),
                FilterMethod::Linear,
                drawing_bounds + offset,
            );
        });
    }

@@ -154,16 +154,22 @@ struct Overlay<'a, 'b, M> {
}

impl<'a, 'b, M: Clone> overlay::Overlay<M, Renderer> for Overlay<'a, 'b, M> {
    fn layout(&self, renderer: &Renderer, _bounds: Size, position: Point) -> Node {
        let limits = Limits::new(Size::ZERO, self.size).pad([0, 0, 10, 0].into());

        let mut child = self.text.as_widget().layout(renderer, &limits);
        child.align(Alignment::Center, Alignment::End, limits.max());

        let mut node = Node::with_children(self.size, vec![child]);
        node.move_to(position);

        node
    fn layout(
        &mut self,
        renderer: &Renderer,
        _bounds: Size,
        position: Point,
        _translation: Vector,
    ) -> Node {
        let limits = Limits::new(Size::ZERO, self.size).shrink([0, 10]);

        let child = self
            .text
            .as_widget()
            .layout(self.tree, renderer, &limits)
            .align(Alignment::Center, Alignment::End, limits.max());

        Node::with_children(self.size, vec![child]).move_to(position)
    }

    fn draw(
diff --git a/shalom/src/widgets/spinner.rs b/shalom/src/widgets/spinner.rs
index afaf917..c85a46f 100644
--- a/shalom/src/widgets/spinner.rs
+++ b/shalom/src/widgets/spinner.rs
@@ -92,20 +92,16 @@ impl CupertinoSpinner {
}

impl<Message, Theme> Widget<Message, Renderer<Theme>> for CupertinoSpinner {
    fn width(&self) -> Length {
        self.width
    }
    fn height(&self) -> Length {
        self.height
    fn size(&self) -> Size<Length> {
        Size::new(self.width, self.height)
    }

    fn layout(&self, _renderer: &Renderer<Theme>, limits: &Limits) -> Node {
        Node::new(
            limits
                .width(self.width)
                .height(self.height)
                .resolve(Size::new(f32::INFINITY, f32::INFINITY)),
        )
    fn layout(&self, _state: &mut Tree, _renderer: &Renderer<Theme>, limits: &Limits) -> Node {
        Node::new(limits.resolve(
            self.width,
            self.height,
            Size::new(f32::INFINITY, f32::INFINITY),
        ))
    }

    fn draw(
@@ -189,7 +185,7 @@ impl<Message, Theme> Widget<Message, Renderer<Theme>> for CupertinoSpinner {
    ) -> event::Status {
        let state: &mut SpinnerState = state.state.downcast_mut::<SpinnerState>();

        if let Event::Window(window::Event::RedrawRequested(_now)) = &event {
        if let Event::Window(_, window::Event::RedrawRequested(_now)) = &event {
            state.spinner.clear();
            shell.request_redraw(window::RedrawRequest::NextFrame);
            return event::Status::Captured;