Skip to content

Comments

fix: update existing tab state when openNew/openCurrent called with explicit state#4134

Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1771678726-fix-ai-tab-state-update
Open

fix: update existing tab state when openNew/openCurrent called with explicit state#4134
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1771678726-fix-ai-tab-state-update

Conversation

@devin-ai-integration
Copy link
Contributor

fix: update existing tab state when openNew called with explicit state

Summary

When openNew({ type: "ai", state: { tab: "intelligence" } }) is called and an AI tab is already open (e.g., on the "templates" sub-tab), the existing tab was simply activated without updating its state. This meant the user would see whichever sub-tab was previously open instead of the requested one.

The fix: in openTab, when an existing matching tab is found and the caller provided an explicit state, the existing tab's state is now replaced with the requested state before activation.

Review & Testing Checklist for Human

  • Broad scope: This change affects all tab types with state (sessions, contacts, templates, AI, search, chat_support, etc.), not just AI tabs. Verify that overwriting existing tab state on re-open is acceptable for all these types — or if this should be scoped to only certain tab types.
  • State replacement vs merge: The code does a full state replacement, not a shallow merge. Confirm this is correct — e.g., if a session tab has accumulated state beyond what's in the new TabInput, it will be lost.
  • as any cast: (tabWithDefaults as any).state bypasses type checking due to the Tab union type. Worth a glance to confirm safety.
  • End-to-end test: Open AI settings → select "Templates" tab → trigger openNew({ type: "ai", state: { tab: "intelligence" } }) (e.g., from a config-error prompt) → verify the AI tab now shows the Intelligence/LLM sub-tab.

Notes

…xplicit state

When openNew or openCurrent is called with an explicit state (e.g.,
{ type: 'ai', state: { tab: 'intelligence' } }), and an existing tab
of the same type is found, the existing tab's state is now updated
with the requested state instead of being ignored.

Previously, the existing tab was simply activated without updating its
state, so calling openNew({ type: 'ai', state: { tab: 'intelligence' } })
when the AI tab was already open on the 'templates' sub-tab would keep
showing templates instead of switching to intelligence.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Feb 21, 2026

Deploy Preview for hyprnote-storybook canceled.

Name Link
🔨 Latest commit b95a8c2
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/6999ac83d071da00083286f4

@netlify
Copy link

netlify bot commented Feb 21, 2026

Deploy Preview for hyprnote canceled.

Name Link
🔨 Latest commit b95a8c2
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/6999ac832fc8f800086c443c

Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

nextTabs = tabs.map((t) =>
isSameTab(t, existingTab!) ? currentTab : { ...t, active: false },
);
return { tabs: nextTabs, currentTab, history } as Partial<T>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🚩 State update on existing tab bypasses history tracking

When an existing tab is found and its state is updated (the shouldUpdateState branch at line 287-298), the function returns { tabs: nextTabs, currentTab, history } at line 299 — passing the original history map unchanged. This means navigating to an already-open tab with a new state (e.g., openNew({ type: 'ai', state: { tab: 'templates' } }) when an ai tab is already open with { tab: 'intelligence' }) will silently update the tab's state without creating a history entry. The user cannot "go back" to the previous state of that tab.

This is the same behavior as before this PR (the old code also returned history unchanged for existing tabs), so it's not a regression. However, it's worth noting that the new state-update feature amplifies the impact of this pre-existing design choice — previously, reopening an existing tab was a no-op on state, so skipping history was fine. Now that state actually changes, skipping history means state transitions are not reversible via back/forward navigation.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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