Switch to jiff from time

This commit is contained in:
Joscha 2024-12-04 20:56:39 +01:00
parent 2ecc482533
commit f471b9ce00
19 changed files with 194 additions and 253 deletions

275
Cargo.lock generated
View file

@ -55,9 +55,9 @@ dependencies = [
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.7" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
@ -95,9 +95,9 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.80" version = "0.1.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -125,17 +125,11 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
@ -182,9 +176,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.4" version = "4.5.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -192,9 +186,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.2" version = "4.5.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -204,9 +198,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.4" version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -226,12 +220,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "const_fn"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d"
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.18.1" version = "0.18.1"
@ -244,9 +232,9 @@ dependencies = [
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -254,9 +242,9 @@ dependencies = [
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.6" version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "cove" name = "cove"
@ -271,6 +259,7 @@ dependencies = [
"crossterm", "crossterm",
"directories", "directories",
"euphoxide", "euphoxide",
"jiff",
"linkify", "linkify",
"log", "log",
"once_cell", "once_cell",
@ -279,10 +268,8 @@ dependencies = [
"rusqlite", "rusqlite",
"serde_json", "serde_json",
"thiserror", "thiserror",
"time",
"tokio", "tokio",
"toss", "toss",
"tz-rs",
"unicode-width", "unicode-width",
"vault", "vault",
] ]
@ -339,7 +326,7 @@ dependencies = [
"bitflags", "bitflags",
"crossterm_winapi", "crossterm_winapi",
"libc", "libc",
"mio", "mio 0.8.11",
"parking_lot", "parking_lot",
"signal-hook", "signal-hook",
"signal-hook-mio", "signal-hook-mio",
@ -378,7 +365,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
"serde",
] ]
[[package]] [[package]]
@ -447,17 +433,17 @@ dependencies = [
[[package]] [[package]]
name = "euphoxide" name = "euphoxide"
version = "0.5.1" version = "0.5.1"
source = "git+https://github.com/Garmelon/euphoxide.git?tag=v0.5.1#0256329f65f3ed853092cc210ae2a4a8c526a4bf" source = "git+https://github.com/Garmelon/euphoxide.git#fe6869493225abb1229631816ffdc2fdae5d32e3"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"caseless", "caseless",
"clap", "clap",
"cookie", "cookie",
"futures-util", "futures-util",
"jiff",
"log", "log",
"serde", "serde",
"serde_json", "serde_json",
"time",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tokio-tungstenite", "tokio-tungstenite",
@ -488,38 +474,29 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -580,12 +557,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]] [[package]]
name = "home" name = "home"
version = "0.5.9" version = "0.5.9"
@ -612,16 +583,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.2.6"
@ -664,10 +625,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "libc" name = "jiff"
version = "0.2.155" version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" checksum = "db69f08d4fb10524cacdb074c10b296299d71274ddbc830a8ee65666867002e9"
dependencies = [
"jiff-tzdb-platform",
"serde",
"windows-sys 0.52.0",
]
[[package]]
name = "jiff-tzdb"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653"
[[package]]
name = "jiff-tzdb-platform"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329"
dependencies = [
"jiff-tzdb",
]
[[package]]
name = "libc"
version = "0.2.167"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
[[package]] [[package]]
name = "libredox" name = "libredox"
@ -717,9 +704,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "memchr" name = "memchr"
@ -748,6 +735,17 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "mio"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
"wasi",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -763,16 +761,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.32.2" version = "0.32.2"
@ -849,12 +837,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.14" version = "0.2.14"
@ -1033,12 +1015,11 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.22.4" version = "0.23.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
dependencies = [ dependencies = [
"log", "once_cell",
"ring",
"rustls-pki-types", "rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"subtle", "subtle",
@ -1047,38 +1028,27 @@ dependencies = [
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.7.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
dependencies = [ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pemfile",
"rustls-pki-types", "rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework",
] ]
[[package]]
name = "rustls-pemfile"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
dependencies = [
"base64",
"rustls-pki-types",
]
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.7.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.102.4" version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
@ -1108,9 +1078,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.11.0" version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"core-foundation", "core-foundation",
@ -1121,9 +1091,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.11.0" version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -1131,9 +1101,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.202" version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -1150,9 +1120,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.202" version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1171,11 +1141,12 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.117" version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr",
"ryu", "ryu",
"serde", "serde",
] ]
@ -1217,7 +1188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [ dependencies = [
"libc", "libc",
"mio", "mio 0.8.11",
"signal-hook", "signal-hook",
] ]
@ -1275,9 +1246,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.65" version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1364,28 +1335,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.37.0" version = "1.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
"libc", "libc",
"mio", "mio 1.0.3",
"num_cpus",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.2.0" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1394,9 +1364,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.25.0" version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-pki-types", "rustls-pki-types",
@ -1405,9 +1375,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.15" version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@ -1416,9 +1386,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-tungstenite" name = "tokio-tungstenite"
version = "0.21.0" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"log", "log",
@ -1478,9 +1448,9 @@ dependencies = [
[[package]] [[package]]
name = "tungstenite" name = "tungstenite"
version = "0.21.0" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"bytes", "bytes",
@ -1493,7 +1463,6 @@ dependencies = [
"rustls-pki-types", "rustls-pki-types",
"sha1", "sha1",
"thiserror", "thiserror",
"url",
"utf-8", "utf-8",
] ]
@ -1503,21 +1472,6 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "tz-rs"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4"
dependencies = [
"const_fn",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
@ -1532,9 +1486,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [ dependencies = [
"tinyvec", "tinyvec",
] ]
@ -1557,17 +1511,6 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]] [[package]]
name = "utf-8" name = "utf-8"
version = "0.7.6" version = "0.7.6"

