feat: automatic dates; timezone setting support
This commit is contained in:
parent
a9dda39526
commit
36542ea0b9
6 changed files with 593 additions and 147 deletions
370
Cargo.lock
generated
370
Cargo.lock
generated
|
|
@ -287,7 +287,7 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093"
|
||||
dependencies = [
|
||||
"async-fs 2.1.2",
|
||||
"async-fs",
|
||||
"async-net",
|
||||
"enumflags2",
|
||||
"futures-channel",
|
||||
|
|
@ -377,18 +377,6 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
|
||||
dependencies = [
|
||||
"async-lock 2.8.0",
|
||||
"autocfg",
|
||||
"blocking",
|
||||
"futures-lite 1.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "2.1.2"
|
||||
|
|
@ -1485,7 +1473,6 @@ dependencies = [
|
|||
"cosmic-settings-config",
|
||||
"cosmic-settings-page",
|
||||
"cosmic-settings-system",
|
||||
"cosmic-settings-time",
|
||||
"cosmic-settings-wallpaper",
|
||||
"derivative",
|
||||
"derive_setters",
|
||||
|
|
@ -1498,6 +1485,7 @@ dependencies = [
|
|||
"hostname1-zbus",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"icu",
|
||||
"image 0.25.2",
|
||||
"itertools 0.13.0",
|
||||
"itoa",
|
||||
|
|
@ -1513,6 +1501,7 @@ dependencies = [
|
|||
"static_init",
|
||||
"sunrise",
|
||||
"tachyonix",
|
||||
"timedate-zbus",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
|
@ -1571,16 +1560,6 @@ dependencies = [
|
|||
"sysinfo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmic-settings-time"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"icu_calendar",
|
||||
"icu_timezone",
|
||||
"timedate-zbus",
|
||||
"zbus 3.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmic-settings-wallpaper"
|
||||
version = "0.1.0"
|
||||
|
|
@ -2163,6 +2142,17 @@ dependencies = [
|
|||
"toml 0.5.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed_decimal"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0febbeb1118a9ecdee6e4520ead6b54882e843dd0592ad233247dbee84c53db8"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"smallvec",
|
||||
"writeable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
|
|
@ -3136,6 +3126,30 @@ dependencies = [
|
|||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff5e3018d703f168b00dcefa540a65f1bbc50754ae32f3f5f0e43fe5ee51502"
|
||||
dependencies = [
|
||||
"icu_calendar",
|
||||
"icu_casemap",
|
||||
"icu_collator",
|
||||
"icu_collections",
|
||||
"icu_datetime",
|
||||
"icu_decimal",
|
||||
"icu_experimental",
|
||||
"icu_list",
|
||||
"icu_locid",
|
||||
"icu_locid_transform",
|
||||
"icu_normalizer",
|
||||
"icu_plurals",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"icu_segmenter",
|
||||
"icu_timezone",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_calendar"
|
||||
version = "1.5.2"
|
||||
|
|
@ -3159,6 +3173,171 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e009b7f0151ee6fb28c40b1283594397e0b7183820793e9ace3dcd13db126d0"
|
||||
|
||||
[[package]]
|
||||
name = "icu_casemap"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ff0c8ae9f8d31b12e27fc385ff9ab1f3cd9b17417c665c49e4ec958c37da75f"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_casemap_data",
|
||||
"icu_collections",
|
||||
"icu_locid",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"writeable",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_casemap_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d57966d5ab748f74513be4046867f9a20e801e2775d41f91d04a0f560b61f08"
|
||||
|
||||
[[package]]
|
||||
name = "icu_collator"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d370371887d31d56f361c3eaa15743e54f13bc677059c9191c77e099ed6966b2"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collator_data",
|
||||
"icu_collections",
|
||||
"icu_locid_transform",
|
||||
"icu_normalizer",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"utf16_iter",
|
||||
"utf8_iter",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collator_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ee3f88741364b7d6269cce6827a3e6a8a2cf408a78f766c9224ab479d5e4ae5"
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_datetime"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d115efb85e08df3fd77e77f52e7e087545a783fffba8be80bfa2102f306b1780"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"either",
|
||||
"fixed_decimal",
|
||||
"icu_calendar",
|
||||
"icu_datetime_data",
|
||||
"icu_decimal",
|
||||
"icu_locid",
|
||||
"icu_locid_transform",
|
||||
"icu_plurals",
|
||||
"icu_provider",
|
||||
"icu_timezone",
|
||||
"litemap",
|
||||
"smallvec",
|
||||
"tinystr",
|
||||
"writeable",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_datetime_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ba7e7f7a01269b9afb0a39eff4f8676f693b55f509b3120e43a0350a9f88bea"
|
||||
|
||||
[[package]]
|
||||
name = "icu_decimal"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb8fd98f86ec0448d85e1edf8884e4e318bb2e121bd733ec929a05c0a5e8b0eb"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"fixed_decimal",
|
||||
"icu_decimal_data",
|
||||
"icu_locid_transform",
|
||||
"icu_provider",
|
||||
"writeable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_decimal_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d424c994071c6f5644f999925fc868c85fec82295326e75ad5017bc94b41523"
|
||||
|
||||
[[package]]
|
||||
name = "icu_experimental"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "844ad7b682a165c758065d694bc4d74ac67f176da1c499a04d85d492c0f193b7"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"fixed_decimal",
|
||||
"icu_collections",
|
||||
"icu_decimal",
|
||||
"icu_experimental_data",
|
||||
"icu_locid",
|
||||
"icu_locid_transform",
|
||||
"icu_normalizer",
|
||||
"icu_pattern",
|
||||
"icu_plurals",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"litemap",
|
||||
"num-bigint",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"smallvec",
|
||||
"tinystr",
|
||||
"writeable",
|
||||
"zerofrom",
|
||||
"zerotrie",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_experimental_data"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c178b9a34083fca5bd70d61f647575335e9c197d0f30c38e8ccd187babc69d0"
|
||||
|
||||
[[package]]
|
||||
name = "icu_list"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_list_data",
|
||||
"icu_locid_transform",
|
||||
"icu_provider",
|
||||
"regex-automata 0.2.0",
|
||||
"writeable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_list_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1825170d2c6679cb20dbd96a589d034e49f698aed9a2ef4fafc9a0101ed298f"
|
||||
|
||||
[[package]]
|
||||
name = "icu_locid"
|
||||
version = "1.5.0"
|
||||
|
|
@ -3192,6 +3371,84 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"utf16_iter",
|
||||
"utf8_iter",
|
||||
"write16",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
||||
|
||||
[[package]]
|
||||
name = "icu_pattern"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7f36aafd098d6717de34e668a8120822275c1fba22b936e757b7de8a2fd7e4"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"either",
|
||||
"writeable",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_plurals"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba5a70e7c025dbd5c501b0a5c188cd11666a424f0dadcd4f0a95b7dafde3b114"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"fixed_decimal",
|
||||
"icu_locid_transform",
|
||||
"icu_plurals_data",
|
||||
"icu_provider",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_plurals_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e3e8f775b215d45838814a090a2227247a7431d74e9156407d9c37f6ef0f208"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_locid_transform",
|
||||
"icu_properties_data",
|
||||
"icu_provider",
|
||||
"tinystr",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "1.5.0"
|
||||
|
|
@ -3220,6 +3477,28 @@ dependencies = [
|
|||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_segmenter"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a717725612346ffc2d7b42c94b820db6908048f39434504cb130e8b46256b0de"
|
||||
dependencies = [
|
||||
"core_maths",
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_locid",
|
||||
"icu_provider",
|
||||
"icu_segmenter_data",
|
||||
"utf8_iter",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_segmenter_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f739ee737260d955e330bc83fdeaaf1631f7fb7ed218761d3c04bb13bb7d79df"
|
||||
|
||||
[[package]]
|
||||
name = "icu_timezone"
|
||||
version = "1.5.0"
|
||||
|
|
@ -5015,6 +5294,15 @@ dependencies = [
|
|||
"regex-syntax 0.6.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
|
|
@ -6024,10 +6312,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "timedate-zbus"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "609052c48ae1d9e27999ac4a159843a290bffab5fdc13856889b940aefc185b7"
|
||||
source = "git+https://github.com/pop-os/dbus-settings-bindings#cd21ddcb1b5cbfc80ab84b34d3c8b1ff3d81179a"
|
||||
dependencies = [
|
||||
"zbus 3.15.2",
|
||||
"zbus 4.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6532,12 +6819,24 @@ dependencies = [
|
|||
"tiny-skia-path",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf16_iter"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
|
@ -7339,11 +7638,20 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
|
|
@ -7515,15 +7823,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6"
|
||||
dependencies = [
|
||||
"async-broadcast 0.5.1",
|
||||
"async-executor",
|
||||
"async-fs 1.6.0",
|
||||
"async-io 1.13.0",
|
||||
"async-lock 2.8.0",
|
||||
"async-process 1.8.1",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
"blocking",
|
||||
"byteorder",
|
||||
"derivative",
|
||||
"enumflags2",
|
||||
|
|
@ -7558,7 +7860,7 @@ checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
|
|||
dependencies = [
|
||||
"async-broadcast 0.7.1",
|
||||
"async-executor",
|
||||
"async-fs 2.1.2",
|
||||
"async-fs",
|
||||
"async-io 2.3.3",
|
||||
"async-lock 3.4.0",
|
||||
"async-process 2.2.3",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ cosmic-randr.workspace = true
|
|||
cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" }
|
||||
cosmic-settings-page = { path = "../page" }
|
||||
cosmic-settings-system = { path = "../pages/system" }
|
||||
cosmic-settings-time = { path = "../pages/time" }
|
||||
cosmic-settings-wallpaper = { path = "../pages/wallpapers" }
|
||||
derivative = "2.2.0"
|
||||
derive_setters = "0.1.6"
|
||||
|
|
@ -31,6 +30,7 @@ futures = { package = "futures-lite", version = "2.3.0" }
|
|||
generator = "=0.8.1"
|
||||
hostname-validator = "1.1.1"
|
||||
hostname1-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings" }
|
||||
timedate-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings" }
|
||||
i18n-embed-fl = "0.8.0"
|
||||
image = "0.25"
|
||||
itertools = "0.13.0"
|
||||
|
|
@ -55,6 +55,10 @@ zbus = { version = "4.4.0", features = ["tokio"] }
|
|||
tachyonix = "0.3.0"
|
||||
slab = "0.4.9"
|
||||
|
||||
[dependencies.icu]
|
||||
version = "1.4.0"
|
||||
features = ["experimental", "compiled_data", "icu_datetime_experimental"]
|
||||
|
||||
[dependencies.i18n-embed]
|
||||
version = "0.14.1"
|
||||
features = ["fluent-system", "desktop-requester"]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::app;
|
||||
use cosmic::{
|
||||
cosmic_config::{self, ConfigGet, ConfigSet},
|
||||
iced,
|
||||
Command,
|
||||
};
|
||||
use cosmic_comp_config::input::{
|
||||
AccelConfig, AccelProfile, ClickMethod, InputConfig, ScrollConfig, ScrollMethod, TapButtonMap,
|
||||
|
|
@ -93,7 +93,7 @@ impl Page {
|
|||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn update(&mut self, message: Message) -> iced::Command<app::Message> {
|
||||
pub fn update(&mut self, message: Message) -> Command<app::Message> {
|
||||
match message {
|
||||
Message::SetAcceleration(value, touchpad) => {
|
||||
let profile = if value {
|
||||
|
|
@ -152,7 +152,7 @@ impl Page {
|
|||
select_model.activate(entity);
|
||||
|
||||
let Some(left_entity) = select_model.entity_at(1) else {
|
||||
return cosmic::Command::none();
|
||||
return Command::none();
|
||||
};
|
||||
|
||||
let left_handed = select_model.active() == left_entity;
|
||||
|
|
@ -173,7 +173,7 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
cosmic::Command::none()
|
||||
Command::none()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,53 +1,85 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use chrono::{Datelike, Timelike};
|
||||
use cosmic::{
|
||||
cosmic_config::{self, ConfigGet, ConfigSet},
|
||||
iced::{widget::horizontal_space, Length},
|
||||
widget::{dropdown, settings},
|
||||
Apply,
|
||||
widget::{self, dropdown, settings},
|
||||
Apply, Command,
|
||||
};
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use icu::{
|
||||
calendar::{DateTime, Iso},
|
||||
datetime::DateTimeFormatter,
|
||||
locid::Locale,
|
||||
};
|
||||
use slab::Slab;
|
||||
use slotmap::SlotMap;
|
||||
pub use timedate_zbus::TimeDateProxy;
|
||||
use tracing::error;
|
||||
|
||||
crate::cache_dynamic_lazy! {
|
||||
static WEEKDAYS: [String; 4] = [fl!("time-format", "friday"), fl!("time-format", "saturday"), fl!("time-format", "sunday"), fl!("time-format", "monday")];
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Info {
|
||||
pub ntp_enabled: bool,
|
||||
pub timezone_id: Option<usize>,
|
||||
pub timezone_list: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct Page {
|
||||
config: cosmic_config::Config,
|
||||
auto: bool,
|
||||
auto_timezone: bool,
|
||||
military_time: bool,
|
||||
cosmic_applet_config: cosmic_config::Config,
|
||||
first_day_of_week: usize,
|
||||
military_time: bool,
|
||||
ntp_enabled: bool,
|
||||
show_date_in_top_panel: bool,
|
||||
local_time: Option<DateTime<Iso>>,
|
||||
timezone: Option<usize>,
|
||||
timezone_list: Vec<String>,
|
||||
formatted_date: String,
|
||||
}
|
||||
|
||||
impl Default for Page {
|
||||
fn default() -> Self {
|
||||
let config = cosmic_config::Config::new("com.system76.CosmicAppletTime", 1).unwrap();
|
||||
let military_time = config.get("military_time").unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'military_time'");
|
||||
false
|
||||
});
|
||||
let first_day_of_week = config.get("first_day_of_week").unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'first_day_of_week'");
|
||||
6
|
||||
});
|
||||
let show_date_in_top_panel = config.get("show_date_in_top_panel").unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'show_date_in_top_panel'");
|
||||
true
|
||||
});
|
||||
let cosmic_applet_config =
|
||||
cosmic_config::Config::new("com.system76.CosmicAppletTime", 1).unwrap();
|
||||
|
||||
let military_time = cosmic_applet_config
|
||||
.get("military_time")
|
||||
.unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'military_time'");
|
||||
false
|
||||
});
|
||||
|
||||
let first_day_of_week = cosmic_applet_config
|
||||
.get("first_day_of_week")
|
||||
.unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'first_day_of_week'");
|
||||
6
|
||||
});
|
||||
|
||||
let show_date_in_top_panel = cosmic_applet_config
|
||||
.get("show_date_in_top_panel")
|
||||
.unwrap_or_else(|err| {
|
||||
error!(?err, "Failed to read config 'show_date_in_top_panel'");
|
||||
true
|
||||
});
|
||||
|
||||
Self {
|
||||
config,
|
||||
auto: false,
|
||||
auto_timezone: false,
|
||||
military_time,
|
||||
cosmic_applet_config,
|
||||
first_day_of_week,
|
||||
formatted_date: String::new(),
|
||||
local_time: None,
|
||||
military_time,
|
||||
ntp_enabled: false,
|
||||
show_date_in_top_panel,
|
||||
timezone: None,
|
||||
timezone_list: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,42 +101,168 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
.title(fl!("time-date"))
|
||||
.description(fl!("time-date", "desc"))
|
||||
}
|
||||
|
||||
fn on_enter(
|
||||
&mut self,
|
||||
_page: cosmic_settings_page::Entity,
|
||||
_sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||
) -> Command<crate::pages::Message> {
|
||||
cosmic::command::future(async move {
|
||||
let client = match zbus::Connection::system().await {
|
||||
Ok(client) => client,
|
||||
Err(why) => {
|
||||
return Message::Error(why.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
let timedate_proxy = match TimeDateProxy::new(&client).await {
|
||||
Ok(timedate_proxy) => timedate_proxy,
|
||||
Err(why) => {
|
||||
return Message::Error(why.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
let can_ntp = timedate_proxy.can_ntp().await.unwrap_or_default();
|
||||
let ntp_enabled = can_ntp && timedate_proxy.ntp().await.unwrap_or_default();
|
||||
let timezone_list = timedate_proxy.list_timezones().await.unwrap_or_default();
|
||||
|
||||
let timezone = timedate_proxy.timezone().await.unwrap_or_default();
|
||||
|
||||
Message::Refresh(Info {
|
||||
ntp_enabled,
|
||||
timezone_id: timezone_list.iter().position(|tz| tz == &timezone),
|
||||
timezone_list,
|
||||
})
|
||||
})
|
||||
.map(crate::pages::Message::DateAndTime)
|
||||
}
|
||||
}
|
||||
|
||||
impl Page {
|
||||
pub fn update(&mut self, message: Message) {
|
||||
pub fn update(&mut self, message: Message) -> Command<crate::Message> {
|
||||
match message {
|
||||
Message::Automatic(enable) => self.auto = enable,
|
||||
Message::AutomaticTimezone(enable) => self.auto_timezone = enable,
|
||||
Message::Automatic(enable) => {
|
||||
self.ntp_enabled = enable;
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
let client = match zbus::Connection::system().await {
|
||||
Ok(client) => client,
|
||||
Err(why) => {
|
||||
tracing::error!(?why, "zbus client error");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let timedate_proxy = match TimeDateProxy::new(&client).await {
|
||||
Ok(timedate_proxy) => timedate_proxy,
|
||||
Err(why) => {
|
||||
tracing::error!(?why, "zbus client error");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
_ = timedate_proxy.set_ntp(enable, true).await;
|
||||
});
|
||||
}
|
||||
|
||||
Message::MilitaryTime(enable) => {
|
||||
self.military_time = enable;
|
||||
if let Err(err) = self.config.set("military_time", enable) {
|
||||
self.update_local_time();
|
||||
|
||||
if let Err(err) = self.cosmic_applet_config.set("military_time", enable) {
|
||||
error!(?err, "Failed to set config 'military_time'");
|
||||
}
|
||||
}
|
||||
|
||||
Message::FirstDayOfWeek(weekday) => {
|
||||
self.first_day_of_week = weekday;
|
||||
if let Err(err) = self.config.set("first_day_of_week", weekday) {
|
||||
|
||||
if let Err(err) = self.cosmic_applet_config.set("first_day_of_week", weekday) {
|
||||
error!(?err, "Failed to set config 'first_day_of_week'");
|
||||
}
|
||||
}
|
||||
|
||||
Message::ShowDate(enable) => {
|
||||
self.show_date_in_top_panel = enable;
|
||||
if let Err(err) = self.config.set("show_date_in_top_panel", enable) {
|
||||
|
||||
if let Err(err) = self
|
||||
.cosmic_applet_config
|
||||
.set("show_date_in_top_panel", enable)
|
||||
{
|
||||
error!(?err, "Failed to set config 'show_date_in_top_panel'");
|
||||
}
|
||||
}
|
||||
|
||||
Message::Timezone(timezone_id) => {
|
||||
self.timezone = Some(timezone_id);
|
||||
|
||||
if let Some(timezone) = self.timezone_list.get(timezone_id).cloned() {
|
||||
return cosmic::command::future(async move {
|
||||
let client = match zbus::Connection::system().await {
|
||||
Ok(client) => client,
|
||||
Err(why) => {
|
||||
return Message::Error(why.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
let timedate_proxy = match TimeDateProxy::new(&client).await {
|
||||
Ok(timedate_proxy) => timedate_proxy,
|
||||
Err(why) => {
|
||||
return Message::Error(why.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
match timedate_proxy.set_timezone(&timezone, true).await {
|
||||
Ok(_) => Message::UpdateTime,
|
||||
Err(why) => Message::Error(why.to_string()),
|
||||
}
|
||||
})
|
||||
.map(crate::pages::Message::DateAndTime)
|
||||
.map(crate::Message::PageMessage);
|
||||
}
|
||||
}
|
||||
|
||||
Message::Error(why) => {
|
||||
tracing::error!(why, "failed to set timezone");
|
||||
}
|
||||
|
||||
Message::UpdateTime => self.update_local_time(),
|
||||
|
||||
Message::Refresh(info) => {
|
||||
self.ntp_enabled = info.ntp_enabled;
|
||||
self.timezone_list = info.timezone_list;
|
||||
self.timezone = info.timezone_id;
|
||||
|
||||
self.update_local_time();
|
||||
}
|
||||
|
||||
Message::None => (),
|
||||
}
|
||||
|
||||
Command::none()
|
||||
}
|
||||
|
||||
pub fn update_local_time(&mut self) {
|
||||
self.local_time = Some(update_local_time());
|
||||
|
||||
self.formatted_date = match self.local_time {
|
||||
Some(ref time) => format_date(time, self.military_time),
|
||||
None => fl!("unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
Automatic(bool),
|
||||
AutomaticTimezone(bool),
|
||||
Error(String),
|
||||
MilitaryTime(bool),
|
||||
None,
|
||||
FirstDayOfWeek(usize),
|
||||
Refresh(Info),
|
||||
ShowDate(bool),
|
||||
Timezone(usize),
|
||||
UpdateTime,
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
|
@ -122,11 +280,11 @@ fn date() -> Section<crate::pages::Message> {
|
|||
settings::view_section(§ion.title)
|
||||
.add(
|
||||
settings::item::builder(&*section.descriptions[auto])
|
||||
.toggler(page.auto, Message::Automatic),
|
||||
.toggler(page.ntp_enabled, Message::Automatic),
|
||||
)
|
||||
.add(settings::item(
|
||||
&*section.descriptions[title],
|
||||
horizontal_space(Length::Fill),
|
||||
widget::text(&page.formatted_date),
|
||||
))
|
||||
.apply(cosmic::Element::from)
|
||||
.map(crate::pages::Message::DateAndTime)
|
||||
|
|
@ -183,8 +341,6 @@ fn format() -> Section<crate::pages::Message> {
|
|||
fn timezone() -> Section<crate::pages::Message> {
|
||||
let mut descriptions = Slab::new();
|
||||
|
||||
let auto = descriptions.insert(fl!("time-zone", "auto"));
|
||||
let auto_info = descriptions.insert(fl!("time-zone", "auto-info"));
|
||||
let time_zone = descriptions.insert(fl!("time-zone"));
|
||||
|
||||
Section::default()
|
||||
|
|
@ -192,18 +348,66 @@ fn timezone() -> Section<crate::pages::Message> {
|
|||
.descriptions(descriptions)
|
||||
.view::<Page>(move |_binder, page, section| {
|
||||
settings::view_section(§ion.title)
|
||||
// Automatic timezone toggle
|
||||
.add(
|
||||
settings::item::builder(&*section.descriptions[auto])
|
||||
.description(&*section.descriptions[auto_info])
|
||||
.toggler(page.auto_timezone, Message::AutomaticTimezone),
|
||||
)
|
||||
// Time zone select
|
||||
.add(
|
||||
settings::item::builder(&*section.descriptions[time_zone])
|
||||
.control(horizontal_space(Length::Fill)),
|
||||
settings::item::builder(&*section.descriptions[time_zone]).control(
|
||||
widget::dropdown(&page.timezone_list, page.timezone, Message::Timezone),
|
||||
),
|
||||
)
|
||||
.apply(cosmic::Element::from)
|
||||
.map(crate::pages::Message::DateAndTime)
|
||||
})
|
||||
}
|
||||
|
||||
fn locale() -> Result<Locale, Box<dyn std::error::Error>> {
|
||||
let locale = std::env::var("LANG")?;
|
||||
let locale = locale
|
||||
.split('.')
|
||||
.next()
|
||||
.ok_or(format!("Can't split the locale {locale}"))?;
|
||||
|
||||
let locale = Locale::from_str(locale).map_err(|e| format!("{e:?}"))?;
|
||||
Ok(locale)
|
||||
}
|
||||
|
||||
fn format_date(date: &DateTime<Iso>, military: bool) -> String {
|
||||
let Ok(locale) = locale() else {
|
||||
return String::new();
|
||||
};
|
||||
|
||||
let mut bag = icu::datetime::options::components::Bag::empty();
|
||||
|
||||
bag.year = Some(icu::datetime::options::components::Year::Numeric);
|
||||
bag.day = Some(icu::datetime::options::components::Day::NumericDayOfMonth);
|
||||
bag.month = Some(icu::datetime::options::components::Month::Long);
|
||||
bag.hour = Some(icu::datetime::options::components::Numeric::Numeric);
|
||||
bag.minute = Some(icu::datetime::options::components::Numeric::Numeric);
|
||||
bag.preferences = Some(icu::datetime::options::preferences::Bag::from_hour_cycle(
|
||||
if military {
|
||||
icu::datetime::options::preferences::HourCycle::H23
|
||||
} else {
|
||||
icu::datetime::options::preferences::HourCycle::H12
|
||||
},
|
||||
));
|
||||
|
||||
let dtf = DateTimeFormatter::try_new_experimental(&locale.into(), bag.into()).unwrap();
|
||||
|
||||
dtf.format(&date.to_any())
|
||||
.expect("can't format value")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn update_local_time() -> DateTime<Iso> {
|
||||
let now = chrono::Local::now();
|
||||
|
||||
DateTime::try_new_gregorian_datetime(
|
||||
now.year(),
|
||||
now.month() as u8,
|
||||
now.day() as u8,
|
||||
now.hour() as u8,
|
||||
now.minute() as u8,
|
||||
now.second() as u8,
|
||||
)
|
||||
.unwrap()
|
||||
.to_iso()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "cosmic-settings-time"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
icu_calendar = "1.5.2"
|
||||
icu_timezone = "1.5.0"
|
||||
timedate-zbus = "0.1.0"
|
||||
|
||||
[dependencies.zbus]
|
||||
version = "3.15.2"
|
||||
default-features = false
|
||||
features = ["tokio"]
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use icu_calendar::{types::IsoSecond, DateTime, Iso};
|
||||
use icu_timezone::CustomTimeZone;
|
||||
use timedate_zbus::TimeDateProxy;
|
||||
|
||||
pub struct Info {
|
||||
pub can_ntp: bool,
|
||||
pub timezone: CustomTimeZone,
|
||||
pub local_time: DateTime<Iso>,
|
||||
}
|
||||
|
||||
impl Info {
|
||||
pub async fn load(proxy: &TimeDateProxy<'_>) -> Option<Info> {
|
||||
let can_ntp = proxy.can_ntp().await.unwrap_or_default();
|
||||
|
||||
let Ok(timezone) = proxy
|
||||
.timezone()
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.parse::<CustomTimeZone>()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let seconds = duration.as_secs();
|
||||
|
||||
let Ok(iso_seconds) = IsoSecond::try_from((seconds % 60) as u8) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let mut local_time = DateTime::from_minutes_since_local_unix_epoch((seconds / 60) as i32);
|
||||
|
||||
local_time.time.second = iso_seconds;
|
||||
|
||||
Some(Info {
|
||||
can_ntp,
|
||||
timezone,
|
||||
local_time,
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue