Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect user preferences when formatting timestamp #7994

Merged
merged 12 commits into from
Feb 24, 2024
Merged

Respect user preferences when formatting timestamp #7994

merged 12 commits into from
Feb 24, 2024

Conversation

bennetbo
Copy link
Contributor

@bennetbo bennetbo commented Feb 19, 2024

This is a follow up to #7945. The current behaviour reads the locale and infers from that which type of time format should be used (12 hour/24 hour).
However, in macOS you can override this behaviour, e.g. you can use en_US locale but still use the 24 hour clock format (Can be customized under Settings > General > Date & Format > 24-hour time). You can even customize the date format.

This PR uses the macOS specific CFDateFormatter API, which outputs time format strings, that respect those settings.

Partially fixes #7956 (as its not implemented for linux)

Release Notes:

  • Added localization support for all macOS specific date and time configurations in chat

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Feb 19, 2024
@ConradIrwin ConradIrwin self-assigned this Feb 19, 2024
return Ok(*force_12_hour_format);
}
}
Ok(false)
Copy link
Member

@ConradIrwin ConradIrwin Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bennetbo This doesn't seem to work for me: I have a US locale and have disabled the 24-hour override setting, but it renders using 24 hour time on my system.

Rather than trying to figure this out for ourselves, I suggest we use CoreFoundation's builtin time formatting code.

We could either call into it directly, or use it to calculate the current format for us and then continue to format ourselves.

We need to add a dependency on core-foundation-sys and then something like the following code works:

        let str = unsafe {
            let locale = CFLocaleCopyCurrent();
            let formatter = CFDateFormatterCreate(
                kCFAllocatorDefault,
                locale,
                kCFDateFormatterNoStyle,
                kCFDateFormatterShortStyle,
            );
            let fmt = CFDateFormatterGetFormat(formatter);

            let str = CFType::wrap_under_get_rule(fmt.as_void_ptr())
                .downcast::<CFString>()
                .ok_or_else(|| anyhow::anyhow!(dbg!("not a string")))?;

            // CFRelease(locale); 
            // CFRelease(formatter);

            str.to_string()
        };
        dbg!(str); // "h:mm a" when I have the 24-hour thing disabled, or "HH:mm" when it is enabled.

It might be simpler to go one step further and call CFDateFormatterCreateStringWithAbsoluteTime directly on mac to generate the timestamps; but it will depend on how much code is needed to convert between rust dates and cocoa dates (and in the opposite direction with strings).

Copy link
Contributor Author

@bennetbo bennetbo Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I installed en_US on my system and can confirm that this does not seem to work. Interestingly neither AppleICUForce12HourTime or AppleICUForce24HourTime seem to be present when using en_US and 12 hour or 24 hour time formatting. I will look into the CFDateFormatter approach, I believe this will also handle more advanced cases, f.e. you can customize the date formatting in macOS converting 01/01/20 to 01.01.20 which is more common in European locales.

@bennetbo bennetbo marked this pull request as draft February 20, 2024 10:19
@bennetbo
Copy link
Contributor Author

bennetbo commented Feb 23, 2024

Thanks for pointing me in the right direction @ConradIrwin. I managed to implement your suggestion in the format_time crate (not sure about the name of the crate, maybe something more general like localization would be better?).

I did some tests locally, and all formats (Configuration under macOS Settings > General > Date & Time/Language & Region) seem to get picked up by zed now.

Also formatting was originally quite slow, caused by the call to CFDateFormatterCreate. Formatting 10000 timestamps took around 30 seconds on my machine. However, caching the date formatter in a thread local brings down the time to format 10000 timestamps to 0.2 seconds (which I think is fine for now, as we normally only format up to 50/100 dates per frame, depending how large the messages are in the chat).

I will add some notes to the code as there is some unsafe in there, which I am not that familiar with and want to make sure to not introduce some sort of memory leaks.

Also I noticed there is still some time formatting code which is not localized (see NotificationPanel::format_timestamp and in the journal stuff). However, I would like to keep the changes minimal for now and follow up with another PR to fix those.

Note:
Previously the year was omitted if the message was sent in the last year. The year is now always included, because there doesn't seem to be away to omit the date using the native api, without some nasty workarounds (handling different settings manually).

So personally, I would say we just include the year even if the message is less then a year old, that's also what other messaging apps seem to be doing (e.g. Discord).

fmt,
cf_absolute_time,
);
Ok(CFString::wrap_under_create_rule(s).to_string())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that CFString will be released as soon as we drop the rust String which is what we are returning here. So there should be no leak, is that correct?

kCFDateFormatterNoStyle,
kCFDateFormatterShortStyle,
)
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As these globals live for the whole lifetime of the application, the memory will be cleaned up by the OS if zed is shutdown. So we do not need any calls to CFRelease here, is that correct?

@bennetbo bennetbo marked this pull request as ready for review February 23, 2024 12:36
util.workspace = true

[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9.4"
Copy link
Contributor Author

@bennetbo bennetbo Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

core-foundation and core-foundation-sys are used in a lot of crates, should we move those dependencies to the workspace Cargo.toml?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes please! In general it's best to have dependencies listed there to avoid accidentally having two versions in flight.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that, also removed the with-uuid feature, which was referenced in gpui. It does not seem to be used anywhere.

@ConradIrwin
Copy link
Member

Thank you!

@ConradIrwin ConradIrwin merged commit dc7e14f into zed-industries:main Feb 24, 2024
7 checks passed
ConradIrwin pushed a commit that referenced this pull request Mar 13, 2024
Follow up of #7994 to rework the notification panel timestamps.
This PR also includes some of the changes @evrsen proposed in #8996 
Here is what it looks like now:


https://github.com/zed-industries/zed/assets/53836821/d85450e7-eab6-4fe7-bd11-1d76c0e87258

Release Notes:
- Reworked date time formatting in the chat and the notification panel
- Added hover style to notifications and hovering tooltip on timestamps

---------

Co-authored-by: Evren Sen <146845123+evrsen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed The user has signed the Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use time formatting settings specified in system settings rather than going by default language
2 participants