Skip to content

Conversation

@MartinSchoeler
Copy link
Collaborator

Let's use this PR to start the review process of what we currently have

'renderMessage',
(message: IMessageWithHTML): IMessageWithHTML => {
if (message.html) {
message.html = renderTimestamp(message.html);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jhanyu2019 could you explain a bit the need for changing the message html using the callbacks?

Copy link
Owner

Choose a reason for hiding this comment

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

Hi Martin, I use callbacks.add('renderMessage', ...) to register a high-priority callback that runs after the basic HTML of a message is generated. This callback inspects the message HTML and calls renderTimestamp to find and replace any <t:...> markup with a readable date/time string. This ensures timestamp markup is always rendered in a user-friendly format whenever messages are displayed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah I see, as I've mentioned in another review, the parsing of the timestamps after the message was sent is already implemented, so I don't think we need to change anything related to message rendering for now

@@ -1,90 +1,138 @@
/* eslint-disable import/no-unresolved */
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think these changes are need as we already have timestamp rendering for the messages once the timestamp feature preview has been enabled

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also, you can see that this component is in the livechat folder, livechat is a client used as an embedded chat popup. This client is not on the scope of the project and we can ignore these files for now

'renderMessage',
(message: IMessageWithHTML): IMessageWithHTML => {
if (message.html) {
message.html = renderTimestamp(message.html);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah I see, as I've mentioned in another review, the parsing of the timestamps after the message was sent is already implemented, so I don't think we need to change anything related to message rendering for now

<MessageToolbarItem
id='timestamp'
icon='clock'
title={t('Add_Timestamp')}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think this we could name it "Add Date and Time" or something similar, as we are not adding a timestamp anymore but an actual date and time that will be rendered to other users using the feature preview

<Field>
<FieldLabel>{t('Date')}</FieldLabel>
<FieldRow>
<input
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here we can use the <InputBox> from fuselage

Here is the link to it's storybook https://rocketchat.github.io/fuselage/fuselage/main/?path=/docs/inputs-inputbox--docs

@@ -0,0 +1,65 @@
import { Modal, Box } from '@rocket.chat/fuselage';
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let's create a storybook to this component, so later we can do some Jest Unit Snapshot tests. Snapshot tests are a good and "cheap" way to make sure the visual integrity of the component is properly covered by tests 😁

return `${year}-${month}-${day}`;
};

const TimestampPicker = ({ onClose, onInsert, initialDate = new Date() }: TimestampPickerProps) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

onChange: (value: string) => void;
};

const TimeInput = ({ value, onChange }: TimeInputProps) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

value={selectedFormat}
onChange={handleFormatChange}
options={formatOptions}
style={{
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since the Select Component inherits from Box, you can just add the property width='full' to the component directly

<Field>
<FieldLabel>{t('Format')}</FieldLabel>
<FieldRow>
<Box w='full'>
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thix box component is not needed here, just add the width='full' to the select component

const createDiscussionAction = useCreateDiscussionAction(room);
const shareLocationAction = useShareLocationAction(room, tmid);
// Added for Timestamp feature
const timestampAction = useTimestampAction(chatContext.composer, !canSend || typing || isRecording);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The !canSend condition here stops the message action from adding timestamps if the message contains something, this check makes sense for actions like audioMessageAction since we cannot send text with the audios, but in the case of the timestamp, we should not check for these conditions

Suggested change
const timestampAction = useTimestampAction(chatContext.composer, !canSend || typing || isRecording);
const timestampAction = useTimestampAction(chatContext.composer);

...(!isHidden(hiddenActions, createDiscussionAction) && { createDiscussionAction }),
...(!isHidden(hiddenActions, shareLocationAction) && { shareLocationAction }),
// Added for Timestamp feature
...(!isHidden(hiddenActions, timestampAction) && { timestampAction}),
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hidden actions are set here https://github.com/jhanyu2019/Rocket.Chat/blob/feature/gsoc-timestamp-picker/apps/meteor/client/providers/LayoutProvider.tsx#L39 via browser message events. Ideally the timestamp picker action should be hidden when the feature preview is disabled.

/**
* Formats a date as a relative time string
*/
const formatRelativeTime = (date: Date): string => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This returns some weird values if the date is earlier than 1 year

Screenshot 2025-06-22 at 15 43 14
The expected result for that date
Screenshot 2025-06-22 at 15 43 25

I think we could experiment swapping the preview component for one of the Gazzodown components https://github.com/jhanyu2019/Rocket.Chat/blob/feature/gsoc-timestamp-picker/packages/gazzodown/src/elements/Timestamp/index.tsx#L39-L40

@github-actions
Copy link

github-actions bot commented Jul 17, 2025

PR Preview Action v1.6.2

🚀 View preview at
https://jhanyu2019.github.io/Rocket.Chat/pr-preview/pr-1/

Built to branch gh-pages at 2025-08-03 05:25 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

MartinSchoeler and others added 17 commits July 17, 2025 14:39
Co-authored-by: Douglas Gubert <[email protected]>
Co-authored-by: Tasso Evangelista <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Jéssica Souza <[email protected]>
Co-authored-by: Matheus Cardoso <[email protected]>
Co-authored-by: Guilherme Gazzo <[email protected]>
[no ci]
ggazzo and others added 29 commits July 29, 2025 10:21
Release 7.9.0
[no ci]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.