From 1189e3eb7b12cea9c6e2ce36067d4048d8ead337 Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 3 Jan 2024 02:20:59 +0100 Subject: [PATCH] Display chat time stamps in configured time zone --- cove/src/euph/small_message.rs | 6 ++++-- cove/src/logger.rs | 4 ++-- cove/src/main.rs | 1 + cove/src/ui/chat.rs | 2 +- cove/src/ui/chat/tree/widgets.rs | 2 +- cove/src/util.rs | 12 ++++++++++++ cove/src/vault.rs | 8 ++++---- cove/src/vault/euph.rs | 5 +++++ 8 files changed, 30 insertions(+), 10 deletions(-) diff --git a/cove/src/euph/small_message.rs b/cove/src/euph/small_message.rs index 2751058..0642801 100644 --- a/cove/src/euph/small_message.rs +++ b/cove/src/euph/small_message.rs @@ -4,6 +4,7 @@ use crossterm::style::Stylize; use euphoxide::api::{MessageId, Snowflake, Time}; use time::OffsetDateTime; use toss::{Style, Styled}; +use tz::TimeZone; use crate::store::Msg; use crate::ui::ChatMsg; @@ -207,6 +208,7 @@ pub struct SmallMessage { pub id: MessageId, pub parent: Option, pub time: Time, + pub time_zone: &'static TimeZone, pub nick: String, pub content: String, pub seen: bool, @@ -270,8 +272,8 @@ impl Msg for SmallMessage { } impl ChatMsg for SmallMessage { - fn time(&self) -> OffsetDateTime { - self.time.0 + fn time(&self) -> Option { + crate::util::convert_to_time_zone(self.time_zone, self.time.0) } fn styled(&self) -> (Styled, Styled) { diff --git a/cove/src/logger.rs b/cove/src/logger.rs index 731a000..b8b696b 100644 --- a/cove/src/logger.rs +++ b/cove/src/logger.rs @@ -42,8 +42,8 @@ impl Msg for LogMsg { } impl ChatMsg for LogMsg { - fn time(&self) -> OffsetDateTime { - self.time + fn time(&self) -> Option { + Some(self.time) } fn styled(&self) -> (Styled, Styled) { diff --git a/cove/src/main.rs b/cove/src/main.rs index 0308604..338642c 100644 --- a/cove/src/main.rs +++ b/cove/src/main.rs @@ -131,6 +131,7 @@ fn update_config_with_args(config: &mut Config, args: &Args) { fn open_vault(config: &Config, dirs: &ProjectDirs) -> anyhow::Result { let time_zone = util::load_time_zone(config.time_zone_ref())?; + let time_zone = Box::leak(Box::new(time_zone)); let vault = if config.ephemeral { vault::launch_in_memory(time_zone)? diff --git a/cove/src/ui/chat.rs b/cove/src/ui/chat.rs index 24ea82e..6a9c9c2 100644 --- a/cove/src/ui/chat.rs +++ b/cove/src/ui/chat.rs @@ -18,7 +18,7 @@ use self::tree::TreeViewState; use super::UiError; pub trait ChatMsg { - fn time(&self) -> OffsetDateTime; + fn time(&self) -> Option; fn styled(&self) -> (Styled, Styled); fn edit(nick: &str, content: &str) -> (Styled, Styled); fn pseudo(nick: &str, content: &str) -> (Styled, Styled); diff --git a/cove/src/ui/chat/tree/widgets.rs b/cove/src/ui/chat/tree/widgets.rs index e52704e..2f1a1ff 100644 --- a/cove/src/ui/chat/tree/widgets.rs +++ b/cove/src/ui/chat/tree/widgets.rs @@ -58,7 +58,7 @@ pub fn msg( Join5::horizontal( Seen::new(msg.seen()).segment().with_fixed(true), - Time::new(Some(msg.time()), style_time(highlighted)) + Time::new(msg.time(), style_time(highlighted)) .padding() .with_right(1) .with_stretch(true) diff --git a/cove/src/util.rs b/cove/src/util.rs index 67c0e68..1bc9d6b 100644 --- a/cove/src/util.rs +++ b/cove/src/util.rs @@ -1,6 +1,7 @@ use std::convert::Infallible; use std::env; +use time::{OffsetDateTime, UtcOffset}; use tz::{TimeZone, TzError}; pub trait InfallibleExt { @@ -35,3 +36,14 @@ pub fn load_time_zone(tz_string: Option<&str>) -> Result { Some(tz_string) => TimeZone::from_posix_tz(tz_string), } } + +pub fn convert_to_time_zone(tz: &TimeZone, time: OffsetDateTime) -> Option { + let utc_offset_in_seconds = tz + .find_local_time_type(time.unix_timestamp()) + .ok()? + .ut_offset(); + + let utc_offset = UtcOffset::from_whole_seconds(utc_offset_in_seconds).ok()?; + + Some(time.to_offset(utc_offset)) +} diff --git a/cove/src/vault.rs b/cove/src/vault.rs index 250456d..55abbf0 100644 --- a/cove/src/vault.rs +++ b/cove/src/vault.rs @@ -15,7 +15,7 @@ pub use self::euph::{EuphRoomVault, EuphVault, RoomIdentifier}; #[derive(Debug, Clone)] pub struct Vault { tokio_vault: TokioVault, - time_zone: TimeZone, + time_zone: &'static TimeZone, ephemeral: bool, } @@ -50,7 +50,7 @@ impl Vault { fn launch_from_connection( conn: Connection, - time_zone: TimeZone, + time_zone: &'static TimeZone, ephemeral: bool, ) -> rusqlite::Result { conn.pragma_update(None, "foreign_keys", true)?; @@ -64,7 +64,7 @@ fn launch_from_connection( }) } -pub fn launch(path: &Path, time_zone: TimeZone) -> rusqlite::Result { +pub fn launch(path: &Path, time_zone: &'static TimeZone) -> rusqlite::Result { // 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. let _ = fs::create_dir_all(path.parent().expect("path to file")); @@ -82,7 +82,7 @@ pub fn launch(path: &Path, time_zone: TimeZone) -> rusqlite::Result { launch_from_connection(conn, time_zone, false) } -pub fn launch_in_memory(time_zone: TimeZone) -> rusqlite::Result { +pub fn launch_in_memory(time_zone: &'static TimeZone) -> rusqlite::Result { let conn = Connection::open_in_memory()?; launch_from_connection(conn, time_zone, true) } diff --git a/cove/src/vault/euph.rs b/cove/src/vault/euph.rs index 4664446..8091613 100644 --- a/cove/src/vault/euph.rs +++ b/cove/src/vault/euph.rs @@ -239,6 +239,8 @@ macro_rules! euph_room_vault_actions { $( struct $struct { room: RoomIdentifier, + #[allow(unused)] + time_zone: &'static tz::TimeZone, $( $arg: $arg_ty, )* } )* @@ -248,6 +250,7 @@ macro_rules! euph_room_vault_actions { pub async fn $fn(&self, $( $arg: $arg_ty, )* ) -> Result<$res, vault::tokio::Error> { self.vault.vault.tokio_vault.execute($struct { room: self.room.clone(), + time_zone: self.vault.vault.time_zone, $( $arg, )* }).await } @@ -607,6 +610,7 @@ impl Action for GetMsg { id: MessageId(row.get::<_, WSnowflake>(0)?.0), parent: row.get::<_, Option>(1)?.map(|s| MessageId(s.0)), time: row.get::<_, WTime>(2)?.0, + time_zone: self.time_zone, nick: row.get(3)?, content: row.get(4)?, seen: row.get(5)?, @@ -700,6 +704,7 @@ impl Action for GetTree { id: MessageId(row.get::<_, WSnowflake>(0)?.0), parent: row.get::<_, Option>(1)?.map(|s| MessageId(s.0)), time: row.get::<_, WTime>(2)?.0, + time_zone: self.time_zone, nick: row.get(3)?, content: row.get(4)?, seen: row.get(5)?,