mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-16 00:47:39 +03:00
linux: Implement local time zone support (#14610)
I decided to remove the GPUI APIs since `chrono` already provides this functionality, and is already been used for this purpose in other parts of the code (e.g. [here](80402a6840/crates/zed/src/main.rs (L756)
) or [here](80402a6840/crates/ui/src/utils/format_distance.rs (L258)
)) These usages end up calling the `time_format` crate, which takes in a `UtcOffset`. It's probably cleaner to rewrite the crate to take in `chrono` types, but that would require rewriting most of the code there. Release Notes: - linux: Use local time zone in chat and Git blame
This commit is contained in:
parent
22a2cc6950
commit
013c9f0420
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2564,6 +2564,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"call",
|
||||
"channel",
|
||||
"chrono",
|
||||
"client",
|
||||
"collections",
|
||||
"db",
|
||||
@ -3593,6 +3594,7 @@ dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
"assets",
|
||||
"chrono",
|
||||
"client",
|
||||
"clock",
|
||||
"collections",
|
||||
|
@ -457,7 +457,6 @@ features = [
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_System_SystemServices",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_Time",
|
||||
"Win32_System_WinRT",
|
||||
"Win32_UI_Controls",
|
||||
"Win32_UI_HiDpi",
|
||||
|
@ -32,6 +32,7 @@ test-support = [
|
||||
anyhow.workspace = true
|
||||
call.workspace = true
|
||||
channel.workspace = true
|
||||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
db.workspace = true
|
||||
|
@ -111,6 +111,7 @@ impl ChatPanel {
|
||||
this.is_scrolled_to_bottom = !event.is_scrolled;
|
||||
}));
|
||||
|
||||
let local_offset = chrono::Local::now().offset().local_minus_utc();
|
||||
let mut this = Self {
|
||||
fs,
|
||||
client,
|
||||
@ -120,7 +121,7 @@ impl ChatPanel {
|
||||
active_chat: Default::default(),
|
||||
pending_serialization: Task::ready(None),
|
||||
message_editor: input_editor,
|
||||
local_timezone: cx.local_timezone(),
|
||||
local_timezone: UtcOffset::from_whole_seconds(local_offset).unwrap(),
|
||||
subscriptions: Vec::new(),
|
||||
is_scrolled_to_bottom: true,
|
||||
active: false,
|
||||
|
@ -127,11 +127,12 @@ impl NotificationPanel {
|
||||
},
|
||||
));
|
||||
|
||||
let local_offset = chrono::Local::now().offset().local_minus_utc();
|
||||
let mut this = Self {
|
||||
fs,
|
||||
client,
|
||||
user_store,
|
||||
local_timezone: cx.local_timezone(),
|
||||
local_timezone: UtcOffset::from_whole_seconds(local_offset).unwrap(),
|
||||
channel_store: ChannelStore::global(cx),
|
||||
notification_store: NotificationStore::global(cx),
|
||||
notification_list,
|
||||
|
@ -31,6 +31,7 @@ test-support = [
|
||||
aho-corasick = "1.1"
|
||||
anyhow.workspace = true
|
||||
assets.workspace = true
|
||||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
clock.workspace = true
|
||||
collections.workspace = true
|
||||
|
@ -8,6 +8,7 @@ use gpui::{
|
||||
use settings::Settings;
|
||||
use std::hash::Hash;
|
||||
use theme::{ActiveTheme, ThemeSettings};
|
||||
use time::UtcOffset;
|
||||
use ui::{
|
||||
div, h_flex, tooltip_container, v_flex, Avatar, Button, ButtonStyle, Clickable as _, Color,
|
||||
FluentBuilder, Icon, IconName, IconPosition, InteractiveElement as _, IntoElement,
|
||||
@ -129,7 +130,7 @@ impl Render for BlameEntryTooltip {
|
||||
let author_email = self.blame_entry.author_mail.clone();
|
||||
|
||||
let short_commit_id = self.blame_entry.sha.display_short();
|
||||
let absolute_timestamp = blame_entry_absolute_timestamp(&self.blame_entry, cx);
|
||||
let absolute_timestamp = blame_entry_absolute_timestamp(&self.blame_entry);
|
||||
|
||||
let message = self
|
||||
.details
|
||||
@ -247,30 +248,25 @@ impl Render for BlameEntryTooltip {
|
||||
}
|
||||
}
|
||||
|
||||
fn blame_entry_timestamp(
|
||||
blame_entry: &BlameEntry,
|
||||
format: time_format::TimestampFormat,
|
||||
cx: &WindowContext,
|
||||
) -> String {
|
||||
fn blame_entry_timestamp(blame_entry: &BlameEntry, format: time_format::TimestampFormat) -> String {
|
||||
match blame_entry.author_offset_date_time() {
|
||||
Ok(timestamp) => time_format::format_localized_timestamp(
|
||||
Ok(timestamp) => {
|
||||
let local = chrono::Local::now().offset().local_minus_utc();
|
||||
time_format::format_localized_timestamp(
|
||||
timestamp,
|
||||
time::OffsetDateTime::now_utc(),
|
||||
cx.local_timezone(),
|
||||
UtcOffset::from_whole_seconds(local).unwrap(),
|
||||
format,
|
||||
),
|
||||
)
|
||||
}
|
||||
Err(_) => "Error parsing date".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blame_entry_relative_timestamp(blame_entry: &BlameEntry, cx: &WindowContext) -> String {
|
||||
blame_entry_timestamp(blame_entry, time_format::TimestampFormat::Relative, cx)
|
||||
pub fn blame_entry_relative_timestamp(blame_entry: &BlameEntry) -> String {
|
||||
blame_entry_timestamp(blame_entry, time_format::TimestampFormat::Relative)
|
||||
}
|
||||
|
||||
fn blame_entry_absolute_timestamp(blame_entry: &BlameEntry, cx: &WindowContext) -> String {
|
||||
blame_entry_timestamp(
|
||||
blame_entry,
|
||||
time_format::TimestampFormat::MediumAbsolute,
|
||||
cx,
|
||||
)
|
||||
fn blame_entry_absolute_timestamp(blame_entry: &BlameEntry) -> String {
|
||||
blame_entry_timestamp(blame_entry, time_format::TimestampFormat::MediumAbsolute)
|
||||
}
|
||||
|
@ -3923,7 +3923,7 @@ fn render_inline_blame_entry(
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) -> AnyElement {
|
||||
let relative_timestamp = blame_entry_relative_timestamp(&blame_entry, cx);
|
||||
let relative_timestamp = blame_entry_relative_timestamp(&blame_entry);
|
||||
|
||||
let author = blame_entry.author.as_deref().unwrap_or_default();
|
||||
let text = format!("{}, {}", author, relative_timestamp);
|
||||
@ -3969,7 +3969,7 @@ fn render_blame_entry(
|
||||
};
|
||||
last_used_color.replace((sha_color, blame_entry.sha));
|
||||
|
||||
let relative_timestamp = blame_entry_relative_timestamp(&blame_entry, cx);
|
||||
let relative_timestamp = blame_entry_relative_timestamp(&blame_entry);
|
||||
|
||||
let short_commit_id = blame_entry.sha.display_short();
|
||||
|
||||
|
@ -14,7 +14,6 @@ use derive_more::{Deref, DerefMut};
|
||||
use futures::{channel::oneshot, future::LocalBoxFuture, Future};
|
||||
use slotmap::SlotMap;
|
||||
use smol::future::FutureExt;
|
||||
use time::UtcOffset;
|
||||
|
||||
pub use async_context::*;
|
||||
use collections::{FxHashMap, FxHashSet, VecDeque};
|
||||
@ -647,11 +646,6 @@ impl AppContext {
|
||||
self.platform.restart(binary_path)
|
||||
}
|
||||
|
||||
/// Returns the local timezone at the platform level.
|
||||
pub fn local_timezone(&self) -> UtcOffset {
|
||||
self.platform.local_timezone()
|
||||
}
|
||||
|
||||
/// Updates the http client assigned to GPUI
|
||||
pub fn update_http_client(&mut self, new_client: Arc<dyn HttpClient>) {
|
||||
self.http_client = new_client;
|
||||
|
@ -60,7 +60,6 @@ pub(crate) use mac::*;
|
||||
pub use semantic_version::SemanticVersion;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub(crate) use test::*;
|
||||
use time::UtcOffset;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub(crate) use windows::*;
|
||||
|
||||
@ -159,7 +158,6 @@ pub(crate) trait Platform: 'static {
|
||||
""
|
||||
}
|
||||
fn app_path(&self) -> Result<PathBuf>;
|
||||
fn local_timezone(&self) -> UtcOffset;
|
||||
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf>;
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle);
|
||||
|
@ -30,7 +30,6 @@ use filedescriptor::FileDescriptor;
|
||||
use flume::{Receiver, Sender};
|
||||
use futures::channel::oneshot;
|
||||
use parking_lot::Mutex;
|
||||
use time::UtcOffset;
|
||||
use util::ResultExt;
|
||||
use wayland_client::Connection;
|
||||
use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::Shape;
|
||||
@ -397,10 +396,6 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
|
||||
fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap) {}
|
||||
|
||||
fn local_timezone(&self) -> UtcOffset {
|
||||
UtcOffset::UTC
|
||||
}
|
||||
|
||||
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
|
||||
Err(anyhow::Error::msg(
|
||||
"Platform<LinuxPlatform>::path_for_auxiliary_executable is not implemented yet",
|
||||
|
@ -49,7 +49,6 @@ use std::{
|
||||
slice, str,
|
||||
sync::Arc,
|
||||
};
|
||||
use time::UtcOffset;
|
||||
|
||||
use super::renderer;
|
||||
|
||||
@ -760,14 +759,6 @@ impl Platform for MacPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
fn local_timezone(&self) -> UtcOffset {
|
||||
unsafe {
|
||||
let local_timezone: id = msg_send![class!(NSTimeZone), localTimeZone];
|
||||
let seconds_from_gmt: NSInteger = msg_send![local_timezone, secondsFromGMT];
|
||||
UtcOffset::from_whole_seconds(seconds_from_gmt.try_into().unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
|
||||
unsafe {
|
||||
let bundle: id = NSBundle::mainBundle();
|
||||
|
@ -257,10 +257,6 @@ impl Platform for TestPlatform {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn local_timezone(&self) -> time::UtcOffset {
|
||||
time::UtcOffset::UTC
|
||||
}
|
||||
|
||||
fn path_for_auxiliary_executable(&self, _name: &str) -> Result<std::path::PathBuf> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ use futures::channel::oneshot::{self, Receiver};
|
||||
use itertools::Itertools;
|
||||
use parking_lot::RwLock;
|
||||
use smallvec::SmallVec;
|
||||
use time::UtcOffset;
|
||||
use windows::{
|
||||
core::*,
|
||||
Win32::{
|
||||
@ -35,7 +34,6 @@ use windows::{
|
||||
Ole::*,
|
||||
SystemInformation::*,
|
||||
Threading::*,
|
||||
Time::*,
|
||||
},
|
||||
UI::{Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*},
|
||||
},
|
||||
@ -482,25 +480,6 @@ impl Platform for WindowsPlatform {
|
||||
Ok(std::env::current_exe()?)
|
||||
}
|
||||
|
||||
fn local_timezone(&self) -> UtcOffset {
|
||||
let mut info = unsafe { std::mem::zeroed() };
|
||||
let ret = unsafe { GetTimeZoneInformation(&mut info) };
|
||||
if ret == TIME_ZONE_ID_INVALID {
|
||||
log::error!(
|
||||
"Unable to get local timezone: {}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
return UtcOffset::UTC;
|
||||
}
|
||||
// Windows treat offset as:
|
||||
// UTC = localtime + offset
|
||||
// so we add a minus here
|
||||
let hours = -info.Bias / 60;
|
||||
let minutes = -info.Bias % 60;
|
||||
|
||||
UtcOffset::from_hms(hours as _, minutes as _, 0).unwrap()
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
|
||||
Err(anyhow!("not yet implemented"))
|
||||
|
Loading…
Reference in New Issue
Block a user