diff --git a/Cargo.lock b/Cargo.lock index 0e0a49e0..cfc881d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,9 +166,9 @@ checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "almost" @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "apply" @@ -445,8 +445,8 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.1", - "futures-lite 2.4.0", + "fastrand 2.2.0", + "futures-lite 2.5.0", "slab", ] @@ -458,7 +458,7 @@ checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" dependencies = [ "async-lock 3.4.0", "blocking", - "futures-lite 2.4.0", + "futures-lite 2.5.0", ] [[package]] @@ -483,18 +483,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.4.0", + "futures-lite 2.5.0", "parking", - "polling 3.7.3", - "rustix 0.38.39", + "polling 3.7.4", + "rustix 0.38.40", "slab", "tracing", "windows-sys 0.59.0", @@ -526,9 +526,9 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" dependencies = [ - "async-io 2.3.4", + "async-io 2.4.0", "blocking", - "futures-lite 2.4.0", + "futures-lite 2.5.0", ] [[package]] @@ -544,7 +544,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.39", + "rustix 0.38.40", "windows-sys 0.48.0", ] @@ -555,15 +555,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", - "async-io 2.3.4", + "async-io 2.4.0", "async-lock 3.4.0", "async-signal", "async-task", "blocking", "cfg-if", "event-listener 5.3.1", - "futures-lite 2.4.0", - "rustix 0.38.39", + "futures-lite 2.5.0", + "rustix 0.38.40", "tracing", ] @@ -584,13 +584,13 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.4", + "async-io 2.4.0", "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.39", + "rustix 0.38.40", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -624,7 +624,7 @@ name = "atomicwrites" version = "0.4.2" source = "git+https://github.com/jackpot51/rust-atomicwrites#043ab4859d53ffd3d55334685303d8df39c9f768" dependencies = [ - "rustix 0.38.39", + "rustix 0.38.40", "tempfile", "windows-sys 0.48.0", ] @@ -850,7 +850,7 @@ dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite 2.4.0", + "futures-lite 2.5.0", "piper", ] @@ -867,9 +867,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +checksum = "f5327f6c99920069d1fe374aa743be1af0031dea9f250852cdf1ae6a0861ee24" dependencies = [ "borsh-derive", "cfg_aliases 0.2.1", @@ -877,16 +877,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +checksum = "10aedd8f1a81a8aafbfde924b0e3061cd6fedd6f6bbcfc6a76e6fd426d7bfe26" dependencies = [ "once_cell", "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 2.0.87", - "syn_derive", ] [[package]] @@ -996,8 +995,8 @@ checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "bitflags 2.6.0", "log", - "polling 3.7.3", - "rustix 0.38.39", + "polling 3.7.4", + "rustix 0.38.40", "slab", "thiserror", ] @@ -1009,16 +1008,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ "calloop", - "rustix 0.38.39", + "rustix 0.38.40", "wayland-backend", "wayland-client", ] [[package]] name = "cc" -version = "1.1.36" +version = "1.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" dependencies = [ "jobserver", "libc", @@ -1462,7 +1461,7 @@ dependencies = [ [[package]] name = "cosmic-comp-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-comp#90883c6ab12533da08a31da338881c38aa773634" +source = "git+https://github.com/pop-os/cosmic-comp#641bb75eb1a6449752d14b9776381a823999b85e" dependencies = [ "cosmic-config", "input", @@ -1472,7 +1471,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1494,7 +1493,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "quote", "syn 1.0.109", @@ -1526,7 +1525,7 @@ dependencies = [ [[package]] name = "cosmic-panel-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#43c3ac30eb8e6e8032cb049e352ce07a525b321c" +source = "git+https://github.com/pop-os/cosmic-panel#d0d79726307405cdf2d879d3fb6162a8b2f5996a" dependencies = [ "anyhow", "cosmic-config", @@ -1558,7 +1557,7 @@ version = "0.1.0" source = "git+https://github.com/pop-os/cosmic-randr#8d0938029f223016fde11aef4c5233ddbfdb2796" dependencies = [ "cosmic-protocols", - "futures-lite 2.4.0", + "futures-lite 2.5.0", "indexmap 2.6.0", "tachyonix", "thiserror", @@ -1609,6 +1608,7 @@ dependencies = [ "dirs", "downcast-rs", "eyre", + "fixed_decimal", "fontdb 0.16.2", "freedesktop-desktop-entry", "futures", @@ -1622,6 +1622,7 @@ dependencies = [ "itertools 0.13.0", "itoa", "libcosmic", + "locale1", "notify", "once_cell", "regex", @@ -1633,6 +1634,7 @@ dependencies = [ "slotmap", "static_init", "sunrise", + "system", "tachyonix", "timedate-zbus", "tokio", @@ -1694,7 +1696,7 @@ dependencies = [ "libpulse-binding", "log", "pipewire", - "rustix 0.38.39", + "rustix 0.38.40", "secure-string", "thiserror", "tokio", @@ -1727,7 +1729,7 @@ dependencies = [ "eyre", "fast_image_resize", "freedesktop-icons", - "futures-lite 2.4.0", + "futures-lite 2.5.0", "futures-util", "image 0.25.5", "infer", @@ -1739,7 +1741,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.12.1" -source = "git+https://github.com/pop-os/cosmic-text.git#4fe90bb6126c22f589b46768d7754d65ae300c5e" +source = "git+https://github.com/pop-os/cosmic-text.git#1f4065c1c3399efad58841082212f7c039b58480" dependencies = [ "bitflags 2.6.0", "fontdb 0.16.2", @@ -1762,7 +1764,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "almost", "cosmic-config", @@ -1785,6 +1787,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -2155,7 +2172,7 @@ dependencies = [ "bytemuck", "drm-ffi", "drm-fourcc", - "rustix 0.38.39", + "rustix 0.38.40", ] [[package]] @@ -2165,7 +2182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6" dependencies = [ "drm-sys", - "rustix 0.38.39", + "rustix 0.38.40", ] [[package]] @@ -2351,9 +2368,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fdeflate" @@ -2589,6 +2606,16 @@ dependencies = [ "xdg", ] +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", + "tokio", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -2670,11 +2697,11 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.1.1", + "fastrand 2.2.0", "futures-core", "futures-io", "parking", @@ -2846,6 +2873,18 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "gpt" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69" +dependencies = [ + "bitflags 2.6.0", + "crc", + "log", + "uuid", +] + [[package]] name = "gpu-alloc" version = "0.6.0" @@ -3110,7 +3149,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "dnd", "iced_accessibility", @@ -3128,7 +3167,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "accesskit", "accesskit_winit", @@ -3137,7 +3176,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "bitflags 2.6.0", "bytes", @@ -3162,7 +3201,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "futures", "iced_core", @@ -3188,7 +3227,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "bitflags 2.6.0", "bytemuck", @@ -3210,7 +3249,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -3222,7 +3261,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "bytes", "dnd", @@ -3238,7 +3277,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "bytemuck", "cosmic-text", @@ -3254,7 +3293,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "as-raw-xcb-connection", "bitflags 2.6.0", @@ -3270,7 +3309,7 @@ dependencies = [ "raw-window-handle", "resvg", "rustc-hash 2.0.0", - "rustix 0.38.39", + "rustix 0.38.40", "smithay-client-toolkit", "thiserror", "tiny-xlib", @@ -3285,7 +3324,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "dnd", "iced_accessibility", @@ -3304,7 +3343,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "dnd", "iced_accessibility", @@ -4280,14 +4319,14 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#9825e730bc1f8535a763ce054f72fba587e4d12b" +source = "git+https://github.com/pop-os/libcosmic#01bd999d281cef270742391fdd5f5addf0bc16f1" dependencies = [ "apply", "ashpd 0.9.2", @@ -4328,13 +4367,12 @@ dependencies = [ [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] @@ -4459,6 +4497,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +[[package]] +name = "locale1" +version = "0.1.0" +source = "git+https://github.com/pop-os/dbus-settings-bindings#62100129240d164e39fff16bda34faad520936de" +dependencies = [ + "zbus 4.4.0", +] + [[package]] name = "locale_config" version = "0.3.0" @@ -5534,7 +5580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.1", + "fastrand 2.2.0", "futures-io", ] @@ -5603,15 +5649,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.39", + "rustix 0.38.40", "tracing", "windows-sys 0.59.0", ] @@ -5662,29 +5708,6 @@ dependencies = [ "toml_edit 0.22.22", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -5739,7 +5762,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix 0.38.39", + "rustix 0.38.40", ] [[package]] @@ -6004,7 +6027,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -6028,9 +6051,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -6253,9 +6276,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -6590,7 +6613,7 @@ dependencies = [ "log", "memmap2 0.9.5", "pkg-config", - "rustix 0.38.39", + "rustix 0.38.40", "thiserror", "wayland-backend", "wayland-client", @@ -6654,7 +6677,7 @@ dependencies = [ "cocoa", "core-graphics", "drm", - "fastrand 2.1.1", + "fastrand 2.2.0", "foreign-types", "js-sys", "log", @@ -6662,7 +6685,7 @@ dependencies = [ "objc", "raw-window-handle", "redox_syscall 0.4.1", - "rustix 0.38.39", + "rustix 0.38.40", "tiny-xlib", "wasm-bindgen", "wayland-backend", @@ -6752,6 +6775,16 @@ dependencies = [ "chrono", ] +[[package]] +name = "superblock" +version = "0.1.0" +source = "git+https://github.com/serpent-os/blsforme.git#77c30adbfbc09cb54cd9f781fb7e5e5a563de3bf" +dependencies = [ + "log", + "thiserror", + "uuid", +] + [[package]] name = "svg_fmt" version = "0.4.4" @@ -6801,18 +6834,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "synstructure" version = "0.13.1" @@ -6847,6 +6868,22 @@ dependencies = [ "windows 0.57.0", ] +[[package]] +name = "system" +version = "0.1.0" +source = "git+https://github.com/serpent-os/lichen#d09e89773d5051a3c6603cd5ef7444183dd2451c" +dependencies = [ + "fs-err", + "futures", + "gpt", + "serde", + "serde_json", + "superblock", + "thiserror", + "tokio", + "tokio-stream", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -6904,14 +6941,14 @@ checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", - "fastrand 2.1.1", + "fastrand 2.2.0", "once_cell", - "rustix 0.38.39", + "rustix 0.38.40", "windows-sys 0.59.0", ] @@ -6932,18 +6969,18 @@ checksum = "7f1835c76a9d443834c04539860f3ce46b9d93ef8c260057f939e967ca81180a" [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -7085,14 +7122,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", "mio 1.0.2", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", @@ -7121,6 +7159,20 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] @@ -7486,6 +7538,9 @@ name = "uuid" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", +] [[package]] name = "v_frame" @@ -7628,7 +7683,7 @@ checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", - "rustix 0.38.39", + "rustix 0.38.40", "scoped-tls", "smallvec", "wayland-sys", @@ -7641,7 +7696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ "bitflags 2.6.0", - "rustix 0.38.39", + "rustix 0.38.40", "wayland-backend", "wayland-scanner", ] @@ -7663,7 +7718,7 @@ version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" dependencies = [ - "rustix 0.38.39", + "rustix 0.38.40", "wayland-client", "xcursor", ] @@ -7728,7 +7783,7 @@ dependencies = [ "bitflags 2.6.0", "downcast-rs", "io-lifetimes 2.0.3", - "rustix 0.38.39", + "rustix 0.38.40", "wayland-backend", "wayland-scanner", ] @@ -8299,7 +8354,7 @@ dependencies = [ "pin-project", "raw-window-handle", "redox_syscall 0.4.1", - "rustix 0.38.39", + "rustix 0.38.40", "sctk-adwaita", "smithay-client-toolkit", "smol_str", @@ -8383,7 +8438,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix 0.38.39", + "rustix 0.38.40", "x11rb-protocol", ] @@ -8418,7 +8473,7 @@ dependencies = [ [[package]] name = "xdg-shell-wrapper-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#43c3ac30eb8e6e8032cb049e352ce07a525b321c" +source = "git+https://github.com/pop-os/cosmic-panel#d0d79726307405cdf2d879d3fb6162a8b2f5996a" dependencies = [ "serde", "wayland-protocols-wlr", @@ -8469,9 +8524,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" [[package]] name = "xmlwriter" @@ -8569,7 +8624,7 @@ dependencies = [ "async-broadcast 0.7.1", "async-executor", "async-fs", - "async-io 2.3.4", + "async-io 2.4.0", "async-lock 3.4.0", "async-process 2.3.0", "async-recursion", diff --git a/cosmic-settings/Cargo.toml b/cosmic-settings/Cargo.toml index 9c578a40..cc2f7ea3 100644 --- a/cosmic-settings/Cargo.toml +++ b/cosmic-settings/Cargo.toml @@ -7,7 +7,9 @@ license = "GPL-3.0-only" [dependencies] anyhow = "1.0" as-result = "0.2.1" -ashpd = { version = "0.9", default-features = false, features = ["tokio"], optional = true } +ashpd = { version = "0.9", default-features = false, features = [ + "tokio", +], optional = true } async-channel = "2.3.1" chrono = "0.4.38" clap = { version = "4.5.17", features = ["derive"] } @@ -39,6 +41,7 @@ indexmap = "2.5.0" itertools = "0.13.0" itoa = "1.0.11" libcosmic.workspace = true +locale1 = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true } notify = "6.1.1" once_cell = "1.19.0" regex = "1.10.6" @@ -63,6 +66,7 @@ xkb-data = "0.2.1" zbus = { version = "4.4.0", features = ["tokio"], optional = true } ustr = "1.0.0" fontdb = "0.16.2" +fixed_decimal = "0.5.6" [dependencies.cosmic-settings-subscriptions] git = "https://github.com/pop-os/cosmic-settings-subscriptions" @@ -78,14 +82,14 @@ features = ["experimental", "compiled_data", "icu_datetime_experimental"] version = "0.15.0" features = ["fluent-system", "desktop-requester"] +# Contains region-handling logic for Linux +[dependencies.lichen-system] +git = "https://github.com/serpent-os/lichen" +package = "system" +optional = true + [features] -default = [ - "a11y", - "dbus-config", - "linux", - "single-instance", - "wgpu", -] +default = ["a11y", "dbus-config", "linux", "single-instance", "wgpu"] # Default features for Linux linux = [ @@ -95,6 +99,7 @@ linux = [ "page-input", "page-networking", "page-power", + "page-region", "page-sound", "page-window-management", "page-workspaces", @@ -106,9 +111,19 @@ linux = [ page-about = ["dep:cosmic-settings-system", "dep:hostname1-zbus", "dep:zbus"] page-bluetooth = ["dep:bluez-zbus", "dep:zbus"] page-date = ["dep:timedate-zbus", "dep:zbus"] -page-input = ["dep:cosmic-comp-config", "dep:cosmic-settings-config", "dep:udev"] -page-networking = ["ashpd", "dep:cosmic-dbus-networkmanager", "dep:cosmic-settings-subscriptions", "dep:zbus"] +page-input = [ + "dep:cosmic-comp-config", + "dep:cosmic-settings-config", + "dep:udev", +] +page-networking = [ + "ashpd", + "dep:cosmic-dbus-networkmanager", + "dep:cosmic-settings-subscriptions", + "dep:zbus", +] page-power = ["dep:upower_dbus", "dep:zbus"] +page-region = ["dep:lichen-system", "dep:locale1"] page-sound = ["dep:cosmic-settings-subscriptions"] page-window-management = ["dep:cosmic-settings-config"] page-workspaces = ["dep:cosmic-comp-config"] diff --git a/cosmic-settings/src/app.rs b/cosmic-settings/src/app.rs index bf16df8f..d864ddc5 100644 --- a/cosmic-settings/src/app.rs +++ b/cosmic-settings/src/app.rs @@ -96,6 +96,7 @@ impl SettingsApp { PageCommands::Panel => self.pages.page_id::(), #[cfg(feature = "page-power")] PageCommands::Power => self.pages.page_id::(), + #[cfg(feature = "page-region")] PageCommands::RegionLanguage => self.pages.page_id::(), #[cfg(feature = "page-sound")] PageCommands::Sound => self.pages.page_id::(), @@ -480,6 +481,13 @@ impl cosmic::Application for SettingsApp { } } + #[cfg(feature = "page-region")] + crate::pages::Message::Region(message) => { + if let Some(page) = self.pages.page_mut::() { + return page.update(message).map(Into::into); + } + } + #[cfg(feature = "page-sound")] crate::pages::Message::Sound(message) => { if let Some(page) = self.pages.page_mut::() { diff --git a/cosmic-settings/src/pages/bluetooth/mod.rs b/cosmic-settings/src/pages/bluetooth/mod.rs index d8519321..02588cb7 100644 --- a/cosmic-settings/src/pages/bluetooth/mod.rs +++ b/cosmic-settings/src/pages/bluetooth/mod.rs @@ -135,7 +135,8 @@ impl page::Page for Page { let cancel_button = widget::button::standard(fl!("cancel")).on_press(Message::PinCancel); - let dialog = widget::dialog(fl!("bluetooth-confirm-pin")) + let dialog = widget::dialog() + .title(fl!("bluetooth-confirm-pin")) .control(control) .primary_action(confirm_button) .secondary_action(cancel_button) diff --git a/cosmic-settings/src/pages/desktop/appearance/mod.rs b/cosmic-settings/src/pages/desktop/appearance/mod.rs index 4b346f4e..a612d1a8 100644 --- a/cosmic-settings/src/pages/desktop/appearance/mod.rs +++ b/cosmic-settings/src/pages/desktop/appearance/mod.rs @@ -24,7 +24,7 @@ use cosmic::widget::{ button, color_picker::ColorPickerUpdate, container, flex_row, horizontal_space, radio, row, scrollable, settings, spin_button, text, ColorPickerModel, }; -use cosmic::{Apply, Element, Task}; +use cosmic::{widget, Apply, Element, Task}; #[cfg(feature = "wayland")] use cosmic_panel_config::CosmicPanelConfig; use cosmic_settings_page::Section; diff --git a/cosmic-settings/src/pages/desktop/panel/applets_inner.rs b/cosmic-settings/src/pages/desktop/panel/applets_inner.rs index e2791817..59a951c9 100644 --- a/cosmic-settings/src/pages/desktop/panel/applets_inner.rs +++ b/cosmic-settings/src/pages/desktop/panel/applets_inner.rs @@ -308,17 +308,17 @@ impl Page { ); } - column::with_children(vec![ - text_input::search_input(fl!("search-applets"), &self.search) - .on_input(move |s| msg_map(Message::Search(s))) - .on_paste(move |s| msg_map(Message::Search(s))) - .width(Length::Fixed(312.0)) - .into(), - list_column.into(), - ]) - .align_x(Alignment::Center) - .spacing(space_xxs) - .into() + let search = text_input::search_input(fl!("search-applets"), &self.search) + .on_input(move |s| msg_map(Message::Search(s))) + .on_paste(move |s| msg_map(Message::Search(s))) + .width(Length::Fixed(312.0)); + + column::with_capacity(2) + .push(search) + .push(list_column) + .align_x(Alignment::Center) + .spacing(space_xxs) + .into() } #[allow(clippy::too_many_lines)] diff --git a/cosmic-settings/src/pages/display/mod.rs b/cosmic-settings/src/pages/display/mod.rs index 44e5c763..b7f92721 100644 --- a/cosmic-settings/src/pages/display/mod.rs +++ b/cosmic-settings/src/pages/display/mod.rs @@ -344,7 +344,8 @@ impl page::Page for Page { /// Task. fn dialog(&self) -> Option> { self.dialog?; - let element = widget::dialog(fl!("dialog", "title")) + let element = widget::dialog() + .title(fl!("dialog", "title")) .body(fl!("dialog", "change-prompt", time = self.dialog_countdown)) .primary_action( widget::button::suggested(fl!("dialog", "keep-changes")) diff --git a/cosmic-settings/src/pages/input/keyboard/mod.rs b/cosmic-settings/src/pages/input/keyboard/mod.rs index bc993054..7ab15727 100644 --- a/cosmic-settings/src/pages/input/keyboard/mod.rs +++ b/cosmic-settings/src/pages/input/keyboard/mod.rs @@ -241,7 +241,7 @@ fn input_source( ) -> cosmic::Element { let expanded = expanded_source_popover.is_some_and(|expanded_id| expanded_id == id); - settings::flex_item(description, popover_button(id, expanded)).into() + settings::item(description, popover_button(id, expanded)).into() } fn special_char_radio_row<'a>( diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs index cbb788b0..585bef21 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs @@ -166,7 +166,8 @@ impl Model { let secondary_action = button::standard(fl!("cancel")) .on_press(ShortcutMessage::CancelReplace); - let dialog = widget::dialog(fl!("replace-shortcut-dialog")) + let dialog = widget::dialog() + .title(fl!("replace-shortcut-dialog")) .icon(icon::from_name("dialog-warning").size(64)) .body(fl!( "replace-shortcut-dialog", @@ -521,7 +522,7 @@ fn context_drawer( .into(); let flex_control = - settings::flex_item_row(vec![input, delete_button]).align_items(Alignment::Center); + settings::item_row(vec![input, delete_button]).align_y(Alignment::Center); section.add(flex_control) }, diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs index 5a79797e..2a38fdf6 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs @@ -321,7 +321,8 @@ impl page::Page for Page { let secondary_action = button::standard(fl!("cancel")).on_press(Message::ReplaceCancel); - let dialog = widget::dialog(fl!("replace-shortcut-dialog")) + let dialog = widget::dialog() + .title(fl!("replace-shortcut-dialog")) .icon(icon::from_name("dialog-warning").size(64)) .body(fl!( "replace-shortcut-dialog", diff --git a/cosmic-settings/src/pages/mod.rs b/cosmic-settings/src/pages/mod.rs index 86c04a53..1d619909 100644 --- a/cosmic-settings/src/pages/mod.rs +++ b/cosmic-settings/src/pages/mod.rs @@ -63,6 +63,8 @@ pub enum Message { PanelApplet(desktop::panel::applets_inner::Message), #[cfg(feature = "page-power")] Power(power::Message), + #[cfg(feature = "page-region")] + Region(time::region::Message), #[cfg(feature = "page-sound")] Sound(sound::Message), #[cfg(feature = "page-input")] diff --git a/cosmic-settings/src/pages/networking/vpn/mod.rs b/cosmic-settings/src/pages/networking/vpn/mod.rs index 662f9ba0..b6d4afd9 100644 --- a/cosmic-settings/src/pages/networking/vpn/mod.rs +++ b/cosmic-settings/src/pages/networking/vpn/mod.rs @@ -229,7 +229,8 @@ impl page::Page for Page { let primary_action = widget::button::standard(fl!("ok")).on_press(Message::CancelDialog); - widget::dialog(fl!("vpn-error")) + widget::dialog() + .title(fl!("vpn-error")) .icon(icon::from_name("dialog-error-symbolic").size(64)) .body(error_kind.localized()) .control(reason) @@ -268,7 +269,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("auth-dialog")) + widget::dialog() + .title(fl!("auth-dialog")) .icon(icon::from_name("network-vpn-symbolic").size(64)) .body(fl!("auth-dialog", "vpn-description")) .control(controls) @@ -289,7 +291,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("wireguard-dialog")) + widget::dialog() + .title(fl!("wireguard-dialog")) .icon(icon::from_name("network-vpn-symbolic").size(64)) .body(fl!("wireguard-dialog", "description")) .control(input) @@ -306,7 +309,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("remove-connection-dialog")) + widget::dialog() + .title(fl!("remove-connection-dialog")) .icon(icon::from_name("dialog-information").size(64)) .body(fl!("remove-connection-dialog", "vpn-description")) .primary_action(primary_action) diff --git a/cosmic-settings/src/pages/networking/wifi.rs b/cosmic-settings/src/pages/networking/wifi.rs index c174a899..25aa74ad 100644 --- a/cosmic-settings/src/pages/networking/wifi.rs +++ b/cosmic-settings/src/pages/networking/wifi.rs @@ -158,7 +158,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("auth-dialog")) + widget::dialog() + .title(fl!("auth-dialog")) .icon(icon::from_name("preferences-wireless-symbolic").size(64)) .body(fl!("auth-dialog", "wifi-description")) .control(password) @@ -175,7 +176,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("forget-dialog")) + widget::dialog() + .title(fl!("forget-dialog")) .icon(icon::from_name("dialog-information").size(64)) .body(fl!("forget-dialog", "description")) .primary_action(primary_action) diff --git a/cosmic-settings/src/pages/networking/wired.rs b/cosmic-settings/src/pages/networking/wired.rs index 1917de8e..bff5de1c 100644 --- a/cosmic-settings/src/pages/networking/wired.rs +++ b/cosmic-settings/src/pages/networking/wired.rs @@ -131,7 +131,8 @@ impl page::Page for Page { let secondary_action = widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog); - widget::dialog(fl!("remove-connection-dialog")) + widget::dialog() + .title(fl!("remove-connection-dialog")) .icon(icon::from_name("dialog-information").size(64)) .body(fl!("remove-connection-dialog", "wired-description")) .primary_action(primary_action) diff --git a/cosmic-settings/src/pages/time/mod.rs b/cosmic-settings/src/pages/time/mod.rs index f2275b5a..426cc9b9 100644 --- a/cosmic-settings/src/pages/time/mod.rs +++ b/cosmic-settings/src/pages/time/mod.rs @@ -32,7 +32,12 @@ impl page::AutoBind for Page { { page = page.sub_page::(); } - page = page.sub_page::(); + + #[cfg(feature = "page-region")] + { + page = page.sub_page::(); + } + page } } diff --git a/cosmic-settings/src/pages/time/region.rs b/cosmic-settings/src/pages/time/region.rs index 37a18b92..4406d8e3 100644 --- a/cosmic-settings/src/pages/time/region.rs +++ b/cosmic-settings/src/pages/time/region.rs @@ -1,13 +1,117 @@ // Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only +use std::collections::{BTreeMap, BTreeSet}; +use std::rc::Rc; +use std::str::FromStr; +use std::sync::Arc; + +use cosmic::iced::{Alignment, Border, Color, Length}; +use cosmic::iced_core::text::Wrapping; +use cosmic::widget::{self, button, container}; +use cosmic::{theme, Apply, Element}; +use cosmic_config::{ConfigGet, ConfigSet}; use cosmic_settings_page::Section; use cosmic_settings_page::{self as page, section}; -use slotmap::SlotMap; +use eyre::Context; +use fixed_decimal::FixedDecimal; +use icu::calendar::DateTime; +use icu::datetime::options::components::{self, Bag}; +use icu::datetime::options::preferences; +use icu::datetime::DateTimeFormatter; +use icu::decimal::options::FixedDecimalFormatterOptions; +use icu::decimal::FixedDecimalFormatter; +use lichen_system::locale; +use slotmap::{DefaultKey, SlotMap}; +use tokio::sync::mpsc; + +#[derive(Clone, Debug)] +pub enum Message { + AddLanguage(DefaultKey), + AddLanguageContext, + AddLanguageSearch(String), + SystemLocales(SlotMap), + ExpandLanguagePopover(Option), + InstallAdditionalLanguages, + SelectRegion(DefaultKey), + SourceContext(SourceContext), + Refresh(Arc>), + RegionContext, +} + +impl From for crate::app::Message { + fn from(message: Message) -> Self { + crate::pages::Message::Region(message).into() + } +} + +impl From for crate::pages::Message { + fn from(message: Message) -> Self { + crate::pages::Message::Region(message) + } +} + +enum ContextView { + AddLanguage, + Region, +} + +#[derive(Clone, Debug)] +pub enum SourceContext { + MoveDown(usize), + MoveUp(usize), + Remove(usize), +} + +#[derive(Clone, Debug)] +pub struct SystemLocale { + lang_code: String, + display_name: String, + region_name: String, +} + +impl Eq for SystemLocale {} + +impl Ord for SystemLocale { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.display_name.cmp(&other.display_name) + } +} + +impl PartialOrd for SystemLocale { + fn partial_cmp(&self, other: &Self) -> Option { + self.display_name.partial_cmp(&other.display_name) + } +} + +impl PartialEq for SystemLocale { + fn eq(&self, other: &Self) -> bool { + self.display_name == other.display_name + } +} + +#[derive(Debug)] +pub struct PageRefresh { + config: Option<(cosmic_config::Config, Vec)>, + registry: Registry, + language: Option, + region: Option, + available_languages: SlotMap, + system_locales: BTreeMap, +} #[derive(Default)] pub struct Page { entity: page::Entity, + config: Option<(cosmic_config::Config, Vec)>, + context: Option, + language: Option, + region: Option, + available_languages: SlotMap, + system_locales: BTreeMap, + registry: Option, + expanded_source_popover: Option, + add_language_search: String, } impl page::Page for Page { @@ -19,7 +123,10 @@ impl page::Page for Page { &self, sections: &mut SlotMap>, ) -> Option { - Some(vec![sections.insert(Section::default())]) + Some(vec![ + sections.insert(preferred_languages::section()), + sections.insert(formatting::section()), + ]) } fn info(&self) -> page::Info { @@ -27,6 +134,806 @@ impl page::Page for Page { .title(fl!("time-region")) .description(fl!("time-region", "desc")) } + + fn on_enter( + &mut self, + _sender: mpsc::Sender, + ) -> cosmic::Task { + cosmic::command::future(async move { Message::Refresh(Arc::new(page_reload().await)) }) + } + + fn context_drawer(&self) -> Option> { + Some(match self.context.as_ref()? { + ContextView::AddLanguage => self.add_language_view(), + ContextView::Region => self.region_view(), + }) + } +} + +impl Page { + pub fn update(&mut self, message: Message) -> cosmic::Task { + match message { + Message::AddLanguage(id) => { + if let Some(language) = self.available_languages.get(id) { + if let Some((config, locales)) = self.config.as_mut() { + if !locales.contains(&language.lang_code) { + locales.push(language.lang_code.clone()); + _ = config.set("system_locales", &locales); + } + } + } + } + + Message::SelectRegion(id) => { + let mut commands = Vec::with_capacity(2); + + if let Some((region, language)) = + self.available_languages.get(id).zip(self.language.as_ref()) + { + self.region = Some(region.clone()); + + let lang = language.lang_code.clone(); + let region = region.lang_code.clone(); + + commands.push(cosmic::command::future(async move { + _ = set_locale(lang, region).await; + Message::Refresh(Arc::new(page_reload().await)) + })); + } + + commands.push(cosmic::Task::done(crate::app::Message::CloseContextDrawer)); + return cosmic::Task::batch(commands); + } + + Message::AddLanguageContext => { + self.context = Some(ContextView::AddLanguage); + return cosmic::Task::done(crate::app::Message::OpenContextDrawer( + self.entity, + fl!("add-language", "context").into(), + )); + } + + Message::AddLanguageSearch(search) => { + self.add_language_search = search; + } + + Message::SystemLocales(languages) => { + self.available_languages = languages; + } + + Message::ExpandLanguagePopover(id) => { + self.expanded_source_popover = id; + } + + Message::InstallAdditionalLanguages => { + return cosmic::command::future(async move { + _ = tokio::process::Command::new("gnome-language-selector") + .status() + .await; + + Message::Refresh(Arc::new(page_reload().await)) + }) + } + + Message::Refresh(result) => match Arc::into_inner(result).unwrap() { + Ok(page_refresh) => { + self.config = page_refresh.config; + self.available_languages = page_refresh.available_languages; + self.system_locales = page_refresh.system_locales; + self.language = page_refresh.language; + self.region = page_refresh.region; + self.registry = Some(page_refresh.registry.0); + } + + Err(why) => { + tracing::error!(?why, "failed to get locales from the system"); + } + }, + + Message::RegionContext => { + self.context = Some(ContextView::Region); + return cosmic::Task::done(crate::app::Message::OpenContextDrawer( + self.entity, + fl!("region").into(), + )); + } + + Message::SourceContext(context_message) => { + self.expanded_source_popover = None; + + if let Some((config, locales)) = self.config.as_mut() { + match context_message { + SourceContext::MoveDown(id) => { + if id + 1 < locales.len() { + locales.swap(id, id + 1); + } + } + + SourceContext::MoveUp(id) => { + if id > 0 { + locales.swap(id, id - 1); + } + } + + SourceContext::Remove(id) => { + let _removed = locales.remove(id); + } + } + + _ = config.set("system_locales", &locales); + + if let Some(language_code) = locales.get(0) { + if let Some(language) = self + .available_languages + .values() + .find(|lang| &lang.lang_code == language_code) + { + let language = language.clone(); + self.language = Some(language.clone()); + let region = self.region.clone(); + + tokio::spawn(async move { + _ = set_locale( + language.lang_code.clone(), + region.unwrap_or(language).lang_code.clone(), + ) + .await; + }); + } + } + } + } + } + + cosmic::Task::none() + } + + fn add_language_view(&self) -> cosmic::Element<'_, crate::pages::Message> { + let cosmic::cosmic_theme::Spacing { space_l, .. } = theme::active().cosmic().spacing; + + let search = widget::search_input(fl!("type-to-search"), &self.add_language_search) + .on_input(Message::AddLanguageSearch) + .on_clear(Message::AddLanguageSearch(String::new())); + + let mut list = widget::list_column(); + + let search_input = &self.add_language_search.trim().to_lowercase(); + + let svg_accent = Rc::new(|theme: &cosmic::Theme| { + let color = theme.cosmic().accent_color().into(); + cosmic::widget::svg::Style { color: Some(color) } + }); + + for (id, available_language) in &self.available_languages { + if search_input.is_empty() + || available_language + .display_name + .to_lowercase() + .contains(search_input) + { + let is_installed = self.config.as_ref().map_or(false, |(_, locales)| { + locales.contains(&available_language.lang_code) + }); + + let button = widget::settings::item_row(vec![ + widget::text::body(&available_language.display_name) + .class(if is_installed { + cosmic::theme::Text::Accent + } else { + cosmic::theme::Text::Default + }) + .wrapping(Wrapping::Word) + .into(), + widget::horizontal_space().width(Length::Fill).into(), + if is_installed { + widget::icon::from_name("object-select-symbolic") + .size(16) + .icon() + .class(cosmic::theme::Svg::Custom(svg_accent.clone())) + .into() + } else { + widget::horizontal_space().width(16).into() + }, + ]) + .apply(widget::container) + .class(cosmic::theme::Container::List) + .apply(widget::button::custom) + .class(cosmic::theme::Button::Transparent) + .on_press_maybe(if is_installed { + None + } else { + Some(Message::AddLanguage(id)) + }); + + list = list.add(button) + } + } + + let install_additional_button = + widget::button::standard(fl!("install-additional-languages")) + .on_press(Message::InstallAdditionalLanguages) + .apply(widget::container) + .width(Length::Fill) + .align_x(Alignment::End); + + widget::column() + .padding([2, 0]) + .spacing(space_l) + .push(search) + .push(list) + .push(install_additional_button) + .apply(Element::from) + .map(crate::pages::Message::Region) + } + + fn formatted_date(&self) -> String { + let time_locale = self + .system_locales + .get("LC_TIME") + .or_else(|| self.system_locales.get("LANG")) + .map_or("en_US", |locale| &locale.lang_code) + .split('.') + .next() + .unwrap_or("en_US"); + + let Ok(locale) = icu::locid::Locale::from_str(time_locale) else { + return String::new(); + }; + + let mut bag = Bag::empty(); + bag.day = Some(components::Day::TwoDigitDayOfMonth); + bag.month = Some(components::Month::TwoDigit); + bag.year = Some(components::Year::Numeric); + + let options = icu::datetime::DateTimeFormatterOptions::Components(bag); + + let dtf = DateTimeFormatter::try_new_experimental(&locale.into(), options).unwrap(); + + let datetime = DateTime::try_new_gregorian_datetime(2024, 1, 1, 12, 0, 0) + .unwrap() + .to_iso() + .to_any(); + + dtf.format(&datetime) + .expect("can't format value") + .to_string() + } + + fn formatted_dates_and_times(&self) -> String { + let time_locale = self + .system_locales + .get("LC_TIME") + .or_else(|| self.system_locales.get("LANG")) + .map_or("en_US", |locale| &locale.lang_code) + .split('.') + .next() + .unwrap_or("en_US"); + + let Ok(locale) = icu::locid::Locale::from_str(time_locale) else { + return String::new(); + }; + + let mut bag = Bag::empty(); + bag.hour = Some(components::Numeric::Numeric); + bag.minute = Some(components::Numeric::Numeric); + bag.second = Some(components::Numeric::Numeric); + bag.preferences = Some(preferences::Bag::from_hour_cycle( + preferences::HourCycle::H12, + )); + // bag.time_zone_name = Some(components::TimeZoneName::ShortSpecific); + bag.day = Some(components::Day::TwoDigitDayOfMonth); + bag.month = Some(components::Month::Short); + bag.year = Some(components::Year::Numeric); + + let options = icu::datetime::DateTimeFormatterOptions::Components(bag); + + let dtf = DateTimeFormatter::try_new_experimental(&locale.into(), options).unwrap(); + + let datetime = DateTime::try_new_gregorian_datetime(2024, 1, 1, 12, 0, 0) + .unwrap() + .to_iso() + .to_any(); + + dtf.format(&datetime) + .expect("can't format value") + .to_string() + } + + fn formatted_time(&self) -> String { + let time_locale = self + .system_locales + .get("LC_TIME") + .or_else(|| self.system_locales.get("LANG")) + .map_or("en_US", |locale| &locale.lang_code) + .split('.') + .next() + .unwrap_or("en_US"); + + let Ok(locale) = icu::locid::Locale::from_str(time_locale) else { + return String::new(); + }; + + let mut bag = Bag::empty(); + bag.hour = Some(components::Numeric::Numeric); + bag.minute = Some(components::Numeric::Numeric); + bag.second = Some(components::Numeric::Numeric); + bag.preferences = Some(preferences::Bag::from_hour_cycle( + preferences::HourCycle::H12, + )); + + let options = icu::datetime::DateTimeFormatterOptions::Components(bag); + + let dtf = DateTimeFormatter::try_new_experimental(&locale.into(), options).unwrap(); + + let datetime = DateTime::try_new_gregorian_datetime(2024, 1, 1, 12, 0, 0) + .unwrap() + .to_iso() + .to_any(); + + dtf.format(&datetime) + .expect("can't format value") + .to_string() + } + + fn formatted_numbers(&self) -> String { + let numerical_locale = self + .system_locales + .get("LC_NUMERIC") + .or_else(|| self.system_locales.get("LANG")) + .map_or("en_US", |locale| &locale.lang_code) + .split('.') + .next() + .unwrap_or("en_US"); + + let Ok(locale) = icu::locid::Locale::from_str(numerical_locale) else { + return String::new(); + }; + + let options = FixedDecimalFormatterOptions::default(); + let formatter = FixedDecimalFormatter::try_new(&locale.into(), options).unwrap(); + let mut value = FixedDecimal::from(123456789); + value.multiply_pow10(-2); + + formatter.format(&value).to_string() + } + + fn region_view(&self) -> cosmic::Element<'_, crate::pages::Message> { + let space_l = theme::active().cosmic().spacing.space_l; + + let svg_accent = Rc::new(|theme: &cosmic::Theme| { + let color = theme.cosmic().accent_color().into(); + cosmic::widget::svg::Style { color: Some(color) } + }); + + let search = widget::search_input(fl!("type-to-search"), &self.add_language_search) + .on_input(Message::AddLanguageSearch) + .on_clear(Message::AddLanguageSearch(String::new())); + + let mut list = widget::list_column(); + + let search_input = &self.add_language_search.trim().to_lowercase(); + + for (id, locale) in &self.available_languages { + if search_input.is_empty() || locale.display_name.to_lowercase().contains(search_input) + { + let is_selected = self + .region + .as_ref() + .map_or(false, |l| l.lang_code == locale.lang_code); + + let button = widget::settings::item_row(vec![ + widget::text::body(&locale.region_name) + .class(if is_selected { + cosmic::theme::Text::Accent + } else { + cosmic::theme::Text::Default + }) + .wrapping(Wrapping::Word) + .into(), + if is_selected { + widget::icon::from_name("object-select-symbolic") + .size(16) + .icon() + .class(cosmic::theme::Svg::Custom(svg_accent.clone())) + .into() + } else { + widget::horizontal_space().width(16).into() + }, + ]) + .apply(widget::container) + .class(cosmic::theme::Container::List) + .apply(widget::button::custom) + .class(cosmic::theme::Button::Transparent) + .on_press_maybe(if is_selected { + None + } else { + Some(Message::SelectRegion(id)) + }); + + list = list.add(button) + } + } + + widget::column() + .padding([2, 0]) + .spacing(space_l) + .push(search) + .push(list) + .apply(Element::from) + .map(crate::pages::Message::Region) + } } impl page::AutoBind for Page {} + +mod preferred_languages { + use super::Message; + use cosmic::{ + iced::{Alignment, Length}, + widget, Apply, + }; + use cosmic_settings_page::Section; + + pub fn section() -> Section { + crate::slab!(descriptions { + pref_lang_desc = fl!("preferred-languages", "desc"); + add_lang_txt = fl!("add-language"); + }); + + Section::default() + .title(fl!("preferred-languages")) + .descriptions(descriptions) + .view::(move |_binder, page, section| { + let title = widget::text::body(§ion.title).font(cosmic::font::bold()); + + let description = widget::text::body(§ion.descriptions[pref_lang_desc]); + + let mut content = widget::settings::section(); + + if let Some(((_config, locales), registry)) = + page.config.as_ref().zip(page.registry.as_ref()) + { + for (id, locale) in locales.iter().enumerate() { + if let Some(locale) = registry.locale(locale) { + content = content.add(super::language_element( + id, + locale.display_name.clone(), + page.expanded_source_popover, + )); + } + } + } + + let add_language_button = + widget::button::standard(§ion.descriptions[add_lang_txt]) + .on_press(Message::AddLanguageContext) + .apply(widget::container) + .width(Length::Fill) + .align_x(Alignment::End); + + widget::column::with_capacity(5) + .push(title) + .push(description) + .push(content) + .push(add_language_button) + .spacing(cosmic::theme::active().cosmic().spacing.space_xxs) + .apply(cosmic::Element::from) + .map(Into::into) + }) + } +} + +mod formatting { + use super::Message; + use cosmic::{widget, Apply}; + use cosmic_settings_page::Section; + + pub fn section() -> Section { + crate::slab!(descriptions { + formatting_txt = fl!("formatting"); + dates_txt = fl!("formatting", "dates"); + time_txt = fl!("formatting", "time"); + date_and_time_txt = fl!("formatting", "date-and-time"); + numbers_txt = fl!("formatting", "numbers"); + // measurement_txt = fl!("formatting", "measurement"); + // paper_txt = fl!("formatting", "paper"); + region_txt = fl!("region"); + }); + + let dates_label = [&descriptions[dates_txt], ":"].concat(); + let time_label = [&descriptions[time_txt], ":"].concat(); + let date_and_time_label = [&descriptions[date_and_time_txt], ":"].concat(); + let numbers_label = [&descriptions[numbers_txt], ":"].concat(); + // let measurement_label = [&descriptions[measurement_txt], ":"].concat(); + // let paper_label = [&descriptions[paper_txt], ":"].concat(); + + Section::default() + .title(fl!("formatting")) + .descriptions(descriptions) + .view::(move |_binder, page, section| { + let desc = §ion.descriptions; + + let dates = widget::row::with_capacity(2) + .push(widget::text::body(dates_label.clone())) + .push(widget::text::body(page.formatted_date()).font(cosmic::font::bold())) + .spacing(4); + + let time = widget::row::with_capacity(2) + .push(widget::text::body(time_label.clone())) + .push(widget::text::body(page.formatted_time()).font(cosmic::font::bold())) + .spacing(4); + + let dates_and_times = widget::row::with_capacity(2) + .push(widget::text::body(date_and_time_label.clone())) + .push( + widget::text::body(page.formatted_dates_and_times()) + .font(cosmic::font::bold()), + ) + .spacing(4); + + let numbers = widget::row::with_capacity(2) + .push(widget::text::body(numbers_label.clone())) + .push(widget::text::body(page.formatted_numbers()).font(cosmic::font::bold())) + .spacing(4); + + // TODO: Display measurement and paper demos + + // let measurement = widget::row::with_capacity(2) + // .push(widget::text::body(measurement_label.clone())) + // .push(widget::text::body("").font(cosmic::font::bold())) + // .spacing(4); + + // let paper = widget::row::with_capacity(2) + // .push(widget::text::body(paper_label.clone())) + // .push(widget::text::body("").font(cosmic::font::bold())) + // .spacing(4); + + let formatted_demo = widget::column::with_capacity(6) + .push(dates) + .push(time) + .push(dates_and_times) + .push(numbers) + // .push(measurement) + // .push(paper) + .spacing(4) + .padding(5.0) + .apply(|column| widget::settings::item_row(vec![column.into()])); + + let region = page + .region + .as_ref() + .map(|locale| locale.region_name.as_str()) + .unwrap_or(""); + + let select_region = crate::widget::go_next_with_item( + &desc[region_txt], + widget::text::body(region), + Message::RegionContext, + ); + + widget::settings::section() + .title(&desc[formatting_txt]) + .add(formatted_demo) + .add(select_region) + .apply(cosmic::Element::from) + .map(Into::into) + }) + } +} + +struct Registry(locale::Registry); + +impl std::fmt::Debug for Registry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Registry").finish() + } +} + +pub async fn page_reload() -> eyre::Result { + let conn = zbus::Connection::system() + .await + .wrap_err("zbus system connection error")?; + + let registry = locale::Registry::new().wrap_err("failed to get locale registry")?; + + let system_locales: BTreeMap = locale1::locale1Proxy::new(&conn) + .await + .wrap_err("locale1 proxy connect error")? + .locale() + .await + .wrap_err("could not get locale from locale1")? + .into_iter() + .filter_map(|expression| { + let mut fields = expression.split('='); + let var = fields.next()?; + let lang_code = fields.next()?; + let locale = registry.locale(lang_code); + Some(( + var.to_owned(), + SystemLocale { + lang_code: lang_code.to_owned(), + display_name: registry + .locale(lang_code) + .map_or(String::from(""), |locale| locale.display_name.clone()), + region_name: locale.map_or(String::from(""), |locale| { + format!( + "{} ({})", + locale.territory.display_name, locale.language.display_name + ) + }), + }, + )) + }) + .collect(); + + let config = cosmic_config::Config::new("com.system76.CosmicSettings", 1) + .ok() + .map(|context| { + let locales = context + .get::>("system_locales") + .ok() + .unwrap_or_else(|| { + let current = system_locales + .get("LANG") + .map_or("en_US.UTF-8", |l| l.lang_code.as_str()) + .to_owned(); + + vec![current] + }); + + (context, locales) + }); + + let language = system_locales + .get("LC_ALL") + .or_else(|| system_locales.get("LANG")) + .cloned(); + + let region = system_locales + .get("LC_TIME") + .or_else(|| system_locales.get("LANG")) + .cloned(); + + let mut available_languages_set = BTreeSet::new(); + + let output = tokio::process::Command::new("localectl") + .arg("list-locales") + .output() + .await + .expect("Failed to run localectl"); + + let output = String::from_utf8(output.stdout).unwrap_or_default(); + for line in output.lines() { + if line == "C.UTF-8" { + continue; + } + + if let Some(locale) = registry.locale(line) { + available_languages_set.insert(SystemLocale { + lang_code: line.to_owned(), + display_name: locale.display_name.clone(), + region_name: format!( + "{} ({})", + locale.territory.display_name, locale.language.display_name + ), + }); + } + } + + let mut available_languages = SlotMap::new(); + for language in available_languages_set { + available_languages.insert(language); + } + + Ok(PageRefresh { + config, + registry: Registry(registry), + language, + region, + available_languages, + system_locales, + }) +} + +fn language_element( + id: usize, + description: String, + expanded_source_popover: Option, +) -> cosmic::Element<'static, Message> { + let expanded = expanded_source_popover.is_some_and(|expanded_id| expanded_id == id); + + widget::settings::item(description, popover_button(id, expanded)).into() +} + +fn popover_button(id: usize, expanded: bool) -> Element<'static, Message> { + let on_press = Message::ExpandLanguagePopover(if expanded { None } else { Some(id) }); + + let button = button::icon(widget::icon::from_name("view-more-symbolic")) + .extra_small() + .on_press(on_press); + + if expanded { + widget::popover(button) + .popup(popover_menu(id)) + .on_close(Message::ExpandLanguagePopover(None)) + .into() + } else { + button.into() + } +} + +fn popover_menu(id: usize) -> Element<'static, Message> { + widget::column::with_children(vec![ + popover_menu_row( + id, + fl!("keyboard-sources", "move-up"), + SourceContext::MoveUp, + ), + cosmic::widget::divider::horizontal::default().into(), + popover_menu_row( + id, + fl!("keyboard-sources", "move-down"), + SourceContext::MoveDown, + ), + cosmic::widget::divider::horizontal::default().into(), + popover_menu_row(id, fl!("keyboard-sources", "remove"), SourceContext::Remove), + ]) + .padding(8) + .width(Length::Shrink) + .height(Length::Shrink) + .apply(cosmic::widget::container) + .class(cosmic::theme::Container::custom(|theme| { + let cosmic = theme.cosmic(); + container::Style { + icon_color: Some(theme.cosmic().background.on.into()), + text_color: Some(theme.cosmic().background.on.into()), + background: Some(Color::from(theme.cosmic().background.base).into()), + border: Border { + radius: cosmic.corner_radii.radius_m.into(), + ..Default::default() + }, + shadow: Default::default(), + } + })) + .into() +} + +fn popover_menu_row( + id: usize, + label: String, + message: impl Fn(usize) -> SourceContext + 'static, +) -> cosmic::Element<'static, Message> { + widget::text::body(label) + .apply(widget::container) + .class(cosmic::theme::Container::custom(|theme| { + widget::container::Style { + background: None, + ..widget::container::Catalog::style(theme, &cosmic::theme::Container::List) + } + })) + .apply(button::custom) + .on_press(()) + .class(theme::Button::Transparent) + .apply(Element::from) + .map(move |()| Message::SourceContext(message(id))) +} + +pub async fn set_locale(lang: String, region: String) { + eprintln!("setting locale lang={lang}, region={region}"); + _ = tokio::process::Command::new("localectl") + .arg("set-locale") + .args(&[ + ["LANG=", &lang].concat(), + ["LC_ADDRESS=", ®ion].concat(), + ["LC_IDENTIFICATION=", ®ion].concat(), + ["LC_MEASUREMENT=", ®ion].concat(), + ["LC_MONETARY=", ®ion].concat(), + ["LC_NAME=", ®ion].concat(), + ["LC_NUMERIC=", ®ion].concat(), + ["LC_PAPER=", ®ion].concat(), + ["LC_TELEPHONE=", ®ion].concat(), + ["LC_TIME=", ®ion].concat(), + ]) + .status() + .await; +} diff --git a/cosmic-settings/src/widget/mod.rs b/cosmic-settings/src/widget/mod.rs index 53fb38c0..4eb3328e 100644 --- a/cosmic-settings/src/widget/mod.rs +++ b/cosmic-settings/src/widget/mod.rs @@ -23,24 +23,26 @@ pub fn color_picker_context_view<'a, Message: Clone + 'static>( let theme = theme::active(); let spacing = &theme.cosmic().spacing; - cosmic::widget::column() - .push_maybe(description.map(|description| text(description).width(Length::Fill))) - .push( - model - .builder(on_update) - .reset_label(reset) - .height(Length::Fixed(158.0)) - .build( - fl!("recent-colors"), - fl!("copy-to-clipboard"), - fl!("copied-to-clipboard"), - ) - .apply(container) - .width(Length::Fixed(248.0)) - .align_x(Alignment::Center) - .apply(container) - .center_x(Length::Fill), + let description = description.map(|description| text(description).width(Length::Fill)); + + let color_picker = model + .builder(on_update) + .reset_label(reset) + .height(Length::Fixed(158.0)) + .build( + fl!("recent-colors"), + fl!("copy-to-clipboard"), + fl!("copied-to-clipboard"), ) + .apply(container) + .width(Length::Fixed(248.0)) + .align_x(Alignment::Center) + .apply(container) + .center_x(Length::Fill); + + cosmic::widget::column() + .push_maybe(description) + .push(color_picker) .padding(spacing.space_l) .align_x(Alignment::Center) .spacing(spacing.space_m) diff --git a/i18n/en/cosmic_settings.ftl b/i18n/en/cosmic_settings.ftl index 575ed7e0..948f4f5f 100644 --- a/i18n/en/cosmic_settings.ftl +++ b/i18n/en/cosmic_settings.ftl @@ -714,6 +714,22 @@ time-format = Date & Time Format time-region = Region & Language .desc = Format dates, times, and numbers based on your region +formatting = Formatting + .dates = Dates + .time = Time + .date-and-time = Date & Time + .numbers = Numbers + .measurement = Measurement + .paper = Paper + +preferred-languages = Preferred Languages + .desc = The order of languages determines which language is used for the translation of the desktop. Changes take effect on next login. + +add-language = Add language + .context = Add Language +install-additional-languages = Install additional languages +region = Region + ## System system = System & Accounts diff --git a/page/src/lib.rs b/page/src/lib.rs index 819b9d96..c5cac6ba 100644 --- a/page/src/lib.rs +++ b/page/src/lib.rs @@ -75,6 +75,7 @@ pub trait Page: Downcast { } /// Assigns the entity ID of the page to the page. + #[allow(unused)] fn set_id(&mut self, entity: Entity) {} /// The title to display in the page header.