Summary
When NewDot is open in a browser tab (visible but not focused — e.g. you've switched to Slack or another desktop app), and the chat with the message sender is the currently open report, no notification is received even though the user is not actively looking at it. The message is silently marked as read with no alert.
If any other chat is open when the same sender messages you, the notification fires correctly. The bug is specific to the case where the sender's chat is the active/open report.
Steps to Reproduce
- Open NewDot in Chrome on macOS (web or PWA).
- Open a DM chat with User A.
- Switch focus to another desktop app (e.g. Slack, Finder) — do not minimize the NewDot window or switch browser tabs. The NewDot tab remains visible.
- Have User A send you a message.
Expected: A desktop notification fires (because you are not actively viewing the chat).
Actual: No notification. The message is silently marked as read.
Contrast (works correctly): Repeat with a different chat open in NewDot → notification fires as expected when User A messages you.
Root Cause
This is a visible-vs-focused mismatch in two separate parts of the notification pipeline.
Step 1 — Browser visibility state when another app is focused
When the user switches to another desktop app (not another tab, not minimizing):
document.visibilityState === 'visible' → Visibility.isVisible() = true
document.hasFocus() = false
So to the app, the page is "visible" even though the user isn't looking at it.
Step 2 — Open chat auto-marks message as read (the actual bug)
In src/pages/inbox/report/ReportActionsList.tsx, handleReportChangeMarkAsRead fires when a new action arrives in the currently open report. Its gate checks isVisible only, not hasFocus:
if ((isVisible || isFromNotification) && !hasNewerActions && isScrolledToEnd) {
readNewestAction(report.reportID, ...); // advances lastReadTime immediately
}
Because isVisible is true (page is not hidden), lastReadTime is advanced to ≥ the incoming message's created timestamp — even though the user's focus is on Slack.
Step 3 — "Already read" gate suppresses the notification
In src/libs/actions/Report/index.ts — shouldShowReportActionNotification():
// If this notification was delayed and the user saw the message already, don't show it
if (action && report?.lastReadTime && report.lastReadTime >= action.created) {
Log.info(`${tag} No notification because the comment was already read`);
return false;
}
Since lastReadTime was just advanced in Step 2, this gate fires and the notification is dropped.
Note: the other suppression gate — reportID === topmostReportID && isVisible() && hasFocus() — does not fire here because hasFocus() is false. It's the "already read" gate that kills the notification, caused by the premature mark-as-read.
Why a different open chat avoids the bug
If Chuck's DM is not the open report, handleReportChangeMarkAsRead runs against whichever chat is open — Chuck's lastReadTime is never advanced, the "already read" gate passes, and the notification fires. This matches the observed behavior exactly.
Suggested Fix Direction
The mark-as-read logic in ReportActionsList.tsx should require focus (not just visibility) before auto-advancing lastReadTime, so a visible-but-unfocused tab does not silently consume messages. Concretely, the condition should be:
if ((isVisible && hasFocus || isFromNotification) && !hasNewerActions && isScrolledToEnd) {
Care is needed to avoid regressing the case where a user is genuinely reading the chat (visible + focused) — that should still mark as read immediately. The change should be limited to the "another desktop app is in the foreground" scenario.
Environment
- Platform: Web (Chrome), macOS — also likely affects PWA
- App version: 9.3.90-2 (confirmed in logs at time of reproduction)
- Browser: Chrome 148
QA Note
When reproducing, switch to another desktop application (do not minimize the NewDot window or switch browser tabs). Minimizing or switching tabs changes visibilityState to hidden, which is a different code path and does not reproduce the bug.
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @nabi-ebrahimi
Summary
When NewDot is open in a browser tab (visible but not focused — e.g. you've switched to Slack or another desktop app), and the chat with the message sender is the currently open report, no notification is received even though the user is not actively looking at it. The message is silently marked as read with no alert.
If any other chat is open when the same sender messages you, the notification fires correctly. The bug is specific to the case where the sender's chat is the active/open report.
Steps to Reproduce
Expected: A desktop notification fires (because you are not actively viewing the chat).
Actual: No notification. The message is silently marked as read.
Contrast (works correctly): Repeat with a different chat open in NewDot → notification fires as expected when User A messages you.
Root Cause
This is a visible-vs-focused mismatch in two separate parts of the notification pipeline.
Step 1 — Browser visibility state when another app is focused
When the user switches to another desktop app (not another tab, not minimizing):
document.visibilityState === 'visible'→Visibility.isVisible()=truedocument.hasFocus()=falseSo to the app, the page is "visible" even though the user isn't looking at it.
Step 2 — Open chat auto-marks message as read (the actual bug)
In
src/pages/inbox/report/ReportActionsList.tsx,handleReportChangeMarkAsReadfires when a new action arrives in the currently open report. Its gate checksisVisibleonly, nothasFocus:Because
isVisibleistrue(page is not hidden),lastReadTimeis advanced to ≥ the incoming message'screatedtimestamp — even though the user's focus is on Slack.Step 3 — "Already read" gate suppresses the notification
In
src/libs/actions/Report/index.ts—shouldShowReportActionNotification():Since
lastReadTimewas just advanced in Step 2, this gate fires and the notification is dropped.Note: the other suppression gate —
reportID === topmostReportID && isVisible() && hasFocus()— does not fire here becausehasFocus()is false. It's the "already read" gate that kills the notification, caused by the premature mark-as-read.Why a different open chat avoids the bug
If Chuck's DM is not the open report,
handleReportChangeMarkAsReadruns against whichever chat is open — Chuck'slastReadTimeis never advanced, the "already read" gate passes, and the notification fires. This matches the observed behavior exactly.Suggested Fix Direction
The mark-as-read logic in
ReportActionsList.tsxshould require focus (not just visibility) before auto-advancinglastReadTime, so a visible-but-unfocused tab does not silently consume messages. Concretely, the condition should be:Care is needed to avoid regressing the case where a user is genuinely reading the chat (visible + focused) — that should still mark as read immediately. The change should be limited to the "another desktop app is in the foreground" scenario.
Environment
QA Note
When reproducing, switch to another desktop application (do not minimize the NewDot window or switch browser tabs). Minimizing or switching tabs changes
visibilityStatetohidden, which is a different code path and does not reproduce the bug.Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @nabi-ebrahimi