View file

@ -14,6 +14,7 @@ cookie = "0.18.1"
crossterm = "0.27.0" crossterm = "0.27.0"
directories = "5.0.1" directories = "5.0.1"
edit = "0.1.5" edit = "0.1.5"
jiff = "0.1.15"
linkify = "0.10.0" linkify = "0.10.0"
log = { version = "0.4.21", features = ["std"] } log = { version = "0.4.21", features = ["std"] }
once_cell = "1.19.0" once_cell = "1.19.0"
@ -29,18 +30,12 @@ syn = "2.0.65"
thiserror = "1.0.61" thiserror = "1.0.61"
tokio = { version = "1.37.0", features = ["full"] } tokio = { version = "1.37.0", features = ["full"] }
toml = "0.8.13" toml = "0.8.13"
tz-rs = "0.6.14"
unicode-width = "0.1.12" unicode-width = "0.1.12"
[workspace.dependencies.euphoxide] [workspace.dependencies.euphoxide]
git = "https://github.com/Garmelon/euphoxide.git" git = "https://github.com/Garmelon/euphoxide.git"
tag = "v0.5.1"
features = ["bot"] features = ["bot"]
[workspace.dependencies.time]
version = "0.3.36"
features = ["macros", "formatting", "parsing", "serde"]
[workspace.dependencies.toss] [workspace.dependencies.toss]
git = "https://github.com/Garmelon/toss.git" git = "https://github.com/Garmelon/toss.git"
tag = "v0.2.3" tag = "v0.2.3"

View file

@ -14,6 +14,7 @@ cookie.workspace = true
crossterm.workspace = true crossterm.workspace = true
directories.workspace = true directories.workspace = true
euphoxide.workspace = true euphoxide.workspace = true
jiff.workspace = true
linkify.workspace = true linkify.workspace = true
log.workspace = true log.workspace = true
once_cell.workspace = true once_cell.workspace = true
@ -22,10 +23,8 @@ parking_lot.workspace = true
rusqlite.workspace = true rusqlite.workspace = true
serde_json.workspace = true serde_json.workspace = true
thiserror.workspace = true thiserror.workspace = true
time.workspace = true
tokio.workspace = true tokio.workspace = true
toss.workspace = true toss.workspace = true
tz-rs.workspace = true
unicode-width.workspace = true unicode-width.workspace = true
vault.workspace = true vault.workspace = true

View file

