|
| 1 | +import { useState, useEffect, useCallback, useMemo } from 'react' |
| 2 | +import { useNavigate } from '@tanstack/react-router' |
| 3 | +import type { StoryFeedItem } from '@/entities/story/model/types' |
| 4 | + |
| 5 | +export function useStoryViewer( |
| 6 | + storiesData: StoryFeedItem[], |
| 7 | + initialUserId: string |
| 8 | +) { |
| 9 | + const navigate = useNavigate() |
| 10 | + |
| 11 | + const currentUserIndex = useMemo(() => { |
| 12 | + const index = storiesData.findIndex( |
| 13 | + (u) => String(u.userId) === String(initialUserId) |
| 14 | + ) |
| 15 | + return index !== -1 ? index : 0 |
| 16 | + }, [storiesData, initialUserId]) |
| 17 | + |
| 18 | + const [currentStoryIndex, setCurrentStoryIndex] = useState(0) |
| 19 | + const [progress, setProgress] = useState(0) |
| 20 | + const [isPaused, setIsPaused] = useState(false) |
| 21 | + const [prevUserId, setPrevUserId] = useState(initialUserId) |
| 22 | + |
| 23 | + if (prevUserId !== initialUserId) { |
| 24 | + setPrevUserId(initialUserId) |
| 25 | + setCurrentStoryIndex(0) |
| 26 | + setProgress(0) |
| 27 | + } |
| 28 | + |
| 29 | + const currentUser = storiesData[currentUserIndex] |
| 30 | + const currentStory = currentUser?.stories?.[currentStoryIndex] |
| 31 | + |
| 32 | + const handleNext = useCallback(() => { |
| 33 | + if (!currentUser || !currentUser.stories) return |
| 34 | + |
| 35 | + if (currentStoryIndex < currentUser.stories.length - 1) { |
| 36 | + setCurrentStoryIndex((prev) => prev + 1) |
| 37 | + setProgress(0) |
| 38 | + } else if (currentUserIndex < storiesData.length - 1) { |
| 39 | + const nextUser = storiesData[currentUserIndex + 1] |
| 40 | + setTimeout(() => { |
| 41 | + navigate({ |
| 42 | + to: '/stories/$user_id', |
| 43 | + params: { user_id: String(nextUser.userId) }, |
| 44 | + }) |
| 45 | + }, 0) |
| 46 | + } else { |
| 47 | + setTimeout(() => { |
| 48 | + navigate({ to: '/' }) |
| 49 | + }, 0) |
| 50 | + } |
| 51 | + }, [currentUser, currentStoryIndex, currentUserIndex, storiesData, navigate]) |
| 52 | + |
| 53 | + const handlePrev = useCallback(() => { |
| 54 | + if (!currentUser || !currentUser.stories) return |
| 55 | + |
| 56 | + if (currentStoryIndex > 0) { |
| 57 | + setCurrentStoryIndex((prev) => prev - 1) |
| 58 | + setProgress(0) |
| 59 | + } else if (currentUserIndex > 0) { |
| 60 | + const prevUser = storiesData[currentUserIndex - 1] |
| 61 | + setTimeout(() => { |
| 62 | + navigate({ |
| 63 | + to: '/stories/$user_id', |
| 64 | + params: { user_id: String(prevUser.userId) }, |
| 65 | + }) |
| 66 | + }, 0) |
| 67 | + } |
| 68 | + }, [currentUser, currentStoryIndex, currentUserIndex, storiesData, navigate]) |
| 69 | + |
| 70 | + const togglePause = useCallback(() => setIsPaused((prev) => !prev), []) |
| 71 | + |
| 72 | + useEffect(() => { |
| 73 | + if (isPaused || !currentUser || !currentUser.stories) return |
| 74 | + |
| 75 | + const interval = setInterval(() => { |
| 76 | + setProgress((prev) => { |
| 77 | + if (prev >= 100) { |
| 78 | + handleNext() |
| 79 | + return 100 |
| 80 | + } |
| 81 | + return prev + 1 |
| 82 | + }) |
| 83 | + }, 50) |
| 84 | + return () => clearInterval(interval) |
| 85 | + }, [handleNext, isPaused, currentUser]) |
| 86 | + |
| 87 | + return { |
| 88 | + currentUser, |
| 89 | + currentStory, |
| 90 | + currentStoryIndex, |
| 91 | + currentUserIndex, |
| 92 | + progress, |
| 93 | + isPaused, |
| 94 | + handleNext, |
| 95 | + handlePrev, |
| 96 | + togglePause, |
| 97 | + } |
| 98 | +} |
0 commit comments