'use client'; import { useState, useEffect, useMemo } from 'react'; import { createGlobalState } from 'react-global-hooks'; import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react'; export interface SampleImageModalState { imgPath: string; numSamples: number; sampleImages: string[]; } export const sampleImageModalState = createGlobalState(null); export const openSampleImage = (sampleImageProps: SampleImageModalState) => { sampleImageModalState.set(sampleImageProps); }; export default function SampleImageModal() { const [imageModal, setImageModal] = sampleImageModalState.use(); const [isOpen, setIsOpen] = useState(false); useEffect(() => { if (imageModal) { setIsOpen(true); } }, [imageModal]); useEffect(() => { if (!isOpen) { // use timeout to allow the dialog to close before resetting the state setTimeout(() => { setImageModal(null); }, 500); } }, [isOpen]); const onCancel = () => { setIsOpen(false); }; const imgInfo = useMemo(() => { const ii = { filename: '', step: 0, promptIdx: 0, }; if (imageModal?.imgPath) { const filename = imageModal.imgPath.split('/').pop(); if (!filename) return ii; // filename is ___. ii.filename = filename as string; const parts = filename .split('.')[0] .split('_') .filter(p => p !== ''); if (parts.length === 3) { ii.step = parseInt(parts[1]); ii.promptIdx = parseInt(parts[2]); } } return ii; }, [imageModal]); const handleArrowUp = () => { if (!imageModal) return; console.log('Arrow Up pressed'); // Change image to same sample but up one step const currentIdx = imageModal.sampleImages.findIndex(img => img === imageModal.imgPath); if (currentIdx === -1) return; const nextIdx = currentIdx - imageModal.numSamples; if (nextIdx < 0) return; openSampleImage({ imgPath: imageModal.sampleImages[nextIdx], numSamples: imageModal.numSamples, sampleImages: imageModal.sampleImages, }); }; const handleArrowDown = () => { if (!imageModal) return; console.log('Arrow Down pressed'); // Change image to same sample but down one step const currentIdx = imageModal.sampleImages.findIndex(img => img === imageModal.imgPath); if (currentIdx === -1) return; const nextIdx = currentIdx + imageModal.numSamples; if (nextIdx >= imageModal.sampleImages.length) return; openSampleImage({ imgPath: imageModal.sampleImages[nextIdx], numSamples: imageModal.numSamples, sampleImages: imageModal.sampleImages, }); }; const handleArrowLeft = () => { if (!imageModal) return; if (imgInfo.promptIdx === 0) return; console.log('Arrow Left pressed'); // go to previous sample const currentIdx = imageModal.sampleImages.findIndex(img => img === imageModal.imgPath); if (currentIdx === -1) return; const minIdx = currentIdx - imgInfo.promptIdx; const nextIdx = currentIdx - 1; if (nextIdx < minIdx) return; openSampleImage({ imgPath: imageModal.sampleImages[nextIdx], numSamples: imageModal.numSamples, sampleImages: imageModal.sampleImages, }); }; const handleArrowRight = () => { if (!imageModal) return; console.log('Arrow Right pressed'); // go to next sample const currentIdx = imageModal.sampleImages.findIndex(img => img === imageModal.imgPath); if (currentIdx === -1) return; const stepMinIdx = currentIdx - imgInfo.promptIdx; const maxIdx = stepMinIdx + imageModal.numSamples - 1; const nextIdx = currentIdx + 1; if (nextIdx > maxIdx) return; if (nextIdx >= imageModal.sampleImages.length) return; openSampleImage({ imgPath: imageModal.sampleImages[nextIdx], numSamples: imageModal.numSamples, sampleImages: imageModal.sampleImages, }); }; // Handle keyboard events useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (!isOpen) return; switch (event.key) { case 'Escape': onCancel(); break; case 'ArrowUp': handleArrowUp(); break; case 'ArrowDown': handleArrowDown(); break; case 'ArrowLeft': handleArrowLeft(); break; case 'ArrowRight': handleArrowRight(); break; default: break; } }; window.addEventListener('keydown', handleKeyDown); return () => { window.removeEventListener('keydown', handleKeyDown); }; }, [isOpen, imageModal, imgInfo]); return (
{imageModal?.imgPath && ( Sample Image )}
step: {imgInfo.step}
); }