@ -2,9 +2,8 @@ use std::mem;
use crossterm::style::Stylize; use crossterm::style::Stylize;
use euphoxide::api::{MessageId, Snowflake, Time}; use euphoxide::api::{MessageId, Snowflake, Time};
use time::OffsetDateTime; use jiff::Timestamp;
use toss::{Style, Styled}; use toss::{Style, Styled};
use tz::TimeZone;
use crate::store::Msg; use crate::store::Msg;
use crate::ui::ChatMsg; use crate::ui::ChatMsg;
@ -208,7 +207,6 @@ pub struct SmallMessage {
pub id: MessageId, pub id: MessageId,
pub parent: Option<MessageId>, pub parent: Option<MessageId>,
pub time: Time, pub time: Time,
pub time_zone: &'static TimeZone,
pub nick: String, pub nick: String,
pub content: String, pub content: String,
pub seen: bool, pub seen: bool,
@ -272,8 +270,8 @@ impl Msg for SmallMessage {
} }
impl ChatMsg for SmallMessage { impl ChatMsg for SmallMessage {
fn time(&self) -> Option<OffsetDateTime> { fn time(&self) -> Option<Timestamp> {
crate::util::convert_to_time_zone(self.time_zone, self.time.0) Some(self.time.as_timestamp())
} }
fn styled(&self) -> (Styled, Styled) { fn styled(&self) -> (Styled, Styled) {

View file

@ -1,16 +1,13 @@
use std::io::Write; use std::io::Write;
use euphoxide::api::MessageId; use euphoxide::api::MessageId;
use time::format_description::FormatItem;
use time::macros::format_description;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use crate::euph::SmallMessage; use crate::euph::SmallMessage;
use crate::store::Tree; use crate::store::Tree;
use crate::vault::EuphRoomVault; use crate::vault::EuphRoomVault;
const TIME_FORMAT: &[FormatItem<'_>] = const TIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S";
format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
const TIME_EMPTY: &str = " "; const TIME_EMPTY: &str = " ";
pub async fn export<W: Write>(vault: &EuphRoomVault, out: &mut W) -> anyhow::Result<()> { pub async fn export<W: Write>(vault: &EuphRoomVault, out: &mut W) -> anyhow::Result<()> {
@ -67,11 +64,7 @@ fn write_msg<W: Write>(
for (i, line) in msg.content.lines().enumerate() { for (i, line) in msg.content.lines().enumerate() {
if i == 0 { if i == 0 {
let time = msg let time = msg.time.as_timestamp().strftime(TIME_FORMAT);
.time
.0
.format(TIME_FORMAT)
.expect("time can be formatted");
writeln!(file, "{time} {indent_string}[{nick}] {line}")?; writeln!(file, "{time} {indent_string}[{nick}] {line}")?;
} else { } else {
writeln!(file, "{TIME_EMPTY} {indent_string}| {nick_empty} {line}")?; writeln!(file, "{TIME_EMPTY} {indent_string}| {nick_empty} {line}")?;

View file

@ -4,9 +4,9 @@ use std::vec;
use async_trait::async_trait; use async_trait::async_trait;
use crossterm::style::Stylize; use crossterm::style::Stylize;
use jiff::Timestamp;
use log::{Level, LevelFilter, Log}; use log::{Level, LevelFilter, Log};
use parking_lot::Mutex; use parking_lot::Mutex;
use time::OffsetDateTime;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use toss::{Style, Styled}; use toss::{Style, Styled};
@ -16,7 +16,7 @@ use crate::ui::ChatMsg;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LogMsg { pub struct LogMsg {
id: usize, id: usize,
time: OffsetDateTime, time: Timestamp,
level: Level, level: Level,
content: String, content: String,
} }
@ -42,7 +42,7 @@ impl Msg for LogMsg {
} }
impl ChatMsg for LogMsg { impl ChatMsg for LogMsg {
fn time(&self) -> Option<OffsetDateTime> { fn time(&self) -> Option<Timestamp> {
Some(self.time) Some(self.time)
} }
@ -209,7 +209,7 @@ impl Log for Logger {
let mut guard = self.messages.lock(); let mut guard = self.messages.lock();
let msg = LogMsg { let msg = LogMsg {
id: guard.len(), id: guard.len(),
time: OffsetDateTime::now_utc(), time: Timestamp::now(),
level: record.level(), level: record.level(),
content: format!("<{}> {}", record.target(), record.args()), content: format!("<{}> {}", record.target(), record.args()),
}; };

View file

@ -118,16 +118,12 @@ fn update_config_with_args(config: &mut Config, args: &Args) {
} }
fn open_vault(config: &Config, dirs: &ProjectDirs) -> anyhow::Result<Vault> { fn open_vault(config: &Config, dirs: &ProjectDirs) -> anyhow::Result<Vault> {
let time_zone =
util::load_time_zone(config.time_zone_ref()).context("failed to load time zone")?;
let time_zone = Box::leak(Box::new(time_zone));
let vault = if config.ephemeral { let vault = if config.ephemeral {
vault::launch_in_memory(time_zone)? vault::launch_in_memory()?
} else { } else {
let data_dir = data_dir(config, dirs); let data_dir = data_dir(config, dirs);
eprintln!("Data dir: {}", data_dir.to_string_lossy()); eprintln!("Data dir: {}", data_dir.to_string_lossy());
vault::launch(&data_dir.join("vault.db"), time_zone)? vault::launch(&data_dir.join("vault.db"))?
}; };
Ok(vault) Ok(vault)
@ -174,11 +170,13 @@ async fn run(
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
info!("Welcome to {NAME} {VERSION}",); info!("Welcome to {NAME} {VERSION}",);
let tz = util::load_time_zone(config.time_zone_ref()).context("failed to load time zone")?;
let vault = open_vault(config, dirs)?; let vault = open_vault(config, dirs)?;
let mut terminal = Terminal::new()?; let mut terminal = Terminal::new()?;
terminal.set_measuring(config.measure_widths); terminal.set_measuring(config.measure_widths);
Ui::run(config, &mut terminal, vault.clone(), logger, logger_rx).await?; Ui::run(config, tz, &mut terminal, vault.clone(), logger, logger_rx).await?;
drop(terminal); drop(terminal);
vault.close().await; vault.close().await;

View file

@ -12,6 +12,7 @@ use std::time::{Duration, Instant};
use cove_config::Config; use cove_config::Config;
use cove_input::InputEvent; use cove_input::InputEvent;
use jiff::tz::TimeZone;
use parking_lot::FairMutex; use parking_lot::FairMutex;
use tokio::sync::mpsc::error::TryRecvError; use tokio::sync::mpsc::error::TryRecvError;
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
@ -84,6 +85,7 @@ impl Ui {
pub async fn run( pub async fn run(
config: &'static Config, config: &'static Config,
tz: TimeZone,
terminal: &mut Terminal, terminal: &mut Terminal,
vault: Vault, vault: Vault,
logger: Logger, logger: Logger,
@ -112,8 +114,8 @@ impl Ui {
config, config,
event_tx: event_tx.clone(), event_tx: event_tx.clone(),
mode: Mode::Main, mode: Mode::Main,
rooms: Rooms::new(config, vault, event_tx.clone()).await, rooms: Rooms::new(config, tz.clone(), vault, event_tx.clone()).await,
log_chat: ChatState::new(logger), log_chat: ChatState::new(logger, tz),
key_bindings_visible: false, key_bindings_visible: false,
key_bindings_list: ListState::new(), key_bindings_list: ListState::new(),
}; };

View file

@ -6,7 +6,8 @@ mod widgets;
use cove_config::Keys; use cove_config::Keys;
use cove_input::InputEvent; use cove_input::InputEvent;
use time::OffsetDateTime; use jiff::tz::TimeZone;
use jiff::Timestamp;
use toss::widgets::{BoxedAsync, EditorState}; use toss::widgets::{BoxedAsync, EditorState};
use toss::{Styled, WidgetExt}; use toss::{Styled, WidgetExt};
@ -19,7 +20,7 @@ use self::tree::TreeViewState;
use super::UiError; use super::UiError;
pub trait ChatMsg { pub trait ChatMsg {
fn time(&self) -> Option<OffsetDateTime>; fn time(&self) -> Option<Timestamp>;
fn styled(&self) -> (Styled, Styled); fn styled(&self) -> (Styled, Styled);
fn edit(nick: &str, content: &str) -> (Styled, Styled); fn edit(nick: &str, content: &str) -> (Styled, Styled);
fn pseudo(nick: &str, content: &str) -> (Styled, Styled); fn pseudo(nick: &str, content: &str) -> (Styled, Styled);
@ -41,14 +42,14 @@ pub struct ChatState<M: Msg, S: MsgStore<M>> {
} }
impl<M: Msg, S: MsgStore<M> + Clone> ChatState<M, S> { impl<M: Msg, S: MsgStore<M> + Clone> ChatState<M, S> {
pub fn new(store: S) -> Self { pub fn new(store: S, tz: TimeZone) -> Self {
Self { Self {
cursor: Cursor::Bottom, cursor: Cursor::Bottom,
editor: EditorState::new(), editor: EditorState::new(),
caesar: 0, caesar: 0,
mode: Mode::Tree, mode: Mode::Tree,
tree: TreeViewState::new(store.clone()), tree: TreeViewState::new(store.clone(), tz),
store, store,
} }

View file

@ -11,6 +11,7 @@ use std::collections::HashSet;
use async_trait::async_trait; use async_trait::async_trait;
use cove_config::Keys; use cove_config::Keys;
use cove_input::InputEvent; use cove_input::InputEvent;
use jiff::tz::TimeZone;
use toss::widgets::EditorState; use toss::widgets::EditorState;
use toss::{AsyncWidget, Frame, Pos, Size, WidgetExt, WidthDb}; use toss::{AsyncWidget, Frame, Pos, Size, WidgetExt, WidthDb};
@ -25,6 +26,7 @@ use super::Reaction;
pub struct TreeViewState<M: Msg, S: MsgStore<M>> { pub struct TreeViewState<M: Msg, S: MsgStore<M>> {
store: S, store: S,
tz: TimeZone,
last_size: Size, last_size: Size,
last_nick: String, last_nick: String,
@ -36,9 +38,10 @@ pub struct TreeViewState<M: Msg, S: MsgStore<M>> {
} }
impl<M: Msg, S: MsgStore<M>> TreeViewState<M, S> { impl<M: Msg, S: MsgStore<M>> TreeViewState<M, S> {
pub fn new(store: S) -> Self { pub fn new(store: S, tz: TimeZone) -> Self {
Self { Self {
store, store,
tz,
last_size: Size::ZERO, last_size: Size::ZERO,
last_nick: String::new(), last_nick: String::new(),
last_cursor: Cursor::Bottom, last_cursor: Cursor::Bottom,
@ -443,6 +446,7 @@ where
let mut renderer = TreeRenderer::new( let mut renderer = TreeRenderer::new(
context, context,
&self.state.store, &self.state.store,
&self.state.tz,
&mut self.state.folded, &mut self.state.folded,
self.cursor, self.cursor,
self.editor, self.editor,

View file

@ -4,6 +4,7 @@ use std::collections::HashSet;
use std::convert::Infallible; use std::convert::Infallible;
use async_trait::async_trait; use async_trait::async_trait;
use jiff::tz::TimeZone;
use toss::widgets::{EditorState, Empty, Predrawn, Resize}; use toss::widgets::{EditorState, Empty, Predrawn, Resize};
use toss::{Size, Widget, WidthDb}; use toss::{Size, Widget, WidthDb};
@ -81,6 +82,7 @@ pub struct TreeRenderer<'a, M: Msg, S: MsgStore<M>> {
context: TreeContext<M::Id>, context: TreeContext<M::Id>,
store: &'a S, store: &'a S,
tz: &'a TimeZone,
folded: &'a mut HashSet<M::Id>, folded: &'a mut HashSet<M::Id>,
cursor: &'a mut Cursor<M::Id>, cursor: &'a mut Cursor<M::Id>,
editor: &'a mut EditorState, editor: &'a mut EditorState,
@ -108,6 +110,7 @@ where
pub fn new( pub fn new(
context: TreeContext<M::Id>, context: TreeContext<M::Id>,
store: &'a S, store: &'a S,
tz: &'a TimeZone,
folded: &'a mut HashSet<M::Id>, folded: &'a mut HashSet<M::Id>,
cursor: &'a mut Cursor<M::Id>, cursor: &'a mut Cursor<M::Id>,
editor: &'a mut EditorState, editor: &'a mut EditorState,
@ -116,6 +119,7 @@ where
Self { Self {
context, context,
store, store,
tz,
folded, folded,
cursor, cursor,
editor, editor,
@ -191,7 +195,14 @@ where
}; };
let highlighted = highlighted && self.context.focused; let highlighted = highlighted && self.context.focused;
let widget = widgets::msg(highlighted, indent, msg, self.context.caesar, folded_info); let widget = widgets::msg(
highlighted,
self.tz.clone(),
indent,
msg,
self.context.caesar,
folded_info,
);
let widget = Self::predraw(widget, self.context.size, self.widthdb); let widget = Self::predraw(widget, self.context.size, self.widthdb);
Block::new(TreeBlockId::Msg(msg_id), widget, true) Block::new(TreeBlockId::Msg(msg_id), widget, true)
} }

View file

@ -37,6 +37,7 @@ where
let mut renderer = TreeRenderer::new( let mut renderer = TreeRenderer::new(
context, context,
&self.store, &self.store,
&self.tz,
&mut self.folded, &mut self.folded,
cursor, cursor,
editor, editor,
@ -64,6 +65,7 @@ where
let mut renderer = TreeRenderer::new( let mut renderer = TreeRenderer::new(
context, context,
&self.store, &self.store,
&self.tz,
&mut self.folded, &mut self.folded,
cursor, cursor,
editor, editor,

View file

@ -1,6 +1,7 @@
use std::convert::Infallible; use std::convert::Infallible;
use crossterm::style::Stylize; use crossterm::style::Stylize;
use jiff::tz::TimeZone;
use toss::widgets::{Boxed, EditorState, Join2, Join4, Join5, Text}; use toss::widgets::{Boxed, EditorState, Join2, Join4, Join5, Text};
use toss::{Style, Styled, WidgetExt}; use toss::{Style, Styled, WidgetExt};
@ -49,6 +50,7 @@ fn style_pseudo_highlight() -> Style {
pub fn msg<M: Msg + ChatMsg>( pub fn msg<M: Msg + ChatMsg>(
highlighted: bool, highlighted: bool,
tz: TimeZone,
indent: usize, indent: usize,
msg: &M, msg: &M,
caesar: i8, caesar: i8,
@ -72,7 +74,7 @@ pub fn msg<M: Msg + ChatMsg>(
Join5::horizontal( Join5::horizontal(
Seen::new(msg.seen()).segment().with_fixed(true), Seen::new(msg.seen()).segment().with_fixed(true),
Time::new(msg.time(), style_time(highlighted)) Time::new(msg.time().map(|t| t.to_zoned(tz)), style_time(highlighted))
.padding() .padding()
.with_right(1) .with_right(1)
.with_stretch(true) .with_stretch(true)

View file

@ -1,9 +1,7 @@
use std::convert::Infallible; use std::convert::Infallible;
use crossterm::style::Stylize; use crossterm::style::Stylize;
use time::format_description::FormatItem; use jiff::Zoned;
use time::macros::format_description;
use time::OffsetDateTime;
use toss::widgets::{Boxed, Empty, Text}; use toss::widgets::{Boxed, Empty, Text};
use toss::{Frame, Pos, Size, Style, Widget, WidgetExt, WidthDb}; use toss::{Frame, Pos, Size, Style, Widget, WidgetExt, WidthDb};
@ -46,15 +44,15 @@ impl<E> Widget<E> for Indent {
} }
} }
const TIME_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day] [hour]:[minute]"); const TIME_FORMAT: &str = "%Y-%m-%d %H:%M";
const TIME_WIDTH: u16 = 16; const TIME_WIDTH: u16 = 16;
pub struct Time(Boxed<'static, Infallible>); pub struct Time(Boxed<'static, Infallible>);
impl Time { impl Time {
pub fn new(time: Option<OffsetDateTime>, style: Style) -> Self { pub fn new(time: Option<Zoned>, style: Style) -> Self {
let widget = if let Some(time) = time { let widget = if let Some(time) = time {
let text = time.format(TIME_FORMAT).expect("could not format time"); let text = time.strftime(TIME_FORMAT).to_string();
Text::new((text, style)) Text::new((text, style))
.background() .background()
.with_style(style) .with_style(style)

View file

@ -6,6 +6,7 @@ use crossterm::style::Stylize;
use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId}; use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId};
use euphoxide::bot::instance::{Event, ServerConfig}; use euphoxide::bot::instance::{Event, ServerConfig};
use euphoxide::conn::{self, Joined, Joining, SessionInfo}; use euphoxide::conn::{self, Joined, Joining, SessionInfo};
use jiff::tz::TimeZone;
use tokio::sync::oneshot::error::TryRecvError; use tokio::sync::oneshot::error::TryRecvError;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use toss::widgets::{BoxedAsync, EditorState, Join2, Layer, Text}; use toss::widgets::{BoxedAsync, EditorState, Join2, Layer, Text};
@ -66,6 +67,7 @@ impl EuphRoom {
server_config: ServerConfig, server_config: ServerConfig,
room_config: cove_config::EuphRoom, room_config: cove_config::EuphRoom,
vault: EuphRoomVault, vault: EuphRoomVault,
tz: TimeZone,
ui_event_tx: mpsc::UnboundedSender<UiEvent>, ui_event_tx: mpsc::UnboundedSender<UiEvent>,
) -> Self { ) -> Self {
Self { Self {
@ -77,7 +79,7 @@ impl EuphRoom {
focus: Focus::Chat, focus: Focus::Chat,
state: State::Normal, state: State::Normal,
popups: VecDeque::new(), popups: VecDeque::new(),
chat: ChatState::new(vault), chat: ChatState::new(vault, tz),
last_msg_sent: None, last_msg_sent: None,
nick_list: ListState::new(), nick_list: ListState::new(),
} }

View file

@ -13,6 +13,7 @@ use crossterm::style::Stylize;
use euphoxide::api::SessionType; use euphoxide::api::SessionType;
use euphoxide::bot::instance::{Event, ServerConfig}; use euphoxide::bot::instance::{Event, ServerConfig};
use euphoxide::conn::{self, Joined}; use euphoxide::conn::{self, Joined};
use jiff::tz::TimeZone;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use toss::widgets::{BoxedAsync, Empty, Join2, Text}; use toss::widgets::{BoxedAsync, Empty, Join2, Text};
use toss::{Style, Styled, Widget, WidgetExt}; use toss::{Style, Styled, Widget, WidgetExt};
@ -73,6 +74,7 @@ impl EuphServer {
pub struct Rooms { pub struct Rooms {
config: &'static Config, config: &'static Config,
tz: TimeZone,
vault: Vault, vault: Vault,
ui_event_tx: mpsc::UnboundedSender<UiEvent>, ui_event_tx: mpsc::UnboundedSender<UiEvent>,
@ -89,11 +91,13 @@ pub struct Rooms {
impl Rooms { impl Rooms {
pub async fn new( pub async fn new(
config: &'static Config, config: &'static Config,
tz: TimeZone,
vault: Vault, vault: Vault,
ui_event_tx: mpsc::UnboundedSender<UiEvent>, ui_event_tx: mpsc::UnboundedSender<UiEvent>,
) -> Self { ) -> Self {
let mut result = Self { let mut result = Self {
config, config,
tz,
vault, vault,
ui_event_tx, ui_event_tx,
state: State::ShowList, state: State::ShowList,
@ -142,6 +146,7 @@ impl Rooms {
server.config.clone(), server.config.clone(),
self.config.euph_room(&room.domain, &room.name), self.config.euph_room(&room.domain, &room.name),
self.vault.euph().room(room), self.vault.euph().room(room),
self.tz.clone(),
self.ui_event_tx.clone(), self.ui_event_tx.clone(),
) )
}) })
@ -158,6 +163,7 @@ impl Rooms {
server.config.clone(), server.config.clone(),
self.config.euph_room(&room.domain, &room.name), self.config.euph_room(&room.domain, &room.name),
self.vault.euph().room(room), self.vault.euph().room(room),
self.tz.clone(),
self.ui_event_tx.clone(), self.ui_event_tx.clone(),
) )
}); });

View file

@ -1,8 +1,7 @@
use std::convert::Infallible; use std::convert::Infallible;
use std::env; use std::env;
use time::{OffsetDateTime, UtcOffset}; use jiff::tz::TimeZone;
use tz::{TimeZone, TzError};
pub trait InfallibleExt { pub trait InfallibleExt {
type Inner; type Inner;
@ -26,27 +25,30 @@ impl<T> InfallibleExt for Result<T, Infallible> {
/// ///
/// If no `TZ` environment variable could be found and no string is provided, /// If no `TZ` environment variable could be found and no string is provided,
/// the system local time (or UTC on Windows) is used. /// the system local time (or UTC on Windows) is used.
pub fn load_time_zone(tz_string: Option<&str>) -> Result<TimeZone, TzError> { pub fn load_time_zone(tz_string: Option<&str>) -> Result<TimeZone, jiff::Error> {
let env_string = env::var("TZ").ok(); let env_string = env::var("TZ").ok();
let tz_string = env_string.as_ref().map(|s| s as &str).or(tz_string); let tz_string = env_string.as_ref().map(|s| s as &str).or(tz_string);
match &tz_string { let Some(tz_string) = tz_string else {
// At the moment, TimeZone::from_posix_tz does not support "localtime" return Ok(TimeZone::system());
// on Windows, so we handle that case manually. };
Some("localtime") | None => TimeZone::local(),
Some(tz_string) => TimeZone::from_posix_tz(tz_string), if tz_string == "localtime" {
return Ok(TimeZone::system());
} }
}
pub fn convert_to_time_zone(tz: &TimeZone, time: OffsetDateTime) -> Option<OffsetDateTime> { if let Some(tz_string) = tz_string.strip_prefix(':') {
let utc_offset_in_seconds = tz return TimeZone::get(tz_string);
.find_local_time_type(time.unix_timestamp()) }
.ok()?
.ut_offset();
let utc_offset = UtcOffset::from_whole_seconds(utc_offset_in_seconds).ok()?; // The time zone is either a manually specified string or a file in the tz
// database. We'll try to parse it as a manually specified string first
// because that doesn't require a fs lookup.
if let Ok(tz) = TimeZone::posix(tz_string) {
return Ok(tz);
}
Some(time.to_offset(utc_offset)) TimeZone::get(tz_string)
} }
pub fn caesar(text: &str, by: i8) -> String { pub fn caesar(text: &str, by: i8) -> String {

View file

@ -6,7 +6,6 @@ use std::fs;
use std::path::Path; use std::path::Path;
use rusqlite::Connection; use rusqlite::Connection;
use tz::TimeZone;
use vault::tokio::TokioVault; use vault::tokio::TokioVault;
use vault::Action; use vault::Action;
@ -15,7 +14,6 @@ pub use self::euph::{EuphRoomVault, EuphVault, RoomIdentifier};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Vault { pub struct Vault {
tokio_vault: TokioVault, tokio_vault: TokioVault,
time_zone: &'static TimeZone,
ephemeral: bool, ephemeral: bool,
} }
@ -48,23 +46,18 @@ impl Vault {
} }
} }
fn launch_from_connection( fn launch_from_connection(conn: Connection, ephemeral: bool) -> rusqlite::Result<Vault> {
conn: Connection,
time_zone: &'static TimeZone,
ephemeral: bool,
) -> rusqlite::Result<Vault> {
conn.pragma_update(None, "foreign_keys", true)?; conn.pragma_update(None, "foreign_keys", true)?;
conn.pragma_update(None, "trusted_schema", false)?; conn.pragma_update(None, "trusted_schema", false)?;
let tokio_vault = TokioVault::launch_and_prepare(conn, &migrate::MIGRATIONS, prepare::prepare)?; let tokio_vault = TokioVault::launch_and_prepare(conn, &migrate::MIGRATIONS, prepare::prepare)?;
Ok(Vault { Ok(Vault {
tokio_vault, tokio_vault,
time_zone,
ephemeral, ephemeral,
}) })
} }
pub fn launch(path: &Path, time_zone: &'static TimeZone) -> rusqlite::Result<Vault> { pub fn launch(path: &Path) -> rusqlite::Result<Vault> {
// If this fails, rusqlite will complain about not being able to open the db // If this fails, rusqlite will complain about not being able to open the db
// file, which saves me from adding a separate vault error type. // file, which saves me from adding a separate vault error type.
let _ = fs::create_dir_all(path.parent().expect("path to file")); let _ = fs::create_dir_all(path.parent().expect("path to file"));
@ -79,10 +72,10 @@ pub fn launch(path: &Path, time_zone: &'static TimeZone) -> rusqlite::Result<Vau
conn.pragma_update(None, "locking_mode", "exclusive")?; conn.pragma_update(None, "locking_mode", "exclusive")?;
conn.pragma_update(None, "journal_mode", "wal")?; conn.pragma_update(None, "journal_mode", "wal")?;
launch_from_connection(conn, time_zone, false) launch_from_connection(conn, false)
} }
pub fn launch_in_memory(time_zone: &'static TimeZone) -> rusqlite::Result<Vault> { pub fn launch_in_memory() -> rusqlite::Result<Vault> {
let conn = Connection::open_in_memory()?; let conn = Connection::open_in_memory()?;
launch_from_connection(conn, time_zone, true) launch_from_connection(conn, true)
} }

View file

@ -6,7 +6,6 @@ use cookie::{Cookie, CookieJar};
use euphoxide::api::{Message, MessageId, SessionId, SessionView, Snowflake, Time, UserId}; use euphoxide::api::{Message, MessageId, SessionId, SessionView, Snowflake, Time, UserId};
use rusqlite::types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef}; use rusqlite::types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef};
use rusqlite::{named_params, params, Connection, OptionalExtension, Row, ToSql, Transaction}; use rusqlite::{named_params, params, Connection, OptionalExtension, Row, ToSql, Transaction};
use time::OffsetDateTime;
use vault::Action; use vault::Action;
use crate::euph::SmallMessage; use crate::euph::SmallMessage;
@ -32,7 +31,7 @@ struct WTime(Time);
impl ToSql for WTime { impl ToSql for WTime {
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> { fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
let timestamp = self.0 .0.unix_timestamp(); let timestamp = self.0 .0;
Ok(ToSqlOutput::Owned(Value::Integer(timestamp))) Ok(ToSqlOutput::Owned(Value::Integer(timestamp)))
} }
} }
@ -40,9 +39,7 @@ impl ToSql for WTime {
impl FromSql for WTime { impl FromSql for WTime {
fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> { fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
let timestamp = i64::column_result(value)?; let timestamp = i64::column_result(value)?;
Ok(Self(Time( Ok(Self(Time(timestamp)))
OffsetDateTime::from_unix_timestamp(timestamp).expect("timestamp in range"),
)))
} }
} }
@ -255,8 +252,6 @@ macro_rules! euph_room_vault_actions {
$( $(
struct $struct { struct $struct {
room: RoomIdentifier, room: RoomIdentifier,
#[allow(unused)]
time_zone: &'static tz::TimeZone,
$( $arg: $arg_ty, )* $( $arg: $arg_ty, )*
} }
)* )*
@ -266,7 +261,6 @@ macro_rules! euph_room_vault_actions {
pub async fn $fn(&self, $( $arg: $arg_ty, )* ) -> Result<$res, vault::tokio::Error<rusqlite::Error>> { pub async fn $fn(&self, $( $arg: $arg_ty, )* ) -> Result<$res, vault::tokio::Error<rusqlite::Error>> {
self.vault.vault.tokio_vault.execute($struct { self.vault.vault.tokio_vault.execute($struct {
room: self.room.clone(), room: self.room.clone(),
time_zone: self.vault.vault.time_zone,
$( $arg, )* $( $arg, )*
}).await }).await
} }
@ -626,7 +620,6 @@ impl Action for GetMsg {
id: MessageId(row.get::<_, WSnowflake>(0)?.0), id: MessageId(row.get::<_, WSnowflake>(0)?.0),
parent: row.get::<_, Option<WSnowflake>>(1)?.map(|s| MessageId(s.0)), parent: row.get::<_, Option<WSnowflake>>(1)?.map(|s| MessageId(s.0)),
time: row.get::<_, WTime>(2)?.0, time: row.get::<_, WTime>(2)?.0,
time_zone: self.time_zone,
nick: row.get(3)?, nick: row.get(3)?,
content: row.get(4)?, content: row.get(4)?,
seen: row.get(5)?, seen: row.get(5)?,
@ -720,7 +713,6 @@ impl Action for GetTree {
id: MessageId(row.get::<_, WSnowflake>(0)?.0), id: MessageId(row.get::<_, WSnowflake>(0)?.0),
parent: row.get::<_, Option<WSnowflake>>(1)?.map(|s| MessageId(s.0)), parent: row.get::<_, Option<WSnowflake>>(1)?.map(|s| MessageId(s.0)),
time: row.get::<_, WTime>(2)?.0, time: row.get::<_, WTime>(2)?.0,
time_zone: self.time_zone,
nick: row.get(3)?, nick: row.get(3)?,
content: row.get(4)?, content: row.get(4)?,
seen: row.get(5)?, seen: row.get(5)?,