Changes
This commit is contained in:
+32
-22
@@ -10,6 +10,7 @@ import { useToast } from '@/hooks/use-toast';
|
|||||||
import GlitchText from '@/components/GlitchText';
|
import GlitchText from '@/components/GlitchText';
|
||||||
import MessageContent from '@/components/MessageContent';
|
import MessageContent from '@/components/MessageContent';
|
||||||
import { AI_PROVIDERS, AIProvider, getProvider, CUSTOM_API_STORAGE_KEY } from '@/lib/aiProviders';
|
import { AI_PROVIDERS, AIProvider, getProvider, CUSTOM_API_STORAGE_KEY } from '@/lib/aiProviders';
|
||||||
|
import { useBrowserFullscreen } from '@/hooks/useGameDimensions';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -104,21 +105,30 @@ const AIChat = () => {
|
|||||||
}
|
}
|
||||||
}, [customApiConfig]);
|
}, [customApiConfig]);
|
||||||
|
|
||||||
// Exit fullscreen on Escape key
|
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
|
||||||
|
const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();
|
||||||
|
|
||||||
// Exit fullscreen on Escape key
|
// Exit fullscreen on Escape key
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleEscape = (e: KeyboardEvent) => {
|
const handleEscape = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Escape' && isFullscreen) {
|
if (e.key === 'Escape' && isFullscreen) {
|
||||||
setIsFullscreen(false);
|
setIsFullscreen(false);
|
||||||
|
exitFullscreen();
|
||||||
playSound('click');
|
playSound('click');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('keydown', handleEscape);
|
window.addEventListener('keydown', handleEscape);
|
||||||
return () => window.removeEventListener('keydown', handleEscape);
|
return () => window.removeEventListener('keydown', handleEscape);
|
||||||
}, [isFullscreen, playSound]);
|
}, [isFullscreen, playSound, exitFullscreen]);
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = async () => {
|
||||||
setIsFullscreen(prev => !prev);
|
if (!isFullscreen) {
|
||||||
|
setIsFullscreen(true);
|
||||||
|
await enterFullscreen();
|
||||||
|
} else {
|
||||||
|
setIsFullscreen(false);
|
||||||
|
await exitFullscreen();
|
||||||
|
}
|
||||||
playSound('click');
|
playSound('click');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -379,21 +389,21 @@ const AIChat = () => {
|
|||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className={`flex flex-col ${
|
className={`flex flex-col ${
|
||||||
isFullscreen
|
isFullscreen
|
||||||
? 'fixed inset-0 z-50 bg-background p-4 md:p-8'
|
? 'fixed inset-0 z-50 bg-background p-3 md:p-8 overflow-hidden'
|
||||||
: 'h-full'
|
: 'h-full'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2 mb-4">
|
<div className="flex items-center justify-between gap-2 mb-3 flex-shrink-0">
|
||||||
<GlitchText
|
<GlitchText
|
||||||
text="AI Terminal"
|
text="AI Terminal"
|
||||||
className="font-minecraft text-2xl md:text-3xl text-primary text-glow"
|
className={`font-minecraft ${isMobile ? 'text-xl' : 'text-2xl md:text-3xl'} text-primary text-glow`}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-1 sm:gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={toggleFullscreen}
|
onClick={toggleFullscreen}
|
||||||
className="text-primary hover:bg-primary/20 order-first sm:order-last"
|
className="text-primary hover:bg-primary/20 p-2"
|
||||||
title={isFullscreen ? 'Exit fullscreen (Esc)' : 'Fullscreen'}
|
title={isFullscreen ? 'Exit fullscreen (Esc)' : 'Fullscreen'}
|
||||||
>
|
>
|
||||||
{isFullscreen ? (
|
{isFullscreen ? (
|
||||||
@@ -404,8 +414,8 @@ const AIChat = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
{messages.length > 0 && (
|
{messages.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-2 px-2 py-1 border border-primary/30 rounded text-xs font-pixel">
|
<div className="hidden sm:flex items-center gap-2 px-2 py-1 border border-primary/30 rounded text-xs font-pixel">
|
||||||
<span className="text-muted-foreground">Memory:</span>
|
<span className="text-muted-foreground">Mem:</span>
|
||||||
<span
|
<span
|
||||||
className={`${
|
className={`${
|
||||||
(() => {
|
(() => {
|
||||||
@@ -437,24 +447,24 @@ const AIChat = () => {
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={clearChat}
|
onClick={clearChat}
|
||||||
className="text-primary hover:bg-primary/20"
|
className="text-primary hover:bg-primary/20 p-2"
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4 mr-2" />
|
<Trash2 className="w-4 h-4" />
|
||||||
Clear
|
<span className="hidden sm:inline ml-2">Clear</span>
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-3 flex-shrink-0 overflow-x-auto">
|
||||||
<span className="text-muted-foreground font-pixel text-sm">{'>'} Model:</span>
|
<span className="text-muted-foreground font-pixel text-xs sm:text-sm whitespace-nowrap">{'>'} Model:</span>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-primary hover:bg-primary/20 font-pixel text-sm gap-1"
|
className="text-primary hover:bg-primary/20 font-pixel text-xs sm:text-sm gap-1 px-2"
|
||||||
>
|
>
|
||||||
{getProvider(selectedProvider).name}
|
{getProvider(selectedProvider).name}
|
||||||
<ChevronDown className="w-3 h-3" />
|
<ChevronDown className="w-3 h-3" />
|
||||||
@@ -507,11 +517,11 @@ const AIChat = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ScrollArea
|
<ScrollArea
|
||||||
className="flex-1 border border-primary/30 rounded-lg p-4 mb-4 bg-background/50"
|
className="flex-1 min-h-0 border border-primary/30 rounded-lg p-2 sm:p-4 mb-3 bg-background/50"
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
>
|
>
|
||||||
{messages.length === 0 ? (
|
{messages.length === 0 ? (
|
||||||
<div className="h-full flex items-center justify-center text-muted-foreground">
|
<div className="h-full flex items-center justify-center text-muted-foreground py-8">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Bot className="w-12 h-12 mx-auto mb-4 opacity-50" />
|
<Bot className="w-12 h-12 mx-auto mb-4 opacity-50" />
|
||||||
<p className="font-pixel text-sm">No messages yet.</p>
|
<p className="font-pixel text-sm">No messages yet.</p>
|
||||||
@@ -549,7 +559,7 @@ const AIChat = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`max-w-[80%] p-3 rounded-lg ${
|
className={`max-w-[85%] sm:max-w-[80%] p-2 sm:p-3 rounded-lg text-sm ${
|
||||||
message.role === 'user'
|
message.role === 'user'
|
||||||
? 'bg-primary/20 border border-primary/50'
|
? 'bg-primary/20 border border-primary/50'
|
||||||
: 'bg-secondary/50 border border-primary/30'
|
: 'bg-secondary/50 border border-primary/30'
|
||||||
@@ -590,14 +600,14 @@ const AIChat = () => {
|
|||||||
)}
|
)}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 flex-shrink-0">
|
||||||
<Textarea
|
<Textarea
|
||||||
value={input}
|
value={input}
|
||||||
onChange={(e) => setInput(e.target.value)}
|
onChange={(e) => setInput(e.target.value)}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Type your message..."
|
placeholder="Type your message..."
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="resize-none font-pixel text-sm bg-background/50 border-primary/50 text-primary placeholder:text-muted-foreground focus:border-primary"
|
className="resize-none font-pixel text-xs sm:text-sm bg-background/50 border-primary/50 text-primary placeholder:text-muted-foreground focus:border-primary min-h-[60px]"
|
||||||
rows={2}
|
rows={2}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Reference in New Issue
Block a user