chat update
This commit is contained in:
@@ -298,45 +298,42 @@ export default function ChatDetail({ chatId }: { chatId: string }) {
|
|||||||
const handleImageNavigation = (direction: 'prev' | 'next') => {
|
const handleImageNavigation = (direction: 'prev' | 'next') => {
|
||||||
if (!chat || selectedMessageIndex === null || selectedAttachmentIndex === null) return;
|
if (!chat || selectedMessageIndex === null || selectedAttachmentIndex === null) return;
|
||||||
|
|
||||||
const currentMessage = chat.messages[selectedMessageIndex];
|
// Get all images from all messages
|
||||||
const currentAttachments = currentMessage.attachments.filter(att =>
|
const allImages: { messageIndex: number; attachmentIndex: number; url: string }[] = [];
|
||||||
/\.(jpg|jpeg|png|gif|webp|svg|bmp|tiff)($|\?)/i.test(att) ||
|
|
||||||
att.includes('/photos/') ||
|
chat.messages.forEach((msg, msgIndex) => {
|
||||||
att.includes('/photo/')
|
msg.attachments.forEach((att, attIndex) => {
|
||||||
|
if (/\.(jpg|jpeg|png|gif|webp|svg|bmp|tiff)($|\?)/i.test(att) ||
|
||||||
|
att.includes('/photos/') ||
|
||||||
|
att.includes('/photo/')) {
|
||||||
|
allImages.push({ messageIndex: msgIndex, attachmentIndex: attIndex, url: att });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allImages.length === 0) return;
|
||||||
|
|
||||||
|
// Find current image index
|
||||||
|
const currentIndex = allImages.findIndex(img =>
|
||||||
|
img.messageIndex === selectedMessageIndex &&
|
||||||
|
img.attachmentIndex === selectedAttachmentIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
let newAttachmentIndex = selectedAttachmentIndex;
|
if (currentIndex === -1) return;
|
||||||
let newMessageIndex = selectedMessageIndex;
|
|
||||||
|
|
||||||
|
// Calculate new index
|
||||||
|
let newIndex;
|
||||||
if (direction === 'next') {
|
if (direction === 'next') {
|
||||||
newAttachmentIndex++;
|
newIndex = (currentIndex + 1) % allImages.length;
|
||||||
if (newAttachmentIndex >= currentAttachments.length) {
|
|
||||||
newAttachmentIndex = 0;
|
|
||||||
newMessageIndex++;
|
|
||||||
if (newMessageIndex >= chat.messages.length) {
|
|
||||||
newMessageIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
newAttachmentIndex--;
|
newIndex = currentIndex === 0 ? allImages.length - 1 : currentIndex - 1;
|
||||||
if (newAttachmentIndex < 0) {
|
|
||||||
newMessageIndex--;
|
|
||||||
if (newMessageIndex < 0) {
|
|
||||||
newMessageIndex = chat.messages.length - 1;
|
|
||||||
}
|
|
||||||
const prevMessage = chat.messages[newMessageIndex];
|
|
||||||
const prevAttachments = prevMessage.attachments.filter(att =>
|
|
||||||
/\.(jpg|jpeg|png|gif|webp|svg|bmp|tiff)($|\?)/i.test(att) ||
|
|
||||||
att.includes('/photos/') ||
|
|
||||||
att.includes('/photo/')
|
|
||||||
);
|
|
||||||
newAttachmentIndex = prevAttachments.length - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedMessageIndex(newMessageIndex);
|
// Update state with new image
|
||||||
setSelectedAttachmentIndex(newAttachmentIndex);
|
const newImage = allImages[newIndex];
|
||||||
setSelectedImage(currentAttachments[newAttachmentIndex]);
|
setSelectedMessageIndex(newImage.messageIndex);
|
||||||
|
setSelectedAttachmentIndex(newImage.attachmentIndex);
|
||||||
|
setSelectedImage(newImage.url);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the image click handler
|
// Update the image click handler
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||||
import { X, ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
interface ImageViewerModalProps {
|
interface ImageViewerModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -10,24 +11,49 @@ interface ImageViewerModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ImageViewerModal({ isOpen, onClose, imageUrl, onNavigate }: ImageViewerModalProps) {
|
export function ImageViewerModal({ isOpen, onClose, imageUrl, onNavigate }: ImageViewerModalProps) {
|
||||||
|
const handleNavigation = (direction: 'prev' | 'next') => (e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onNavigate?.(direction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add keyboard navigation
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (!onNavigate) return;
|
||||||
|
|
||||||
|
if (e.key === 'ArrowLeft') {
|
||||||
|
e.preventDefault();
|
||||||
|
onNavigate('prev');
|
||||||
|
} else if (e.key === 'ArrowRight') {
|
||||||
|
e.preventDefault();
|
||||||
|
onNavigate('next');
|
||||||
|
} else if (e.key === 'Escape') {
|
||||||
|
e.preventDefault();
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [isOpen, onNavigate, onClose]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||||
<DialogContent className="max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-none">
|
<DialogContent className="max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-none">
|
||||||
<div className="relative w-full h-full">
|
<div className="relative w-full h-full">
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
className="absolute -top-10 right-0 p-2 text-white hover:text-gray-300 transition-colors"
|
|
||||||
>
|
|
||||||
<X size={24} />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{onNavigate && (
|
{onNavigate && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="absolute left-4 top-1/2 -translate-y-1/2 text-white hover:text-gray-300 hover:bg-white/10"
|
className="absolute left-4 top-1/2 -translate-y-1/2 text-white hover:text-gray-300 hover:bg-white/10"
|
||||||
onClick={() => onNavigate('prev')}
|
onClick={handleNavigation('prev')}
|
||||||
>
|
>
|
||||||
<ChevronLeft size={24} />
|
<ChevronLeft size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -35,7 +61,7 @@ export function ImageViewerModal({ isOpen, onClose, imageUrl, onNavigate }: Imag
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-white hover:text-gray-300 hover:bg-white/10"
|
className="absolute right-4 top-1/2 -translate-y-1/2 text-white hover:text-gray-300 hover:bg-white/10"
|
||||||
onClick={() => onNavigate('next')}
|
onClick={handleNavigation('next')}
|
||||||
>
|
>
|
||||||
<ChevronRight size={24} />
|
<ChevronRight size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user