Skip to content

feat: show relative time in Omnichannel Contact Center date columns - #41204

Merged
dionisio-bot[bot] merged 10 commits into
developfrom
feat/omnichannel-contact-center-date-format
Jul 17, 2026
Merged

feat: show relative time in Omnichannel Contact Center date columns#41204
dionisio-bot[bot] merged 10 commits into
developfrom
feat/omnichannel-contact-center-date-format

Conversation

@abhinavkrin

@abhinavkrin abhinavkrin commented Jul 6, 2026

Copy link
Copy Markdown
Member

Proposed changes (including videos or screenshots)

The Omnichannel Contact Center date columns now show both the formatted date and a relative time ("2 minutes ago") that updates live as time passes, instead of a static value.

  • Contacts tab: the Last Chat column shows the formatted date with the relative time below it.
  • Conversations tab: the Started at and Last Message columns show the formatted date with the relative time below it (previously the relative time was only available on hover).

Technically, this adds a useReactiveTimeFromNow hook that formats a timestamp via date-fns and refreshes itself on a self-rescheduling timer, with an adaptive interval based on how old the timestamp is. The full date and relative strings are also exposed as title tooltips so they remain readable when a column is narrow.
Screenshot 2026-07-07 at 2 56 11 AM
Screenshot 2026-07-07 at 2 56 03 AM

Issue(s)

Steps to test or reproduce

Further comments

CORE-2313

Review in cubic

Summary by CodeRabbit

  • New Features

    • Omnichannel contact center now shows formatted date plus live-updating relative time (with tooltips) for Last Chat, Started at, and Last Message.
    • Updated chat and contact directory row layouts to use a consistent two-line date + relative-time presentation.
  • Bug Fixes

    • Improved resilience of relative time rendering for missing or invalid timestamps.
  • Tests

    • Added Jest/React Testing Library coverage for reactive updates, undefined/invalid handling, and withSuffix behavior.

Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
@abhinavkrin
abhinavkrin requested a review from a team as a code owner July 6, 2026 21:28
@dionisio-bot

dionisio-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot

changeset-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 98b9675

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@abhinavkrin abhinavkrin modified the milestones: 8.6.0, 8.7.0 Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dougfabris dougfabris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can u tell me why we're creating useReactiveTimeFromNow ??

@coderabbitai coderabbitai Bot added the type: feature Pull requests that introduces new feature label Jul 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx (1)

93-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated "date + relative time" cell pattern; avoid duplicate formatDate calls.

The ts and lm columns here duplicate the same Box layout (formatted date line + hint-colored relative-time line, each with a title tooltip), and the same pattern is repeated a third time in ContactTableRow.tsx for lastChat.ts. Additionally, formatDate(ts)/formatDate(lm) is invoked twice per cell (once for title, once for content) — worth memoizing into a local variable regardless of extraction.

Consider extracting a small shared component (e.g. DateWithRelativeTime) taking the formatted date and relative-time string, to remove this duplication across both files.

