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 ChatInput from './ChatInput';
import ContextDisplay from './ContextDisplay'; import ContextDisplay from './ContextDisplay';
import { handleSend, handleStopGeneration } from './lib/chatUtils'; import { handleSend, handleStopGeneration } from './lib/chatUtils';
import { X } from 'lucide-react';
interface Message { interface Message {
role: 'user' | 'assistant'; role: 'user' | 'assistant';
@ -11,7 +12,7 @@ interface Message {
context?: string; 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 [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState(''); const [input, setInput] = useState('');
const [isGenerating, setIsGenerating] = useState(false); 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 flex-col h-screen w-full">
<div className="flex justify-between items-center p-2 border-b"> <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">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>
<div ref={chatContainerRef} className="flex-grow overflow-y-auto p-4 space-y-4"> <div ref={chatContainerRef} className="flex-grow overflow-y-auto p-4 space-y-4">
{messages.map((message, messageIndex) => ( {messages.map((message, messageIndex) => (

View File

@ -76,6 +76,7 @@ export default function CodeEditor({
// Layout state // Layout state
const [isHorizontalLayout, setIsHorizontalLayout] = useState(false); const [isHorizontalLayout, setIsHorizontalLayout] = useState(false);
const [previousLayout, setPreviousLayout] = useState(false);
// AI Chat state // AI Chat state
const [isAIChatOpen, setIsAIChatOpen] = useState(false); const [isAIChatOpen, setIsAIChatOpen] = useState(false);
@ -530,13 +531,19 @@ export default function CodeEditor({
e.preventDefault() e.preventDefault()
setIsAIChatOpen(prev => !prev); 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 () => { return () => {
document.removeEventListener("keydown", down) document.removeEventListener("keydown", down)
} }
}, [activeFileId, tabs, debouncedSaveData, setIsAIChatOpen]) }, [activeFileId, tabs, debouncedSaveData, setIsAIChatOpen, editorRef])
// Liveblocks live collaboration setup effect // Liveblocks live collaboration setup effect
useEffect(() => { useEffect(() => {
@ -848,7 +855,24 @@ export default function CodeEditor({
}; };
const toggleLayout = () => { 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 // On disabled access for shared users, show un-interactable loading placeholder + info modal
@ -984,7 +1008,7 @@ export default function CodeEditor({
deletingFolderId={deletingFolderId} deletingFolderId={deletingFolderId}
/> />
{/* Outer ResizablePanelGroup for main layout */} {/* Outer ResizablePanelGroup for main layout */}
<ResizablePanelGroup direction="horizontal"> <ResizablePanelGroup direction={isHorizontalLayout ? "horizontal" : "vertical"}>
{/* Left side: Editor and Preview/Terminal */} {/* Left side: Editor and Preview/Terminal */}
<ResizablePanel defaultSize={isAIChatOpen ? 80 : 100} minSize={50}> <ResizablePanel defaultSize={isAIChatOpen ? 80 : 100} minSize={50}>
<ResizablePanelGroup direction={isHorizontalLayout ? "vertical" : "horizontal"}> <ResizablePanelGroup direction={isHorizontalLayout ? "vertical" : "horizontal"}>
@ -1101,7 +1125,13 @@ export default function CodeEditor({
onExpand={() => setIsPreviewCollapsed(false)} onExpand={() => setIsPreviewCollapsed(false)}
> >
<div className="flex items-center justify-between"> <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" />} {isHorizontalLayout ? <ArrowRightToLine className="w-4 h-4" /> : <ArrowDownToLine className="w-4 h-4" />}
</Button> </Button>
<PreviewWindow <PreviewWindow
@ -1145,10 +1175,11 @@ export default function CodeEditor({
<> <>
<ResizableHandle /> <ResizableHandle />
<ResizablePanel defaultSize={30} minSize={15}> <ResizablePanel defaultSize={30} minSize={15}>
<AIChat <AIChat
activeFileContent={activeFileContent} activeFileContent={activeFileContent}
activeFileName={tabs.find(tab => tab.id === activeFileId)?.name || 'No file selected'} activeFileName={tabs.find(tab => tab.id === activeFileId)?.name || 'No file selected'}
/> onClose={toggleAIChat}
/>
</ResizablePanel> </ResizablePanel>
</> </>
)} )}
@ -1171,4 +1202,4 @@ const defaultCompilerOptions: monaco.languages.typescript.CompilerOptions = {
module: monaco.languages.typescript.ModuleKind.ESNext, module: monaco.languages.typescript.ModuleKind.ESNext,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
target: monaco.languages.typescript.ScriptTarget.ESNext, target: monaco.languages.typescript.ScriptTarget.ESNext,
} }

View File

@ -4,9 +4,8 @@ import {
FilePlus, FilePlus,
FolderPlus, FolderPlus,
Loader2, Loader2,
MonitorPlay,
Search,
Sparkles, Sparkles,
MessageSquareMore,
} from "lucide-react"; } from "lucide-react";
import SidebarFile from "./file"; import SidebarFile from "./file";
import SidebarFolder from "./folder"; import SidebarFolder from "./folder";
@ -14,14 +13,13 @@ import { Sandbox, TFile, TFolder, TTab } from "@/lib/types";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import New from "./new"; import New from "./new";
import { Socket } from "socket.io-client"; import { Socket } from "socket.io-client";
import { Switch } from "@/components/ui/switch"; import { Button } from "@/components/ui/button";
import { import {
dropTargetForElements, dropTargetForElements,
monitorForElements, monitorForElements,
} from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
import Button from "@/components/ui/customButton";
export default function Sidebar({ export default function Sidebar({
sandboxData, sandboxData,
files, files,
@ -105,9 +103,9 @@ export default function Sidebar({
}, []); }, []);
return ( return (
<div className="h-full w-56 select-none flex flex-col text-sm items-start justify-between p-2"> <div className="h-full w-56 select-none flex flex-col text-sm">
<div className="w-full flex flex-col items-start"> <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="flex w-full items-center justify-between h-8 mb-1">
<div className="text-muted-foreground">Explorer</div> <div className="text-muted-foreground">Explorer</div>
<div className="flex space-x-1"> <div className="flex space-x-1">
<button <button
@ -181,10 +179,25 @@ export default function Sidebar({
)} )}
</div> </div>
</div> </div>
<div className="w-full space-y-4"> <div className="fixed bottom-0 w-48 flex flex-col p-2 bg-background">
{/* <Button className="w-full"> <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}}>
<MonitorPlay className="w-4 h-4 mr-2" /> Run <Sparkles className="h-4 w-4 mr-2 text-indigo-500 opacity-70" />
</Button> */} 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>
</div> </div>
); );