This commit is contained in:
prateek singh 2025-10-31 18:49:30 +05:30 committed by GitHub
commit 5443acdccd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 712 additions and 604 deletions

View file

@ -41,6 +41,7 @@ export const CodePreviewPanel = async ({ path, repoName, revisionName }: CodePre
return (
<>
<div className="flex flex-row py-1 px-2 items-center justify-between ">
<div className="w-2/3">
<PathHeader
path={path}
repo={{
@ -51,24 +52,27 @@ export const CodePreviewPanel = async ({ path, repoName, revisionName }: CodePre
}}
branchDisplayName={revisionName}
/>
</div>
<div className="w-1/3 flex justify-end">
{(fileWebUrl && codeHostInfo) && (
<a
href={fileWebUrl}
target="_blank"
rel="noopener noreferrer"
className="flex flex-row items-center gap-2 px-2 py-0.5 rounded-md flex-shrink-0"
className="flex flex-row items-center gap-4 px-2 py-0.5 rounded-md"
>
<Image
src={codeHostInfo.icon}
alt={codeHostInfo.codeHostName}
className={cn('w-4 h-4 flex-shrink-0', codeHostInfo.iconClassName)}
/>
<span className="text-sm font-medium">Open in {codeHostInfo.codeHostName}</span>
<span className="text-xs font-medium">Open in {codeHostInfo.codeHostName}</span>
</a>
)}
</div>
</div>
<Separator />
<PureCodePreviewPanel
source={fileSourceResponse.source}
@ -77,6 +81,7 @@ export const CodePreviewPanel = async ({ path, repoName, revisionName }: CodePre
path={path}
revisionName={revisionName ?? 'HEAD'}
/>
</>
)
}

View file

@ -11,10 +11,12 @@ export interface BrowseState {
language: string;
}
isBottomPanelCollapsed: boolean;
isChatPanelCollapsed: boolean;
isFileTreePanelCollapsed: boolean;
isFileSearchOpen: boolean;
activeExploreMenuTab: "references" | "definitions";
bottomPanelSize: number;
chatPanelSize: number;
}
const defaultState: BrowseState = {
@ -24,6 +26,8 @@ const defaultState: BrowseState = {
isFileSearchOpen: false,
activeExploreMenuTab: "references",
bottomPanelSize: 35,
isChatPanelCollapsed: true,
chatPanelSize: 20,
};
export const SET_BROWSE_STATE_QUERY_PARAM = "setBrowseState";

View file

@ -0,0 +1,94 @@
'use client'
import { KeyboardShortcutHint } from "@/app/components/keyboardShortcutHint"
import { Button } from "@/components/ui/button"
import { RiRobot3Line } from "react-icons/ri";
import { useBrowseState } from "../hooks/useBrowseState";
import { ImperativePanelHandle } from "react-resizable-panels";
import { useEffect, useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { Separator } from "@/components/ui/separator";
import { ResizablePanel } from "@/components/ui/resizable";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
export const CHAT_PANEL_MIN_SIZE = 5;
export const CHAT_PANEL_MAX_SIZE = 50;
interface ChatPanelProps {
order: number;
}
export const ChatPanel = ({ order }: ChatPanelProps) => {
const panelRef = useRef<ImperativePanelHandle>(null);
const {
state: { isChatPanelCollapsed, chatPanelSize },
updateBrowseState
} = useBrowseState();
useEffect(() => {
if (isChatPanelCollapsed) {
panelRef.current?.collapse();
} else {
panelRef.current?.expand();
}
}, [isChatPanelCollapsed]);
useHotkeys("shift+mod+o", (event) => {
event.preventDefault();
updateBrowseState({ isChatPanelCollapsed: !isChatPanelCollapsed });
}, {
enableOnFormTags: true,
enableOnContentEditable: true,
description: "Open Chat Panel"
});
return (
<>
<ResizablePanel
minSize={CHAT_PANEL_MIN_SIZE}
maxSize={CHAT_PANEL_MAX_SIZE}
collapsible={true}
ref={panelRef}
defaultSize={isChatPanelCollapsed ? 0 : chatPanelSize}
onCollapse={() => updateBrowseState({ isChatPanelCollapsed: true })}
onExpand={() => updateBrowseState({ isChatPanelCollapsed: false })}
onResize={(size) => {
if (!isChatPanelCollapsed) {
updateBrowseState({ chatPanelSize: size });
}
}}
order={order}
id={"chat-panel"}
>
<div className="flex flex-col items-center justify-center h-full text-muted-foreground gap-2 p-4">
<p className="text-sm">Chat goes here</p>
</div>
</ResizablePanel>
{isChatPanelCollapsed && (
<div className="flex flex-col items-center h-full p-2">
<Tooltip
delayDuration={100}
>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-8 w-8"
onClick={() => {
panelRef.current?.expand();
}}
>
<RiRobot3Line className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="bottom" className="flex flex-row items-center gap-2">
<KeyboardShortcutHint shortcut="⇧ ⌘ O" />
<Separator orientation="vertical" className="h-4" />
<span>Open AI Chat</span>
</TooltipContent>
</Tooltip>
</div>
)}
</>
)
}

View file

@ -2,6 +2,7 @@
import { ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { BottomPanel } from "./components/bottomPanel";
import { ChatPanel } from "./components/chatPanel";
import { AnimatedResizableHandle } from "@/components/ui/animatedResizableHandle";
import { BrowseStateProvider } from "./browseStateProvider";
import { FileTreePanel } from "@/features/fileTree/components/fileTreePanel";
@ -42,8 +43,8 @@ export default function Layout({
<ResizablePanel
order={2}
minSize={10}
defaultSize={80}
minSize={20}
defaultSize={60}
id="code-preview-panel-container"
>
<ResizablePanelGroup
@ -61,6 +62,10 @@ export default function Layout({
/>
</ResizablePanelGroup>
</ResizablePanel>
<AnimatedResizableHandle />
<ChatPanel order={3} />
</ResizablePanelGroup>
</div>
<FileSearchCommandDialog />