Skip to content

fix(web): keep sidebar unread dots in sync across browser tabs - #978

Merged
wbxl2000 merged 1 commit into
mainfrom
fix/web-unread-cross-tab
Jun 22, 2026
Merged

fix(web): keep sidebar unread dots in sync across browser tabs#978
wbxl2000 merged 1 commit into
mainfrom
fix/web-unread-cross-tab

Conversation

@wbxl2000

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — follow-up to #977.

Problem

Each browser tab keeps its own in-memory unreadBySession map, and the old saveUnreadToStorage wrote the whole map back to localStorage in one shot. A clear in one tab could be overwritten by another tab's stale map:

  1. Tab-A and Tab-B both have {B: true, C: true} in memory.
  2. Tab-A opens B → writes {C: true} (B cleared).
  3. Tab-B has a session finish → writes its stale {B: true, C: true, D: true} back.
  4. Tab-A refreshes → B's unread dot is back.

There was also no cross-tab sync, so clearing a dot in one tab never updated the others.

What changed

  • saveUnread now takes a partial set of changes and merges them onto the latest stored value, so a tab only touches the sessions it actually changed.
  • A storage event listener adopts another tab's value as soon as it writes the unread key, keeping every tab's in-memory map in sync.
  • Moved the unread read/write helpers into lib/storage.ts and added unit tests for the merge behavior.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9cbf1ca

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

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code 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

@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@d66ade8
npx https://pkg.pr.new/@moonshot-ai/kimi-code@d66ade8

commit: d66ade8

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f46d15d7c4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +374 to +376
window.addEventListener('storage', (event) => {
if (event.key === STORAGE_KEYS.unread) {
rawState.unreadBySession = loadUnread();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep active sessions from being re-marked unread

When this tab is currently viewing session X, another tab where X is in the background can still receive X's idle event and write { X: true } to kimi-web.unread; this storage listener then blindly adopts that value, so the tab that is already displaying X shows an unread dot and can persist it until the user re-selects the row. Filter/clear rawState.activeSessionId when applying cross-tab unread state so a session that is open in this tab cannot be re-marked unread by another tab's view of it.

Useful? React with 👍 / 👎.

@wbxl2000
wbxl2000 force-pushed the fix/web-unread-cross-tab branch from f46d15d to 6fa4e29 Compare June 22, 2026 13:49
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6fa4e29abe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +381 to +383
if (active) {
delete latest[active];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear persisted unread state for the active session

When tab A is already viewing session X and tab B records X as unread because it is in the background there, this handler only removes X from tab A's in-memory copy. The localStorage value remains { X: true }, so tab B and any future reload still show an unread dot even though X was visible in tab A, leaving the cross-tab state out of sync for the active-session case. Persisting a false change before deleting the active key would propagate the clear to the other tabs.

Useful? React with 👍 / 👎.

@wbxl2000
wbxl2000 force-pushed the fix/web-unread-cross-tab branch from 6fa4e29 to e3b98dd Compare June 22, 2026 14:17
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3b98ddb2b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +382 to +383
if (active && latest[active]) {
saveUnread({ [active]: false });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid clearing unread from hidden tabs

When the same session is selected in a background tab, this storage handler clears the newly persisted unread bit for every tab, even if the tab that has the session selected is not visible. For example, with hidden Tab A on session S and visible Tab B on session T, when S finishes in the background Tab B writes S as unread, then hidden Tab A receives the storage event and immediately saveUnread({ [active]: false }), causing Tab B to remove the sidebar dot before the user sees it. This should only clear globally when the tab is actually visible/viewing the session, or it should leave the unread bit intact for other tabs.

Useful? React with 👍 / 👎.

@wbxl2000
wbxl2000 force-pushed the fix/web-unread-cross-tab branch from e3b98dd to 9cbf1ca Compare June 22, 2026 14:48
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9cbf1cab61

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

active &&
latest[active] &&
typeof document !== 'undefined' &&
document.visibilityState === 'visible'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear active unread when hidden tab becomes visible

When a tab has session S selected but is hidden, another tab can mark S unread; this branch skips the clear because visibilityState is hidden, then stores S in rawState.unreadBySession. I couldn't find a later visibility-change clear in this composable, so when the tab is shown again the session is already on screen but its sidebar dot and persisted unread flag remain until the user re-selects it, leaving the cross-tab unread state stale for the active session.

Useful? React with 👍 / 👎.

@wbxl2000
wbxl2000 force-pushed the fix/web-unread-cross-tab branch from 9cbf1ca to d66ade8 Compare June 22, 2026 15:28
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: d66ade853a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@wbxl2000
wbxl2000 merged commit d4ae02d into main Jun 22, 2026
8 checks passed
@wbxl2000
wbxl2000 deleted the fix/web-unread-cross-tab branch June 22, 2026 15:37
@github-actions github-actions Bot mentioned this pull request Jun 22, 2026
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.

1 participant