Use icu for date and time localization (#934)
* Use icu for date and time localization * Handle military time config in dialog
This commit is contained in:
parent
3245f762a6
commit
5e21c7cf99
7 changed files with 511 additions and 80 deletions
305
Cargo.lock
generated
305
Cargo.lock
generated
|
|
@ -901,6 +901,16 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
|
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "calendrical_calculations"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e97f73e95d668625c9b28a3072e6326773785a0cf807de9f3d632778438f3d38"
|
||||||
|
dependencies = [
|
||||||
|
"core_maths",
|
||||||
|
"displaydoc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
|
@ -1413,6 +1423,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_maths"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-client-toolkit"
|
name = "cosmic-client-toolkit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -1476,6 +1495,7 @@ dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"i18n-embed",
|
"i18n-embed",
|
||||||
"i18n-embed-fl",
|
"i18n-embed-fl",
|
||||||
|
"icu",
|
||||||
"icu_collator",
|
"icu_collator",
|
||||||
"icu_provider",
|
"icu_provider",
|
||||||
"ignore",
|
"ignore",
|
||||||
|
|
@ -2223,6 +2243,17 @@ dependencies = [
|
||||||
"toml 0.5.11",
|
"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]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
@ -3250,6 +3281,75 @@ dependencies = [
|
||||||
"xkeysym",
|
"xkeysym",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7265b2137f9a36f7634a308d91f984574bbdba8cfd95ceffe1c345552275a8ff"
|
||||||
|
dependencies = [
|
||||||
|
"calendrical_calculations",
|
||||||
|
"displaydoc",
|
||||||
|
"icu_calendar_data",
|
||||||
|
"icu_locid",
|
||||||
|
"icu_locid_transform",
|
||||||
|
"icu_provider",
|
||||||
|
"tinystr",
|
||||||
|
"writeable",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_calendar_data"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "820499e77e852162190608b4f444e7b4552619150eafc39a9e39333d9efae9e1"
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02bd9f6276270c85a5cd54611adbbf94e993ec464a2a86a452a6c565b7ded5d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collator"
|
name = "icu_collator"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -3287,6 +3387,112 @@ dependencies = [
|
||||||
"zerovec",
|
"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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef5f04076123cab1b7a926a7083db27fe0d7a0e575adb984854aae3f3a6507d"
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67c95dd97f5ccf6d837a9c115496ec7d36646fa86ca18e7f1412115b4c820ae2"
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "121df92eafb8f5286d4e8ff401c1e7db8384377f806db3f8db77b91e5b7bd4dd"
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_locid"
|
name = "icu_locid"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -3344,6 +3550,39 @@ version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
|
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a483403238cb7d6a876a77a5f8191780336d80fe7b8b00bfdeb20be6abbfd112"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_properties"
|
name = "icu_properties"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
|
|
@ -3393,6 +3632,49 @@ dependencies = [
|
||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1e52775179941363cc594e49ce99284d13d6948928d8e72c755f55e98caa1eb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_timezone"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa91ba6a585939a020c787235daa8aee856d9bceebd6355e283c0c310bc6de96"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_calendar",
|
||||||
|
"icu_provider",
|
||||||
|
"icu_timezone_data",
|
||||||
|
"tinystr",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_timezone_data"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1adcf7b613a268af025bc2a2532b4b9ee294e6051c5c0832d8bff20ac0232e68"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -5556,6 +5838,15 @@ dependencies = [
|
||||||
"regex-syntax 0.6.29",
|
"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]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
|
@ -7839,6 +8130,9 @@ name = "writeable"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x11-dl"
|
name = "x11-dl"
|
||||||
|
|
@ -8280,6 +8574,17 @@ dependencies = [
|
||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerotrie"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb594dd55d87335c5f60177cee24f19457a5ec10a065e0a3014722ad252d0a1f"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec"
|
name = "zerovec"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ vergen = { version = "8", features = ["git", "gitcl"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { version = "0.4", features = ["unstable-locales"] }
|
chrono = { version = "0.4", features = ["unstable-locales"] }
|
||||||
|
icu = { version = "1.5.0", features = [
|
||||||
|
"experimental",
|
||||||
|
"compiled_data",
|
||||||
|
"icu_datetime_experimental",
|
||||||
|
] }
|
||||||
# Completion-based IO runtime to enable io_uring / IOCP file IO support.
|
# Completion-based IO runtime to enable io_uring / IOCP file IO support.
|
||||||
compio = { version = "0.14.0", features = ["io", "macros", "runtime"] }
|
compio = { version = "0.14.0", features = ["io", "macros", "runtime"] }
|
||||||
cosmic-mime-apps = { git = "https://github.com/pop-os/cosmic-mime-apps.git", optional = true }
|
cosmic-mime-apps = { git = "https://github.com/pop-os/cosmic-mime-apps.git", optional = true }
|
||||||
|
|
|
||||||
26
src/app.rs
26
src/app.rs
|
|
@ -68,7 +68,10 @@ use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
||||||
config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig, TypeToSearch},
|
config::{
|
||||||
|
AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig, TimeConfig, TypeToSearch,
|
||||||
|
TIME_CONFIG_ID,
|
||||||
|
},
|
||||||
dialog::{Dialog, DialogKind, DialogMessage, DialogResult},
|
dialog::{Dialog, DialogKind, DialogMessage, DialogResult},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::key_binds,
|
key_bind::key_binds,
|
||||||
|
|
@ -371,6 +374,7 @@ pub enum Message {
|
||||||
Option<Vec<PathBuf>>,
|
Option<Vec<PathBuf>>,
|
||||||
),
|
),
|
||||||
TabView(Option<Entity>, tab::View),
|
TabView(Option<Entity>, tab::View),
|
||||||
|
TimeConfigChange(TimeConfig),
|
||||||
ToggleContextPage(ContextPage),
|
ToggleContextPage(ContextPage),
|
||||||
ToggleFoldersFirst,
|
ToggleFoldersFirst,
|
||||||
Undo(usize),
|
Undo(usize),
|
||||||
|
|
@ -3499,6 +3503,10 @@ impl Application for App {
|
||||||
config.view = view;
|
config.view = view;
|
||||||
return self.update(Message::TabConfig(config));
|
return self.update(Message::TabConfig(config));
|
||||||
}
|
}
|
||||||
|
Message::TimeConfigChange(time_config) => {
|
||||||
|
self.config.tab.military_time = time_config.military_time;
|
||||||
|
return self.update_config();
|
||||||
|
}
|
||||||
Message::ToggleContextPage(context_page) => {
|
Message::ToggleContextPage(context_page) => {
|
||||||
//TODO: ensure context menus are closed
|
//TODO: ensure context menus are closed
|
||||||
if self.context_page == context_page
|
if self.context_page == context_page
|
||||||
|
|
@ -5063,6 +5071,7 @@ impl Application for App {
|
||||||
struct ThemeSubscription;
|
struct ThemeSubscription;
|
||||||
struct WatcherSubscription;
|
struct WatcherSubscription;
|
||||||
struct TrashWatcherSubscription;
|
struct TrashWatcherSubscription;
|
||||||
|
struct TimeSubscription;
|
||||||
|
|
||||||
let mut subscriptions = vec![
|
let mut subscriptions = vec![
|
||||||
event::listen_with(|event, status, window_id| match event {
|
event::listen_with(|event, status, window_id| match event {
|
||||||
|
|
@ -5127,6 +5136,21 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::SystemThemeModeChange(update.config)
|
Message::SystemThemeModeChange(update.config)
|
||||||
}),
|
}),
|
||||||
|
cosmic_config::config_subscription::<_, TimeConfig>(
|
||||||
|
TypeId::of::<TimeSubscription>(),
|
||||||
|
TIME_CONFIG_ID.into(),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.map(|update| {
|
||||||
|
if !update.errors.is_empty() {
|
||||||
|
log::info!(
|
||||||
|
"errors loading time config {:?}: {:?}",
|
||||||
|
update.keys,
|
||||||
|
update.errors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Message::TimeConfigChange(update.config)
|
||||||
|
}),
|
||||||
Subscription::run_with_id(
|
Subscription::run_with_id(
|
||||||
TypeId::of::<WatcherSubscription>(),
|
TypeId::of::<WatcherSubscription>(),
|
||||||
stream::channel(100, |mut output| async move {
|
stream::channel(100, |mut output| async move {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use std::{any::TypeId, num::NonZeroU16, path::PathBuf};
|
use std::{any::TypeId, num::NonZeroU16, path::PathBuf};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, ConfigGet, CosmicConfigEntry},
|
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
||||||
iced::Subscription,
|
iced::Subscription,
|
||||||
theme, Application,
|
theme, Application,
|
||||||
};
|
};
|
||||||
|
|
@ -205,7 +205,7 @@ pub struct TabConfig {
|
||||||
pub show_hidden: bool,
|
pub show_hidden: bool,
|
||||||
/// Icon zoom
|
/// Icon zoom
|
||||||
pub icon_sizes: IconSizes,
|
pub icon_sizes: IconSizes,
|
||||||
#[serde(skip, default = "military_time_enabled")]
|
#[serde(skip)]
|
||||||
/// 24 hour clock; this is neither serialized nor deserialized because we use the user's global
|
/// 24 hour clock; this is neither serialized nor deserialized because we use the user's global
|
||||||
/// preference rather than save it
|
/// preference rather than save it
|
||||||
pub military_time: bool,
|
pub military_time: bool,
|
||||||
|
|
@ -220,27 +220,12 @@ impl Default for TabConfig {
|
||||||
folders_first: true,
|
folders_first: true,
|
||||||
show_hidden: false,
|
show_hidden: false,
|
||||||
icon_sizes: IconSizes::default(),
|
icon_sizes: IconSizes::default(),
|
||||||
military_time: military_time_enabled(),
|
military_time: false,
|
||||||
single_click: false,
|
single_click: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether the user enabled military time via the Time applet.
|
|
||||||
fn military_time_enabled() -> bool {
|
|
||||||
// Borrowed from COSMIC Greeter
|
|
||||||
match cosmic_config::Config::new("com.system76.CosmicAppletTime", 1) {
|
|
||||||
Ok(config_handler) => config_handler.get("military_time").unwrap_or_default(),
|
|
||||||
Err(err) => {
|
|
||||||
log::error!(
|
|
||||||
"failed to create CosmicAppletTime config handler: {:?}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct IconSizes {
|
pub struct IconSizes {
|
||||||
|
|
@ -270,3 +255,11 @@ impl IconSizes {
|
||||||
percent!(self.grid, ICON_SIZE_GRID) as _
|
percent!(self.grid, ICON_SIZE_GRID) as _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const TIME_CONFIG_ID: &str = "com.system76.CosmicAppletTime";
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, CosmicConfigEntry, PartialEq, Eq)]
|
||||||
|
#[version = 1]
|
||||||
|
pub struct TimeConfig {
|
||||||
|
pub military_time: bool,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ use std::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind},
|
app::{Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind},
|
||||||
config::{Config, Favorite, IconSizes, TabConfig},
|
config::{Config, Favorite, IconSizes, TabConfig, TimeConfig, TIME_CONFIG_ID},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::key_binds,
|
key_bind::key_binds,
|
||||||
localize::LANGUAGE_SORTER,
|
localize::LANGUAGE_SORTER,
|
||||||
|
|
@ -399,6 +399,7 @@ enum Message {
|
||||||
TabMessage(tab::Message),
|
TabMessage(tab::Message),
|
||||||
TabRescan(Location, Option<tab::Item>, Vec<tab::Item>),
|
TabRescan(Location, Option<tab::Item>, Vec<tab::Item>),
|
||||||
TabView(tab::View),
|
TabView(tab::View),
|
||||||
|
TimeConfigChange(TimeConfig),
|
||||||
ToggleFoldersFirst,
|
ToggleFoldersFirst,
|
||||||
ZoomDefault,
|
ZoomDefault,
|
||||||
ZoomIn,
|
ZoomIn,
|
||||||
|
|
@ -686,7 +687,10 @@ impl App {
|
||||||
|
|
||||||
fn update_config(&mut self) -> Task<Message> {
|
fn update_config(&mut self) -> Task<Message> {
|
||||||
self.update_nav_model();
|
self.update_nav_model();
|
||||||
Task::none()
|
|
||||||
|
self.update(Message::TabMessage(tab::Message::Config(
|
||||||
|
self.flags.config.tab,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate_nav_model_location(&mut self, location: &Location) {
|
fn activate_nav_model_location(&mut self, location: &Location) {
|
||||||
|
|
@ -1658,6 +1662,10 @@ impl Application for App {
|
||||||
Message::TabView(view) => {
|
Message::TabView(view) => {
|
||||||
self.tab.config.view = view;
|
self.tab.config.view = view;
|
||||||
}
|
}
|
||||||
|
Message::TimeConfigChange(time_config) => {
|
||||||
|
self.flags.config.tab.military_time = time_config.military_time;
|
||||||
|
return self.update_config();
|
||||||
|
}
|
||||||
Message::ToggleFoldersFirst => {
|
Message::ToggleFoldersFirst => {
|
||||||
self.tab.config.folders_first = !self.tab.config.folders_first;
|
self.tab.config.folders_first = !self.tab.config.folders_first;
|
||||||
}
|
}
|
||||||
|
|
@ -1741,6 +1749,7 @@ impl Application for App {
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
struct WatcherSubscription;
|
struct WatcherSubscription;
|
||||||
|
struct TimeSubscription;
|
||||||
let mut subscriptions = vec![
|
let mut subscriptions = vec![
|
||||||
event::listen_with(|event, status, _window_id| match event {
|
event::listen_with(|event, status, _window_id| match event {
|
||||||
Event::Keyboard(KeyEvent::KeyPressed { key, modifiers, .. }) => match status {
|
Event::Keyboard(KeyEvent::KeyPressed { key, modifiers, .. }) => match status {
|
||||||
|
|
@ -1765,6 +1774,21 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::Config(update.config)
|
Message::Config(update.config)
|
||||||
}),
|
}),
|
||||||
|
cosmic_config::config_subscription::<_, TimeConfig>(
|
||||||
|
TypeId::of::<TimeSubscription>(),
|
||||||
|
TIME_CONFIG_ID.into(),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.map(|update| {
|
||||||
|
if !update.errors.is_empty() {
|
||||||
|
log::info!(
|
||||||
|
"errors loading time config {:?}: {:?}",
|
||||||
|
update.keys,
|
||||||
|
update.errors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Message::TimeConfigChange(update.config)
|
||||||
|
}),
|
||||||
Subscription::run_with_id(
|
Subscription::run_with_id(
|
||||||
TypeId::of::<WatcherSubscription>(),
|
TypeId::of::<WatcherSubscription>(),
|
||||||
stream::channel(100, |mut output| async move {
|
stream::channel(100, |mut output| async move {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use i18n_embed::{
|
||||||
fluent::{fluent_language_loader, FluentLanguageLoader},
|
fluent::{fluent_language_loader, FluentLanguageLoader},
|
||||||
DefaultLocalizer, LanguageLoader, Localizer,
|
DefaultLocalizer, LanguageLoader, Localizer,
|
||||||
};
|
};
|
||||||
|
use icu::locid::Locale;
|
||||||
use icu_collator::{Collator, CollatorOptions, Numeric};
|
use icu_collator::{Collator, CollatorOptions, Numeric};
|
||||||
use icu_provider::DataLocale;
|
use icu_provider::DataLocale;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
@ -40,18 +41,29 @@ pub static LANGUAGE_SORTER: Lazy<Collator> = Lazy::new(|| {
|
||||||
.expect("Creating a collator from the system's current language, the fallback language, or American English should succeed")
|
.expect("Creating a collator from the system's current language, the fallback language, or American English should succeed")
|
||||||
});
|
});
|
||||||
|
|
||||||
pub static LANGUAGE_CHRONO: Lazy<chrono::Locale> = Lazy::new(|| {
|
pub static LOCALE: Lazy<Locale> = Lazy::new(|| {
|
||||||
std::env::var("LC_TIME")
|
fn get_local() -> Result<Locale, Box<dyn std::error::Error>> {
|
||||||
.or_else(|_| std::env::var("LANG"))
|
let locale = std::env::var("LC_TIME").or_else(|_| std::env::var("LANG"))?;
|
||||||
.ok()
|
|
||||||
.and_then(|locale_full| {
|
let locale = locale
|
||||||
// Split LANG because it may be set to a locale such as en_US.UTF8
|
.split('.')
|
||||||
locale_full
|
.next()
|
||||||
.split('.')
|
.ok_or(format!("Can't split the locale {locale}"))?;
|
||||||
.next()
|
|
||||||
.and_then(|locale| chrono::Locale::from_str(locale).ok())
|
let locale = Locale::from_str(locale).map_err(|e| format!("{e:?}"))?;
|
||||||
})
|
|
||||||
.unwrap_or(chrono::Locale::en_US)
|
Ok(locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
match get_local() {
|
||||||
|
Ok(locale) => locale,
|
||||||
|
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("can't get locale {e}");
|
||||||
|
|
||||||
|
Locale::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
||||||
162
src/tab.rs
162
src/tab.rs
|
|
@ -37,8 +37,12 @@ use cosmic::{
|
||||||
Element,
|
Element,
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||||
use i18n_embed::LanguageLoader;
|
use i18n_embed::LanguageLoader;
|
||||||
|
use icu::datetime::{
|
||||||
|
options::{components, preferences},
|
||||||
|
DateTimeFormatter, DateTimeFormatterOptions,
|
||||||
|
};
|
||||||
use mime_guess::{mime, Mime};
|
use mime_guess::{mime, Mime};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -64,7 +68,7 @@ use crate::{
|
||||||
config::{DesktopConfig, IconSizes, TabConfig, ICON_SCALE_MAX, ICON_SIZE_GRID},
|
config::{DesktopConfig, IconSizes, TabConfig, ICON_SCALE_MAX, ICON_SIZE_GRID},
|
||||||
dialog::DialogKind,
|
dialog::DialogKind,
|
||||||
fl,
|
fl,
|
||||||
localize::{LANGUAGE_CHRONO, LANGUAGE_SORTER},
|
localize::{LANGUAGE_SORTER, LOCALE},
|
||||||
menu, mime_app,
|
menu, mime_app,
|
||||||
mime_icon::{mime_for_path, mime_icon},
|
mime_icon::{mime_for_path, mime_icon},
|
||||||
mounter::MOUNTERS,
|
mounter::MOUNTERS,
|
||||||
|
|
@ -85,11 +89,6 @@ const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32);
|
||||||
|
|
||||||
const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
||||||
|
|
||||||
//TODO: adjust for locales?
|
|
||||||
const DATE_TIME_FORMAT: &str = "%b %-d, %-Y, %-I:%M %p";
|
|
||||||
const DATE_TIME_FORMAT_MILITARY: &str = "%b %-d, %-Y, %-H:%M %p";
|
|
||||||
const TIME_FORMAT: &str = "%-I:%M %p";
|
|
||||||
const TIME_FORMAT_MILITARY: &str = "%-H:%M %p";
|
|
||||||
static SPECIAL_DIRS: Lazy<HashMap<PathBuf, &'static str>> = Lazy::new(|| {
|
static SPECIAL_DIRS: Lazy<HashMap<PathBuf, &'static str>> = Lazy::new(|| {
|
||||||
let mut special_dirs = HashMap::new();
|
let mut special_dirs = HashMap::new();
|
||||||
if let Some(dir) = dirs::document_dir() {
|
if let Some(dir) = dirs::document_dir() {
|
||||||
|
|
@ -382,13 +381,50 @@ fn format_permissions(metadata: &Metadata, owner: PermissionOwner) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FormatTime {
|
fn date_time_formatter(military_time: bool) -> DateTimeFormatter {
|
||||||
pub time: SystemTime,
|
let mut bag = components::Bag::empty();
|
||||||
pub military_time: bool,
|
bag.day = Some(components::Day::NumericDayOfMonth);
|
||||||
|
bag.month = Some(components::Month::Short);
|
||||||
|
bag.year = Some(components::Year::Numeric);
|
||||||
|
bag = bag.merge(time_bag(military_time));
|
||||||
|
let options = DateTimeFormatterOptions::Components(bag);
|
||||||
|
|
||||||
|
DateTimeFormatter::try_new_experimental(&LOCALE.as_ref().into(), options)
|
||||||
|
.expect("failed to create DateTimeFormatter")
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormatTime {
|
fn time_formatter(military_time: bool) -> DateTimeFormatter {
|
||||||
fn from_secs(secs: i64, military_time: bool) -> Option<Self> {
|
let options = DateTimeFormatterOptions::Components(time_bag(military_time));
|
||||||
|
|
||||||
|
DateTimeFormatter::try_new_experimental(&LOCALE.as_ref().into(), options)
|
||||||
|
.expect("failed to create DateTimeFormatter")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time_bag(military_time: bool) -> components::Bag {
|
||||||
|
let mut bag = components::Bag::empty();
|
||||||
|
bag.hour = Some(components::Numeric::Numeric);
|
||||||
|
bag.minute = Some(components::Numeric::Numeric);
|
||||||
|
let hour_cyle = if military_time {
|
||||||
|
preferences::HourCycle::H23
|
||||||
|
} else {
|
||||||
|
preferences::HourCycle::H12
|
||||||
|
};
|
||||||
|
bag.preferences = Some(preferences::Bag::from_hour_cycle(hour_cyle));
|
||||||
|
bag
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FormatTime<'a> {
|
||||||
|
pub time: SystemTime,
|
||||||
|
pub date_time_formatter: &'a DateTimeFormatter,
|
||||||
|
pub time_formatter: &'a DateTimeFormatter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FormatTime<'a> {
|
||||||
|
fn from_secs(
|
||||||
|
secs: i64,
|
||||||
|
date_time_formatter: &'a DateTimeFormatter,
|
||||||
|
time_formatter: &'a DateTimeFormatter,
|
||||||
|
) -> Option<Self> {
|
||||||
// This looks convoluted because we need to ensure the units match up
|
// This looks convoluted because we need to ensure the units match up
|
||||||
let secs: u64 = secs.try_into().ok()?;
|
let secs: u64 = secs.try_into().ok()?;
|
||||||
let now = SystemTime::now();
|
let now = SystemTime::now();
|
||||||
|
|
@ -400,48 +436,57 @@ impl FormatTime {
|
||||||
.map(Duration::from_secs)?;
|
.map(Duration::from_secs)?;
|
||||||
now.checked_sub(filetime_diff).map(|time| Self {
|
now.checked_sub(filetime_diff).map(|time| Self {
|
||||||
time,
|
time,
|
||||||
military_time,
|
date_time_formatter,
|
||||||
|
time_formatter,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FormatTime {
|
impl Display for FormatTime<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let date_time = chrono::DateTime::<chrono::Local>::from(self.time);
|
let datetime = chrono::DateTime::<chrono::Local>::from(self.time);
|
||||||
let now = chrono::Local::now();
|
let now = chrono::Local::now();
|
||||||
if date_time.date_naive() == now.date_naive() {
|
let icu_datetime = icu::calendar::DateTime::try_new_iso_datetime(
|
||||||
|
datetime.year(),
|
||||||
|
datetime.month() as u8,
|
||||||
|
datetime.day() as u8,
|
||||||
|
datetime.hour() as u8,
|
||||||
|
datetime.minute() as u8,
|
||||||
|
datetime.second() as u8,
|
||||||
|
)
|
||||||
|
.expect("failed to construct DateTime")
|
||||||
|
.to_any();
|
||||||
|
|
||||||
|
if datetime.date_naive() == now.date_naive() {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}, {}",
|
"{}, {}",
|
||||||
fl!("today"),
|
fl!("today"),
|
||||||
date_time.format_localized(
|
self.time_formatter
|
||||||
if self.military_time {
|
.format(&icu_datetime)
|
||||||
TIME_FORMAT_MILITARY
|
.map_err(|_| fmt::Error)?
|
||||||
} else {
|
|
||||||
TIME_FORMAT
|
|
||||||
},
|
|
||||||
*LANGUAGE_CHRONO
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
date_time
|
write!(
|
||||||
.format_localized(
|
f,
|
||||||
if self.military_time {
|
"{}",
|
||||||
DATE_TIME_FORMAT_MILITARY
|
self.date_time_formatter
|
||||||
} else {
|
.format(&icu_datetime)
|
||||||
DATE_TIME_FORMAT
|
.map_err(|_| fmt::Error)?
|
||||||
},
|
)
|
||||||
*LANGUAGE_CHRONO,
|
|
||||||
)
|
|
||||||
.fmt(f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn format_time(time: SystemTime, military_time: bool) -> FormatTime {
|
const fn format_time<'a>(
|
||||||
|
time: SystemTime,
|
||||||
|
date_time_formatter: &'a DateTimeFormatter,
|
||||||
|
time_formatter: &'a DateTimeFormatter,
|
||||||
|
) -> FormatTime<'a> {
|
||||||
FormatTime {
|
FormatTime {
|
||||||
time,
|
time,
|
||||||
military_time,
|
date_time_formatter,
|
||||||
|
time_formatter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1593,24 +1638,30 @@ impl Item {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let date_time_formatter = date_time_formatter(military_time);
|
||||||
|
let time_formatter = time_formatter(military_time);
|
||||||
|
|
||||||
if let Ok(time) = metadata.created() {
|
if let Ok(time) = metadata.created() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-created",
|
"item-created",
|
||||||
created = format_time(time, military_time).to_string()
|
created =
|
||||||
|
format_time(time, &date_time_formatter, &time_formatter).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(time) = metadata.modified() {
|
if let Ok(time) = metadata.modified() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-modified",
|
"item-modified",
|
||||||
modified = format_time(time, military_time).to_string()
|
modified =
|
||||||
|
format_time(time, &date_time_formatter, &time_formatter).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(time) = metadata.accessed() {
|
if let Ok(time) = metadata.accessed() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-accessed",
|
"item-accessed",
|
||||||
accessed = format_time(time, military_time).to_string()
|
accessed =
|
||||||
|
format_time(time, &date_time_formatter, &time_formatter).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1703,9 +1754,12 @@ impl Item {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
if let Ok(time) = metadata.modified() {
|
if let Ok(time) = metadata.modified() {
|
||||||
|
let date_time_formatter = date_time_formatter(military_time);
|
||||||
|
let time_formatter = time_formatter(military_time);
|
||||||
|
|
||||||
column = column.push(widget::text::body(format!(
|
column = column.push(widget::text::body(format!(
|
||||||
"Last modified: {}",
|
"Last modified: {}",
|
||||||
format_time(time, military_time)
|
format_time(time, &date_time_formatter, &time_formatter)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1827,6 +1881,8 @@ pub struct Tab {
|
||||||
last_scroll_position: Option<Point>,
|
last_scroll_position: Option<Point>,
|
||||||
last_scroll_offset: Option<Point>,
|
last_scroll_offset: Option<Point>,
|
||||||
scroll_bounds_opt: Option<Rectangle>,
|
scroll_bounds_opt: Option<Rectangle>,
|
||||||
|
date_time_formatter: DateTimeFormatter,
|
||||||
|
time_formatter: DateTimeFormatter,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
||||||
|
|
@ -1921,6 +1977,8 @@ impl Tab {
|
||||||
last_scroll_position: None,
|
last_scroll_position: None,
|
||||||
last_scroll_offset: None,
|
last_scroll_offset: None,
|
||||||
scroll_bounds_opt: None,
|
scroll_bounds_opt: None,
|
||||||
|
date_time_formatter: date_time_formatter(config.military_time),
|
||||||
|
time_formatter: time_formatter(config.military_time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2523,9 +2581,14 @@ impl Tab {
|
||||||
// View is preserved for existing tabs
|
// View is preserved for existing tabs
|
||||||
let view = self.config.view;
|
let view = self.config.view;
|
||||||
let show_hidden = self.config.show_hidden;
|
let show_hidden = self.config.show_hidden;
|
||||||
|
let military_time_changed = self.config.military_time != config.military_time;
|
||||||
self.config = config;
|
self.config = config;
|
||||||
self.config.view = view;
|
self.config.view = view;
|
||||||
self.config.show_hidden = show_hidden;
|
self.config.show_hidden = show_hidden;
|
||||||
|
if military_time_changed {
|
||||||
|
self.date_time_formatter = date_time_formatter(self.config.military_time);
|
||||||
|
self.time_formatter = time_formatter(self.config.military_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::ContextAction(action) => {
|
Message::ContextAction(action) => {
|
||||||
// Close context menu
|
// Close context menu
|
||||||
|
|
@ -4386,17 +4449,18 @@ impl Tab {
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let military_time = self.config.military_time;
|
|
||||||
let modified_text = match &item.metadata {
|
let modified_text = match &item.metadata {
|
||||||
ItemMetadata::Path { metadata, .. } => match metadata.modified() {
|
ItemMetadata::Path { metadata, .. } => match metadata.modified() {
|
||||||
Ok(time) => format_time(time, military_time).to_string(),
|
Ok(time) => self.format_time(time).to_string(),
|
||||||
Err(_) => String::new(),
|
Err(_) => String::new(),
|
||||||
},
|
},
|
||||||
ItemMetadata::Trash { entry, .. } => {
|
ItemMetadata::Trash { entry, .. } => FormatTime::from_secs(
|
||||||
FormatTime::from_secs(entry.time_deleted, military_time)
|
entry.time_deleted,
|
||||||
.map(|t| t.to_string())
|
&self.date_time_formatter,
|
||||||
.unwrap_or_default()
|
&self.time_formatter,
|
||||||
}
|
)
|
||||||
|
.map(|t| t.to_string())
|
||||||
|
.unwrap_or_default(),
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -5102,6 +5166,10 @@ impl Tab {
|
||||||
|
|
||||||
Subscription::batch(subscriptions)
|
Subscription::batch(subscriptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_time<'a>(&'a self, time: SystemTime) -> FormatTime<'a> {
|
||||||
|
format_time(time, &self.date_time_formatter, &self.time_formatter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn respond_to_scroll_direction(delta: ScrollDelta, modifiers: Modifiers) -> Option<Message> {
|
pub fn respond_to_scroll_direction(delta: ScrollDelta, modifiers: Modifiers) -> Option<Message> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue