| ... | ... | @@ -131,6 +131,7 @@ import { |
| 131 | 131 | resolveSettledTimestamp, |
| 132 | 132 | resolveSidebarThreadStatus, |
| 133 | 133 | searchSidebarThreadsByTitle, |
| 134 | shouldCreateNewThreadInCurrentProject, |
| 134 | 135 | resolveWorkingStartedAt, |
| 135 | 136 | sortLogicalProjectsForSidebar, |
| 136 | 137 | sortPinnedThreadsForSidebar, |
| ... | ... | @@ -3164,29 +3165,39 @@ export default function Sidebar() { |
| 3164 | 3165 | // falling back to the top project) — same resolution the command palette |
| 3165 | 3166 | // uses. The command palette already offers a "New thread in..." submenu |
| 3166 | 3167 | // for multi-project setups. |
| 3167 | | const handleNewThreadClick = useCallback(() => { |
| 3168 | | // One project: nothing to pick, create immediately. |
| 3169 | | if (projectGroups.length <= 1) { |
| 3168 | const handleNewThreadClick = useCallback( |
| 3169 | (event?: ReactMouseEvent) => { |
| 3170 | // One project: nothing to pick, create immediately. Shift+click creates |
| 3171 | // directly in the current project even with several projects, skipping |
| 3172 | // the palette picker. |
| 3173 | if (shouldCreateNewThreadInCurrentProject(event?.shiftKey ?? false, projectGroups.length)) { |
| 3174 | if (isMobile) setOpenMobile(false); |
| 3175 | void startNewThreadFromContext({ |
| 3176 | activeDraftThread: newThreadContext.activeDraftThread, |
| 3177 | activeThread: newThreadContext.activeThread ?? undefined, |
| 3178 | defaultProjectRef: newThreadContext.defaultProjectRef, |
| 3179 | handleNewThread: newThreadContext.handleNewThread, |
| 3180 | }); |
| 3181 | return; |
| 3182 | } |
| 3170 | 3183 | if (isMobile) setOpenMobile(false); |
| 3171 | | void startNewThreadFromContext({ |
| 3172 | | activeDraftThread: newThreadContext.activeDraftThread, |
| 3173 | | activeThread: newThreadContext.activeThread ?? undefined, |
| 3174 | | defaultProjectRef: newThreadContext.defaultProjectRef, |
| 3175 | | handleNewThread: newThreadContext.handleNewThread, |
| 3176 | | }); |
| 3177 | | return; |
| 3178 | | } |
| 3179 | | if (isMobile) setOpenMobile(false); |
| 3180 | | openCommandPalette({ open: "new-thread-in" }); |
| 3181 | | }, [isMobile, newThreadContext, projectGroups.length, setOpenMobile]); |
| 3184 | openCommandPalette({ open: "new-thread-in" }); |
| 3185 | }, |
| 3186 | [isMobile, newThreadContext, projectGroups.length, setOpenMobile], |
| 3187 | ); |
| 3182 | 3188 | |
| 3183 | 3189 | // The button mirrors chat.new: in multi-project setups both route through |
| 3184 | 3190 | // the command palette's "New thread in..." picker, and in single-project |
| 3185 | | // setups both create immediately. chat.newLocal always creates directly, so |
| 3186 | | // it is only a correct label when chat.new is unbound. |
| 3191 | // setups both create immediately. In multi-project setups the label is only |
| 3192 | // the picker's shortcut: falling back to chat.newLocal would advertise the |
| 3193 | // same shortcut for both the picker and direct create. In single-project |
| 3194 | // setups both commands create directly, so chat.newLocal is a valid |
| 3195 | // fallback. The second tooltip line (multi-project only) advertises |
| 3196 | // shift+click and its keyboard twin chat.newLocal for direct create. |
| 3187 | 3197 | const newThreadShortcutLabel = |
| 3188 | 3198 | shortcutLabelForCommand(keybindings, "chat.new") ?? |
| 3189 | | shortcutLabelForCommand(keybindings, "chat.newLocal"); |
| 3199 | (projectGroups.length <= 1 ? shortcutLabelForCommand(keybindings, "chat.newLocal") : undefined); |
| 3200 | const newThreadInProjectShortcutLabel = shortcutLabelForCommand(keybindings, "chat.newLocal"); |
| 3190 | 3201 | return ( |
| 3191 | 3202 | <> |
| 3192 | 3203 | <SidebarChromeHeader isElectron={isElectron} /> |
| ... | ... | @@ -3264,9 +3275,25 @@ export default function Sidebar() { |
| 3264 | 3275 | /> |
| 3265 | 3276 | </TooltipTrigger> |
| 3266 | 3277 | <TooltipPopup side="right"> |
| 3267 | | {newThreadShortcutLabel |
| 3268 | | ? `New thread (${newThreadShortcutLabel})` |
| 3269 | | : "New thread"} |
| 3278 | {projectGroups.length > 1 ? ( |
| 3279 | <span className="flex flex-col gap-0.5"> |
| 3280 | <span> |
| 3281 | {newThreadShortcutLabel |
| 3282 | ? `New thread (${newThreadShortcutLabel})` |
| 3283 | : "New thread"} |
| 3284 | </span> |
| 3285 | <span className="text-muted-foreground"> |
| 3286 | New thread in current project: Shift+click |
| 3287 | {newThreadInProjectShortcutLabel |
| 3288 | ? ` (${newThreadInProjectShortcutLabel})` |
| 3289 | : ""} |
| 3290 | </span> |
| 3291 | </span> |
| 3292 | ) : newThreadShortcutLabel ? ( |
| 3293 | `New thread (${newThreadShortcutLabel})` |
| 3294 | ) : ( |
| 3295 | "New thread" |
| 3296 | )} |
| 3270 | 3297 | </TooltipPopup> |
| 3271 | 3298 | </Tooltip> |
| 3272 | 3299 | </div> |