♻️ Example extraction
const DateWithRelativeTime = ({ date, relative }: { date: string; relative?: string }) => (
	<Box display='flex' flexDirection='column'>
		<Box fontScale='p2m' withTruncatedText title={date}>
			{date}
		</Box>
		<Box color='hint' withTruncatedText title={relative}>
			{relative}
		</Box>
	</Box>
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx`
around lines 93 - 114, The `ChatsTableRow` date cells repeat the same “formatted
date + relative time” layout and call `formatDate(ts)`/`formatDate(lm)` twice
per cell. Refactor the duplicated `Box` markup into a shared helper/component
(e.g. `DateWithRelativeTime`) and compute the formatted date once in
`ChatsTableRow` before rendering. Reuse the same extracted pattern in
`ContactTableRow` for `lastChat.ts` so both rows share the same implementation.
apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts (1)

1-63: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a test for cleanup on unmount.

Coverage is good for formatting/refresh/withSuffix behavior, but nothing asserts that the recursive setTimeout is cleared when the hook unmounts (e.g. via jest.spyOn(global, 'clearTimeout') or asserting no further setText calls after unmount()). Since this hook is instantiated per table row and relies on a self-rescheduling timer, an unmount-cleanup regression could silently leak timers across many rows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts` around lines 1 - 63,
Add a cleanup-on-unmount test for useReactiveTimeFromNow to cover the
self-rescheduling timer lifecycle. In the spec, verify that when the hook
unmounts it clears the pending timeout (for example by spying on global
clearTimeout) or that no further updates occur after unmount. Use the existing
renderHook setup and the useReactiveTimeFromNow hook name to keep the test
aligned with the recursive setTimeout behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts`:
- Around line 1-63: Add a cleanup-on-unmount test for useReactiveTimeFromNow to
cover the self-rescheduling timer lifecycle. In the spec, verify that when the
hook unmounts it clears the pending timeout (for example by spying on global
clearTimeout) or that no further updates occur after unmount. Use the existing
renderHook setup and the useReactiveTimeFromNow hook name to keep the test
aligned with the recursive setTimeout behavior.

In
`@apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx`:
- Around line 93-114: The `ChatsTableRow` date cells repeat the same “formatted
date + relative time” layout and call `formatDate(ts)`/`formatDate(lm)` twice
per cell. Refactor the duplicated `Box` markup into a shared helper/component
(e.g. `DateWithRelativeTime`) and compute the formatted date once in
`ChatsTableRow` before rendering. Reuse the same extracted pattern in
`ContactTableRow` for `lastChat.ts` so both rows share the same implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a89ba01f-68e4-4f8a-8af7-0cead8978136

📥 Commits

Reviewing files that changed from the base of the PR and between a62b126 and 74cf0da.

📒 Files selected for processing (5)
  • .changeset/omnichannel-contact-center-date-relative-time.md
  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
  • apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx
  • apps/meteor/client/views/omnichannel/directory/contacts/ContactTableRow.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: Hacktron Security Check
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/views/omnichannel/directory/contacts/ContactTableRow.tsx
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
  • apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
🧠 Learnings (10)
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-05-11T20:30:35.265Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 40480
File: apps/meteor/client/meteor/startup/accounts.ts:59-61
Timestamp: 2026-05-11T20:30:35.265Z
Learning: In Rocket.Chat’s Meteor client code, when calling `dispatchToastMessage` with `{ type: 'error' }`, pass the raw caught error object as `message` without manual normalization. `dispatchToastMessage` is designed to accept `message: unknown` for error toasts, so avoid converting errors to strings (e.g., `String(error)`) or extracting `error.message` before passing them.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-02-24T19:22:48.358Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts:66-67
Timestamp: 2026-02-24T19:22:48.358Z
Learning: In Playwright end-to-end tests (e.g., under apps/meteor/tests/e2e/...), prefer locating elements by translated text (getByText) and ARIA roles (getByRole) over data-qa attributes. If translation values change, update the corresponding test locators accordingly. Never use data-qa locators. This guideline applies to all Playwright e2e test specs in the repository and helps keep tests robust to UI text changes and accessible semantics.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-03-06T18:10:15.268Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39397
File: packages/gazzodown/src/code/CodeBlock.spec.tsx:47-68
Timestamp: 2026-03-06T18:10:15.268Z
Learning: In tests (especially those using testing-library/dom/jsdom) for Rocket.Chat components, the HTML <code> element has an implicit ARIA role of 'code'. Therefore, screen.getByRole('code') or screen.findByRole('code') will locate <code> elements even without a role attribute. Do not flag findByRole('code') as invalid in reviews; prefer using the implicit role instead of adding role="code" unless necessary for accessibility.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
📚 Learning: 2026-04-14T21:10:31.855Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36292
File: apps/meteor/client/hooks/useHasValidLocationHash.ts:7-12
Timestamp: 2026-04-14T21:10:31.855Z
Learning: When reviewing files in apps/meteor/client/hooks/, do not treat JSDoc-style comments on React hooks (especially exported hooks) as a violation of any “avoid code comments in implementation” guideline. It’s acceptable to use JSDoc to document the public API of exported hooks (e.g., parameter/return types, intended usage), as long as it documents behavior/contracts rather than adding narrative implementation comments.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.spec.ts
  • apps/meteor/client/views/omnichannel/directory/contacts/ContactTableRow.tsx
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
  • apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx
📚 Learning: 2026-03-16T21:50:37.589Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: .changeset/migrate-users-register-openapi.md:3-3
Timestamp: 2026-03-16T21:50:37.589Z
Learning: For changes related to OpenAPI migrations in Rocket.Chat/OpenAPI, when removing endpoint types and validators from rocket.chat/rest-typings (e.g., UserRegisterParamsPOST, /v1/users.register) document this as a minor changeset (not breaking) per RocketChat/Rocket.Chat-Open-API#150 Rule 7. Note that the endpoint type is re-exposed via a module augmentation .d.ts in the consuming package (e.g., packages/web-ui-registration/src/users-register.d.ts). In reviews, ensure the changeset clearly states: this is a non-breaking change, the major version should not be bumped, and the changeset reflects a minor version bump. Do not treat this as a breaking change during OpenAPI migrations.

Applied to files:

  • .changeset/omnichannel-contact-center-date-relative-time.md
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/views/omnichannel/directory/contacts/ContactTableRow.tsx
  • apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx
🔇 Additional comments (6)
apps/meteor/client/views/omnichannel/directory/contacts/ContactTableRow.tsx (2)

56-66: 📐 Maintainability & Code Quality | ⚡ Quick win

Same duplicate formatDate/layout pattern as ChatsTableRow.

This block duplicates the same date + relative-time layout (and double formatDate(lastChat.ts) calls) flagged in ChatsTableRow.tsx; see that comment for a suggested shared-component extraction covering all three columns.


8-16: LGTM!

Also applies to: 37-55, 67-70

apps/meteor/client/hooks/useReactiveTimeFromNow.ts (1)

25-52: LGTM!

apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableRow.tsx (2)

53-92: LGTM!

Also applies to: 115-119


94-97: 🎯 Functional Correctness

Confirm ts is always set on IOmnichannelRoomWithDepartment.
formatDate(ts) is rendered unconditionally here, unlike lm. If ts can be missing, this will render a blank or invalid date instead of nothing.

.changeset/omnichannel-contact-center-date-relative-time.md (1)

1-6: LGTM!

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/meteor/client/hooks/useReactiveTimeFromNow.ts Outdated
Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
@abhinavkrin

Copy link
Copy Markdown
Member Author

Can u tell me why we're creating useReactiveTimeFromNow ??

Hey @dougfabris
Because no existing hook does live updating X ago text. useTimeFromNow gives the right text but its static, useFormattedRelativeTime is a duration. useReactiveTimeFromNow is just useTimeFromNow plus a timer so it refreshes on its own

Tested with useFormattedRelativeTime
Screenshot 2026-07-07 at 3 10 37 AM

@abhinavkrin
abhinavkrin requested a review from dougfabris July 6, 2026 21:53
@dougfabris

dougfabris commented Jul 6, 2026

Copy link
Copy Markdown
Member

useTimeFromNow gives the right text but its static

but do we need to keep updating the value live? is this a direction from product?

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 68.50%. Comparing base (115dfe8) to head (98b9675).
⚠️ Report is 142 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #41204      +/-   ##
===========================================
- Coverage    69.29%   68.50%   -0.80%     
===========================================
  Files         3539     4114     +575     
  Lines       138832   159690   +20858     
  Branches     24767    29070    +4303     
===========================================
+ Hits         96210   109398   +13188     
- Misses       38607    45238    +6631     
- Partials      4015     5054    +1039     
Flag Coverage Δ
e2e 59.01% <85.71%> (-0.39%) ⬇️
e2e-api 45.33% <ø> (-4.52%) ⬇️
unit 70.47% <ø> (+0.32%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@abhinavkrin

abhinavkrin commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

useTimeFromNow gives the right text but its static

but do we need to keep updating the value live? is this a direction from product?

Ticket doesn’t actually specify live refresh, just says show date + relative time. I added it because otherwise it goes stale, “2 min ago” will still say that an hour later if nothing re-renders it, which can be misleading when checking how recent a chat was.

useReactiveTimeFromNow just reuses the same adaptive refresh gazzodown already does for message timestamps, so not really new complexity, just applying it here too.

Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
@abhinavkrin

Copy link
Copy Markdown
Member Author

Checked with product, they are ok with it as long as it doesnt impact performance. so i dropped the 1s refresh for the sub minute case, it just shows "less than a minute ago" there so refreshing every second was pointless. it now refreshes at 30s at most and backs off further for older rows. shouldnt impact performance.

Comment thread apps/meteor/client/hooks/useReactiveTimeFromNow.ts Outdated
@abhinavkrin
abhinavkrin requested a review from ricardogarim July 9, 2026 11:12
Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/meteor/client/hooks/useReactiveTimeFromNow.ts`:
- Line 7: The helper in useReactiveTimeFromNow contains an implementation
comment that should be removed to follow the no-comments guideline. Delete the
inline narrative comment near the hook logic, and if the behavior still needs
explanation, make the intent clearer through the naming or structure of
useReactiveTimeFromNow rather than keeping a code comment.
- Around line 14-35: The self-rescheduling timer in useReactiveTimeFromNow only
calls schedule() again, so the hook never re-renders and formatFromNow(time,
withSuffix) stays stale. Add a local state update inside the setTimeout callback
(within the useEffect in useReactiveTimeFromNow) so each tick triggers a
re-render, then keep rescheduling the timer as before and clear it in the
cleanup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6e181a50-955e-4c4b-890a-770356f8ee1b

📥 Commits

Reviewing files that changed from the base of the PR and between 9899d61 and 3bb9ad6.

📒 Files selected for processing (1)
  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: Hacktron Security Check
  • GitHub Check: CodeQL-Build
⚠️ CI failures not shown inline (1)

GitHub Check: Dionisio QA: Some checks did not pass

Conclusion: failure

View job details

**Conclusion:** failure
### Steps
- ✅ **No merge conflicts**
- ❌ **QA assured** — This PR is missing the 'stat: QA assured' label
- ✅ **Mergeable**
- ✅ **Has milestone or project**
- ✅ **Valid PR title**
- ✅ **Correct target version**
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
🧠 Learnings (6)
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-05-11T20:30:35.265Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 40480
File: apps/meteor/client/meteor/startup/accounts.ts:59-61
Timestamp: 2026-05-11T20:30:35.265Z
Learning: In Rocket.Chat’s Meteor client code, when calling `dispatchToastMessage` with `{ type: 'error' }`, pass the raw caught error object as `message` without manual normalization. `dispatchToastMessage` is designed to accept `message: unknown` for error toasts, so avoid converting errors to strings (e.g., `String(error)`) or extracting `error.message` before passing them.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-04-14T21:10:31.855Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36292
File: apps/meteor/client/hooks/useHasValidLocationHash.ts:7-12
Timestamp: 2026-04-14T21:10:31.855Z
Learning: When reviewing files in apps/meteor/client/hooks/, do not treat JSDoc-style comments on React hooks (especially exported hooks) as a violation of any “avoid code comments in implementation” guideline. It’s acceptable to use JSDoc to document the public API of exported hooks (e.g., parameter/return types, intended usage), as long as it documents behavior/contracts rather than adding narrative implementation comments.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/hooks/useReactiveTimeFromNow.ts

Comment thread apps/meteor/client/hooks/useReactiveTimeFromNow.ts Outdated
Comment thread apps/meteor/client/hooks/useReactiveTimeFromNow.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread apps/meteor/client/hooks/useReactiveTimeFromNow.ts Outdated
Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
ricardogarim
ricardogarim previously approved these changes Jul 15, 2026

@dougfabris dougfabris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here's my honest review:
The feature request is simply asking to bring back the relative time we use to have for many years additionally to the fixed one we have now.

You're adding a live-updating behavior that add cost to the list performance. Every rendered row now creates 1–2 independent setTimeout chains. A table of 50 rows = ~100 timers firing every 30s.

It's not a huge problem but personally I don't see ANY value on this because the update almost never matters in practice. I won't block the pull request, feel free to get another opinion but during these times I will avoid as much as I can adding feature creep on my behalf

The path I would follow:

  1. keep the hardcoded time
  2. add the relative time in the same cell with a slightly different color
  3. remove the tooltip since it doesn't make sense anymore

@dougfabris
dougfabris dismissed their stale review July 16, 2026 13:56

dismissing to not block different thoughts about this

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@abhinavkrin abhinavkrin added stat: QA assured Means it has been tested and approved by a company insider and removed stat: QA assured Means it has been tested and approved by a company insider labels Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@abhinavkrin abhinavkrin added stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge and removed stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge labels Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

1 similar comment
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@abhinavkrin abhinavkrin added stat: QA assured Means it has been tested and approved by a company insider and removed stat: ready to merge PR tested and approved waiting for merge stat: QA assured Means it has been tested and approved by a company insider labels Jul 17, 2026
@dionisio-bot dionisio-bot Bot added the stat: ready to merge PR tested and approved waiting for merge label Jul 17, 2026
@dionisio-bot
dionisio-bot Bot added this pull request to the merge queue Jul 17, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 17, 2026
@abhinavkrin abhinavkrin removed the stat: QA assured Means it has been tested and approved by a company insider label Jul 17, 2026
@dionisio-bot dionisio-bot Bot removed the stat: ready to merge PR tested and approved waiting for merge label Jul 17, 2026
@abhinavkrin abhinavkrin added stat: ready to merge PR tested and approved waiting for merge stat: QA assured Means it has been tested and approved by a company insider labels Jul 17, 2026
@dionisio-bot
dionisio-bot Bot added this pull request to the merge queue Jul 17, 2026
Merged via the queue into develop with commit 65a366e Jul 17, 2026
84 of 86 checks passed
@dionisio-bot
dionisio-bot Bot deleted the feat/omnichannel-contact-center-date-format branch July 17, 2026 09:47
This was referenced Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants