feat(web): default panel layout for new project chats - #6100
feat(web): default panel layout for new project chats#6100pranav100000 wants to merge 3 commits into
Conversation
Adds two client settings under Settings -> General, both off by default: "Open files panel in new chats" and "Open terminal in new chats". When on, a new chat in a project opens with the files panel and/or the terminal drawer already visible instead of a bare chat column. The defaults are seeded at chat creation, keyed by the draft's pre-allocated thread ref, so the layout survives the draft -> thread promotion on first send. A chat that already has panel state keeps it, so a panel the user deliberately closed is never re-opened.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
| "newThreadOpenFilesPanel" | "newThreadOpenTerminal" | ||
| >; | ||
|
|
||
| // Both stores drop a thread's entry once it returns to the all-closed default, |
There was a problem hiding this comment.
🟡 Medium src/newThreadPanelDefaults.ts:21
hasPanelState returns false for a draft whose terminal was closed, so applyNewThreadPanelDefaults reopens it. Closing the last terminal resets the terminal UI state to its default (removing the entry from terminalUiStateByThreadKey) but records the closed id in suppressedTerminalIdsByThreadKey; since that map is never checked, hasPanelState misses the closed state. The same applies to the files panel: closing the last right-panel surface deletes the thread entry from byThreadKey, so hasPanelState cannot distinguish an untouched draft from one the user explicitly closed, and the enabled-files default is reapplied. Consider tracking an explicit initialization/tombstone marker per draft so store-key presence is not used to infer an untouched state.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/newThreadPanelDefaults.ts around line 21:
`hasPanelState` returns `false` for a draft whose terminal was closed, so `applyNewThreadPanelDefaults` reopens it. Closing the last terminal resets the terminal UI state to its default (removing the entry from `terminalUiStateByThreadKey`) but records the closed id in `suppressedTerminalIdsByThreadKey`; since that map is never checked, `hasPanelState` misses the closed state. The same applies to the files panel: closing the last right-panel surface deletes the thread entry from `byThreadKey`, so `hasPanelState` cannot distinguish an untouched draft from one the user explicitly closed, and the enabled-files default is reapplied. Consider tracking an explicit initialization/tombstone marker per draft so store-key presence is not used to infer an untouched state.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e7395910b
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| applyNewThreadPanelDefaults( | ||
| scopeThreadRef(projectRef.environmentId, threadId), | ||
| getClientSettings(), | ||
| ); |
There was a problem hiding this comment.
Apply defaults to every new-chat creation path
When preparing a pull request must allocate a fresh draft (ChatView.tsx:1906-1918) or Implement Plan directly creates and navigates to a new thread (ChatView.tsx:5654-5731), neither path invokes useNewThreadHandler, so enabled panel defaults remain closed despite the setting promising to affect every new project chat. Apply the defaults from a shared initializer used by these creation paths rather than only here.
AGENTS.md reference: AGENTS.md:L67-L69
Useful? React with 👍 / 👎.
| // "New chat" hands back an unused draft rather than minting one whenever it | ||
| // can, so the defaults must never re-force a layout: whatever that draft | ||
| // already has wins, including a panel the user deliberately closed. | ||
| if (hasPanelState(threadRef)) return; |
There was a problem hiding this comment.
Remember fully closed layouts before reapplying defaults
When an empty draft's files tab is the only surface and the user closes that tab or chooses Close All, rightPanelStore.updateThread removes the resulting all-closed entry; therefore hasPanelState returns false, and invoking New Chat again for the reusable draft reopens the panel the user deliberately closed. Preserve an explicit initialized/closed marker instead of treating absence as proof that defaults were never applied.
AGENTS.md reference: AGENTS.md:L73-L73
Useful? React with 👍 / 👎.
ApprovabilityVerdict: Needs human review 1 blocking correctness issue found. This PR introduces new user-facing settings that change how new project chats open, constituting a new feature. There are also unresolved review comments raising edge-case concerns about panel state tracking and settings hydration timing that warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Both panel stores drop a thread's entry once its layout returns to the all-closed default, so store contents alone could not tell an untouched draft from one the user had emptied on purpose: pressing "new chat" again reused that draft and re-opened the panel the user just closed. Decide the defaults once per chat and remember that decision, and count a suppressed terminal id — the only trace left when the last terminal is closed — as a layout the user has already shaped.
Checking out a pull request into a chat, implementing a plan in a fresh thread, and reusing the draft already on screen each hand the user a new chat without going through the path that seeds the layout, so the setting appeared to do nothing there. Route all of them through the same defaults, which still leave a chat that has a layout alone.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9560bb82b5
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // The chats this defaulting has already decided on. Both stores drop a thread's | ||
| // entry once its layout returns to the all-closed default, so store contents | ||
| // alone cannot tell an untouched chat from one the user emptied on purpose. | ||
| const decidedThreadKeys = new Set<string>(); |
There was a problem hiding this comment.
Persist the all-closed decision across reloads
When an enabled default is applied to a reusable empty draft, the user closes every panel, and then reloads the app, both panel stores persist the all-closed state as no entry while this module-level set is reset; pressing New Chat for that persisted draft therefore reopens a panel the user deliberately closed. The fresh evidence in this revision is that the attempted fix records the decision only in the in-memory decidedThreadKeys set, so it still needs a durable initialized/closed marker associated with the persisted draft.
AGENTS.md reference: AGENTS.md:L73-L73
Useful? React with 👍 / 👎.
| applyNewThreadPanelDefaults( | ||
| scopeThreadRef(projectRef.environmentId, emptyStoredDraftThread.threadId), | ||
| getClientSettings(), |
There was a problem hiding this comment.
Wait for client-settings hydration before defaulting
Immediately after startup, before asynchronous client-settings hydration completes, getClientSettings() still returns DEFAULT_CLIENT_SETTINGS, with both new options false. Because the new-chat UI is not gated on hydration, opening or reusing a draft during that window causes applyNewThreadPanelDefaults to return without applying the persisted opt-ins, and nothing retries after hydration, leaving that first chat with the wrong layout.
Useful? React with 👍 / 👎.
| <SettingsRow | ||
| {...searchableSetting("new-thread-open-files")} | ||
| description="Start every new chat in a project with the files panel already open." |
There was a problem hiding this comment.
Document the new chat-layout settings
This exposes two user-visible settings that change the initial layout of every project chat, but a repo-wide search finds no corresponding addition under docs/user/. Add shipped-product documentation describing these preferences and their defaults so the behavior is documented in the required audience-specific location.
AGENTS.md reference: AGENTS.md:L75-L75
Useful? React with 👍 / 👎.
New project chats open with a sensible default panel layout instead of blank, configurable in Settings. Adds the setting to contracts + settings UI and applies it on new-chat creation. Tests included, incl. the desktop client-settings round-trip (46 passing).
Closes #5676.
Note
Add default panel layout settings for new project chats
newThreadOpenFilesPanelandnewThreadOpenTerminal(both defaultfalse), to control which panels open automatically when starting a new chat.applyNewThreadPanelDefaultswhich applies these defaults once per thread, skipping threads that already have panel state or a suppressed terminal.ChatViewanduseHandleNewThreadso all new or reused draft threads respect the settings.Macroscope summarized 9560bb8.
Note
Low Risk
Client-local panel UI state only; behavior is covered by unit tests including edge cases for reused drafts and user-closed panels.
Overview
Adds client settings
newThreadOpenFilesPanelandnewThreadOpenTerminal(default off) so new project chats can open with the files panel and/or terminal drawer already visible.Introduces
applyNewThreadPanelDefaults, which seedsrightPanelStoreandterminalUiStateStorefrom those settings, skips threads that already have layout state, and uses a per-sessiondecidedThreadKeysguard so reused empty drafts are not re-forced after the user closes panels. The helper is wired into new-thread flows (useHandleNewThread), draft reuse paths inChatView, and implementation thread creation after promote.General settings gets two toggles plus search entries; contracts decode/patch and desktop client-settings tests cover the new keys.
Reviewed by Cursor Bugbot for commit 9560bb8. Bugbot is set up for automated code reviews on this repo. Configure here.