-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e20e0e6
commit ff04d26
Showing
10 changed files
with
302 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,115 +1,138 @@ | ||
import { useEffect } from "react"; | ||
import { useNavigate } from "react-router-dom"; | ||
import { Prompt } from "@/types"; | ||
|
||
export const usePromptNavigation = ( | ||
currentPromptIndex: number, | ||
prompts: Prompt[], | ||
type: string, | ||
currentImageIndex: number | ||
) => { | ||
|
||
// hooks/usePromptNavigation.ts | ||
import { useEffect, useCallback } from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import { Prompt } from '../types'; | ||
|
||
interface PromptNavigationHookResult { | ||
navigateToNext: () => void; | ||
navigateToPrevious: () => void; | ||
} | ||
|
||
interface UsePromptNavigationProps { | ||
currentPromptIndex: number; | ||
prompts: Prompt[]; | ||
type: string; | ||
currentImageIndex: number; | ||
} | ||
|
||
export const usePromptNavigation = ({ | ||
currentPromptIndex, | ||
prompts, | ||
type, | ||
currentImageIndex, | ||
}: UsePromptNavigationProps): PromptNavigationHookResult => { | ||
const navigate = useNavigate(); | ||
|
||
const navigateToNext = () => { | ||
const nextIndex = currentPromptIndex + 1; | ||
|
||
if (nextIndex < prompts.length) { | ||
const nextImageIndex = currentImageIndex + 1; | ||
const images = prompts[currentPromptIndex].images; | ||
|
||
console.log(`/prompt/${prompts[currentPromptIndex].id}`, { type, index: nextImageIndex }); | ||
if (nextImageIndex < images.length) { | ||
navigate(`/prompt/${prompts[currentPromptIndex].id}`, { | ||
state: { type, index: nextImageIndex }, | ||
}); | ||
} else { | ||
navigate(`/prompt/${prompts[nextIndex].id}`, { | ||
state: { type, index: 0 }, | ||
}); | ||
} | ||
const navigateToNext = useCallback(() => { | ||
const currentPrompt = prompts[currentPromptIndex]; | ||
if (!currentPrompt) return; | ||
|
||
const nextImageIndex = currentImageIndex + 1; | ||
|
||
// Check if we can move to the next image in the current prompt | ||
if (nextImageIndex < currentPrompt.images.length) { | ||
navigate(`/prompt/${currentPrompt.id}/${nextImageIndex}`, { | ||
state: { type }, | ||
replace: true, | ||
}); | ||
return; | ||
} | ||
}; | ||
|
||
const navigateToPrevious = () => { | ||
const previousIndex = currentPromptIndex - 1; | ||
const images = prompts[previousIndex]?.images; | ||
|
||
if (previousIndex >= 0) { | ||
const previousImageIndex = currentImageIndex - 1; | ||
|
||
if (previousImageIndex >= 0) { | ||
navigate(`/prompt/${prompts[currentPromptIndex].id}`, { | ||
state: { type, index: previousImageIndex }, | ||
}); | ||
} else { | ||
navigate(`/prompt/${prompts[previousIndex].id}`, { | ||
state: { type, index: images.length - 1 }, | ||
}); | ||
} | ||
|
||
// Move to the next prompt | ||
const nextPromptIndex = currentPromptIndex + 1; | ||
if (nextPromptIndex < prompts.length) { | ||
navigate(`/prompt/${prompts[nextPromptIndex].id}/0`, { | ||
state: { type }, | ||
replace: true, | ||
}); | ||
} | ||
}; | ||
}, [currentPromptIndex, currentImageIndex, prompts, type, navigate]); | ||
|
||
const navigateToPrevious = useCallback(() => { | ||
const currentPrompt = prompts[currentPromptIndex]; | ||
if (!currentPrompt) return; | ||
|
||
const previousImageIndex = currentImageIndex - 1; | ||
|
||
// Check if we can move to the previous image in the current prompt | ||
if (previousImageIndex >= 0) { | ||
navigate(`/prompt/${currentPrompt.id}/${previousImageIndex}`, { | ||
state: { type }, | ||
replace: true, | ||
}); | ||
return; | ||
} | ||
|
||
// Move to the previous prompt | ||
const previousPromptIndex = currentPromptIndex - 1; | ||
if (previousPromptIndex >= 0) { | ||
const previousPrompt = prompts[previousPromptIndex]; | ||
navigate( | ||
`/prompt/${previousPrompt.id}/${previousPrompt.images.length - 1}`, | ||
{ | ||
state: { type }, | ||
replace: true, | ||
} | ||
); | ||
} | ||
}, [currentPromptIndex, currentImageIndex, prompts, type, navigate]); | ||
|
||
useEffect(() => { | ||
let touchStartX = 0; | ||
|
||
const handleKeyDown = (event: KeyboardEvent) => { | ||
if (event.key === "ArrowRight" || event.key === "ArrowDown") { | ||
navigateToNext(); | ||
} else if (event.key === "ArrowLeft" || event.key === "ArrowUp") { | ||
navigateToPrevious(); | ||
switch (event.key) { | ||
case 'ArrowRight': | ||
case 'ArrowDown': | ||
event.preventDefault(); | ||
navigateToNext(); | ||
break; | ||
case 'ArrowLeft': | ||
case 'ArrowUp': | ||
event.preventDefault(); | ||
navigateToPrevious(); | ||
break; | ||
} | ||
}; | ||
|
||
const handleScroll = (event: WheelEvent) => { | ||
const handleWheel = (event: WheelEvent) => { | ||
event.preventDefault(); | ||
if (event.deltaY > 0) { | ||
navigateToNext(); | ||
} else if (event.deltaY < 0) { | ||
navigateToPrevious(); | ||
} | ||
}; | ||
|
||
// Variables to store touch start and end coordinates | ||
let touchStartX = 0; | ||
let touchEndX = 0; | ||
|
||
// Handle touch start | ||
const handleTouchStart = (event: TouchEvent) => { | ||
touchStartX = event.touches[0].clientX; | ||
}; | ||
|
||
// Handle touch move | ||
const handleTouchMove = (event: TouchEvent) => { | ||
touchEndX = event.touches[0].clientX; | ||
}; | ||
|
||
// Handle touch end | ||
const handleTouchEnd = () => { | ||
if (touchStartX - touchEndX > 50) { | ||
// Swipe left to navigate to the next prompt | ||
const handleTouchEnd = (event: TouchEvent) => { | ||
const touchEndX = event.changedTouches[0].clientX; | ||
const SWIPE_THRESHOLD = 50; | ||
|
||
if (touchStartX - touchEndX > SWIPE_THRESHOLD) { | ||
navigateToNext(); | ||
} else if (touchEndX - touchStartX > 50) { | ||
// Swipe right to navigate to the previous prompt | ||
} else if (touchEndX - touchStartX > SWIPE_THRESHOLD) { | ||
navigateToPrevious(); | ||
} | ||
}; | ||
|
||
window.addEventListener("keydown", handleKeyDown); | ||
window.addEventListener("wheel", handleScroll); | ||
|
||
// Add touch event listeners for mobile support | ||
window.addEventListener("touchstart", handleTouchStart); | ||
window.addEventListener("touchmove", handleTouchMove); | ||
window.addEventListener("touchend", handleTouchEnd); | ||
// Add event listeners with passive: false for better scroll performance | ||
window.addEventListener('keydown', handleKeyDown); | ||
window.addEventListener('wheel', handleWheel, { passive: false }); | ||
window.addEventListener('touchstart', handleTouchStart, { passive: true }); | ||
window.addEventListener('touchend', handleTouchEnd, { passive: true }); | ||
|
||
return () => { | ||
window.removeEventListener("keydown", handleKeyDown); | ||
window.removeEventListener("wheel", handleScroll); | ||
|
||
// Remove touch event listeners | ||
window.removeEventListener("touchstart", handleTouchStart); | ||
window.removeEventListener("touchmove", handleTouchMove); | ||
window.removeEventListener("touchend", handleTouchEnd); | ||
window.removeEventListener('keydown', handleKeyDown); | ||
window.removeEventListener('wheel', handleWheel); | ||
window.removeEventListener('touchstart', handleTouchStart); | ||
window.removeEventListener('touchend', handleTouchEnd); | ||
}; | ||
}, [currentPromptIndex, currentImageIndex, prompts]); | ||
}, [navigateToNext, navigateToPrevious]); | ||
|
||
// Return the navigation functions for potential external use | ||
return { navigateToNext, navigateToPrevious }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.