fix: global buttons and indicators

- cmd/ctrl + L works globally now
- added the copilot and ai chat button indicators
- when aichat is open, the preview/terminal column becomes horizontal
This commit is contained in:
Akhileshrangani4 2024-10-20 23:23:04 -04:00
parent fae09d2b6d
commit 7951221310
3 changed files with 81 additions and 26 deletions

View File

@ -4,6 +4,7 @@ import ChatMessage from './ChatMessage';
import ChatInput from './ChatInput';
import ContextDisplay from './ContextDisplay';
import { handleSend, handleStopGeneration } from './lib/chatUtils';
import { X } from 'lucide-react';
interface Message {
role: 'user' | 'assistant';
@ -11,7 +12,7 @@ interface Message {
context?: string;
}
export default function AIChat({ activeFileContent, activeFileName }: { activeFileContent: string, activeFileName: string }) {
export default function AIChat({ activeFileContent, activeFileName, onClose }: { activeFileContent: string, activeFileName: string, onClose: () => void }) {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState('');
const [isGenerating, setIsGenerating] = useState(false);
@ -40,7 +41,17 @@ export default function AIChat({ activeFileContent, activeFileName }: { activeFi
<div className="flex flex-col h-screen w-full">
<div className="flex justify-between items-center p-2 border-b">
<span className="text-muted-foreground/50 font-medium">CHAT</span>
<span className="text-muted-foreground/50 font-medium truncate max-w-[50%]" title={activeFileName}>{activeFileName}</span>
<div className="flex items-center h-full">
<span className="text-muted-foreground/50 font-medium">{activeFileName}</span>
<div className="mx-2 h-full w-px bg-muted-foreground/20"></div>
<button
onClick={onClose}
className="text-muted-foreground/50 hover:text-muted-foreground focus:outline-none"
aria-label="Close AI Chat"
>
<X size={18} />
</button>
</div>
</div>
<div ref={chatContainerRef} className="flex-grow overflow-y-auto p-4 space-y-4">
{messages.map((message, messageIndex) => (

View File

@ -76,6 +76,7 @@ export default function CodeEditor({
// Layout state
const [isHorizontalLayout, setIsHorizontalLayout] = useState(false);
const [previousLayout, setPreviousLayout] = useState(false);
// AI Chat state
const [isAIChatOpen, setIsAIChatOpen] = useState(false);
@ -530,13 +531,19 @@ export default function CodeEditor({
e.preventDefault()
setIsAIChatOpen(prev => !prev);
}
}
document.addEventListener("keydown", down)
};
document.addEventListener("keydown", down);
// Added this line to prevent Monaco editor from handling Cmd/Ctrl+L
editorRef?.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyL, () => {
setIsAIChatOpen(prev => !prev);
});
return () => {
document.removeEventListener("keydown", down)
}
}, [activeFileId, tabs, debouncedSaveData, setIsAIChatOpen])
}, [activeFileId, tabs, debouncedSaveData, setIsAIChatOpen, editorRef])
// Liveblocks live collaboration setup effect
useEffect(() => {
@ -848,7 +855,24 @@ export default function CodeEditor({
};
const toggleLayout = () => {
setIsHorizontalLayout(prev => !prev);
if (!isAIChatOpen) {
setIsHorizontalLayout(prev => !prev);
}
};
// Add an effect to handle layout changes when AI chat is opened/closed
useEffect(() => {
if (isAIChatOpen) {
setPreviousLayout(isHorizontalLayout);
setIsHorizontalLayout(true);
} else {
setIsHorizontalLayout(previousLayout);
}
}, [isAIChatOpen]);
// Modify the toggleAIChat function
const toggleAIChat = () => {
setIsAIChatOpen(prev => !prev);
};
// On disabled access for shared users, show un-interactable loading placeholder + info modal
@ -984,7 +1008,7 @@ export default function CodeEditor({
deletingFolderId={deletingFolderId}
/>
{/* Outer ResizablePanelGroup for main layout */}
<ResizablePanelGroup direction="horizontal">
<ResizablePanelGroup direction={isHorizontalLayout ? "horizontal" : "vertical"}>
{/* Left side: Editor and Preview/Terminal */}
<ResizablePanel defaultSize={isAIChatOpen ? 80 : 100} minSize={50}>
<ResizablePanelGroup direction={isHorizontalLayout ? "vertical" : "horizontal"}>
@ -1101,7 +1125,13 @@ export default function CodeEditor({
onExpand={() => setIsPreviewCollapsed(false)}
>
<div className="flex items-center justify-between">
<Button onClick={toggleLayout} size="sm" variant="ghost" className="mr-2 border">
<Button
onClick={toggleLayout}
size="sm"
variant="ghost"
className="mr-2 border"
disabled={isAIChatOpen}
>
{isHorizontalLayout ? <ArrowRightToLine className="w-4 h-4" /> : <ArrowDownToLine className="w-4 h-4" />}
</Button>
<PreviewWindow
@ -1145,10 +1175,11 @@ export default function CodeEditor({
<>
<ResizableHandle />
<ResizablePanel defaultSize={30} minSize={15}>
<AIChat
activeFileContent={activeFileContent}
activeFileName={tabs.find(tab => tab.id === activeFileId)?.name || 'No file selected'}
/>
<AIChat
activeFileContent={activeFileContent}
activeFileName={tabs.find(tab => tab.id === activeFileId)?.name || 'No file selected'}
onClose={toggleAIChat}
/>
</ResizablePanel>
</>
)}

View File

@ -4,9 +4,8 @@ import {
FilePlus,
FolderPlus,
Loader2,
MonitorPlay,
Search,
Sparkles,
MessageSquareMore,
} from "lucide-react";
import SidebarFile from "./file";
import SidebarFolder from "./folder";
@ -14,13 +13,12 @@ import { Sandbox, TFile, TFolder, TTab } from "@/lib/types";
import { useEffect, useRef, useState } from "react";
import New from "./new";
import { Socket } from "socket.io-client";
import { Switch } from "@/components/ui/switch";
import { Button } from "@/components/ui/button";
import {
dropTargetForElements,
monitorForElements,
} from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
import Button from "@/components/ui/customButton";
export default function Sidebar({
sandboxData,
@ -105,9 +103,9 @@ export default function Sidebar({
}, []);
return (
<div className="h-full w-56 select-none flex flex-col text-sm items-start justify-between p-2">
<div className="w-full flex flex-col items-start">
<div className="flex w-full items-center justify-between h-8 mb-1 ">
<div className="h-full w-56 select-none flex flex-col text-sm">
<div className="flex-grow overflow-auto p-2 pb-[84px]">
<div className="flex w-full items-center justify-between h-8 mb-1">
<div className="text-muted-foreground">Explorer</div>
<div className="flex space-x-1">
<button
@ -181,10 +179,25 @@ export default function Sidebar({
)}
</div>
</div>
<div className="w-full space-y-4">
{/* <Button className="w-full">
<MonitorPlay className="w-4 h-4 mr-2" /> Run
</Button> */}
<div className="fixed bottom-0 w-48 flex flex-col p-2 bg-background">
<Button variant="ghost" className="w-full justify-start text-sm text-muted-foreground font-normal h-8 px-2 mb-2" disabled aria-disabled="true" style={{ opacity: 1}}>
<Sparkles className="h-4 w-4 mr-2 text-indigo-500 opacity-70" />
Copilot
<div className="ml-auto">
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground">
<span className="text-xs"></span>G
</kbd>
</div>
</Button>
<Button variant="ghost" className="w-full justify-start text-sm text-muted-foreground font-normal h-8 px-2 mb-2" disabled aria-disabled="true" style={{ opacity: 1 }}>
<MessageSquareMore className="h-4 w-4 mr-2 text-indigo-500 opacity-70" />
AI Chat
<div className="ml-auto">
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground">
<span className="text-xs"></span>L
</kbd>
</div>
</Button>
</div>
</div>
);