175 lines
4.9 KiB
JavaScript
175 lines
4.9 KiB
JavaScript
import { useIsFocused, useRoute } from '@react-navigation/native'
|
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
|
import Carousel from 'react-native-reanimated-carousel'
|
|
import { responsiveHeight } from 'react-native-responsive-dimensions'
|
|
import { projectsRef } from '../../config/firebase'
|
|
import useDataFromRef from '../../hooks/useDataFromRef'
|
|
import usePlayer from '../../hooks/usePlayer'
|
|
import PlaybackItem from './components/PlaybackItem'
|
|
import PlaybackCharts from './components/PlaybackCharts'
|
|
import { Palette } from '../../styles'
|
|
import { FONT_FAMILY } from '../../styles/Fonts'
|
|
|
|
const Playbacks = () => {
|
|
const [activeIndex, setActiveIndex] = useState(0)
|
|
const userCache = useRef(new Map())
|
|
const isFocused = useIsFocused()
|
|
const wasFocusedRef = useRef(false)
|
|
const route = useRoute()
|
|
const { stop } = usePlayer() || {}
|
|
const initialFocusProjectId = route?.params?.projectId || route?.params?.focusId || null
|
|
const [focusProjectId, setFocusProjectId] = useState(initialFocusProjectId)
|
|
const [viewMode, setViewMode] = useState(initialFocusProjectId ? 'feed' : 'charts')
|
|
const { data: rawPlaybacks = [], loadMore } = useDataFromRef({
|
|
ref: projectsRef.where('playbackUrl', '!=', null),
|
|
simpleRef: false,
|
|
listener: false,
|
|
usePagination: true,
|
|
batchSize: 6,
|
|
})
|
|
const focusIndex = useMemo(() => {
|
|
if (!focusProjectId) return -1
|
|
return rawPlaybacks.findIndex((p) => p?.id === focusProjectId)
|
|
}, [focusProjectId, rawPlaybacks])
|
|
|
|
const playbacks = useMemo(() => {
|
|
if (focusIndex < 0) return rawPlaybacks
|
|
const target = rawPlaybacks[focusIndex]
|
|
const before = rawPlaybacks.slice(0, focusIndex)
|
|
const after = rawPlaybacks.slice(focusIndex + 1)
|
|
return [target, ...after, ...before]
|
|
}, [focusIndex, rawPlaybacks])
|
|
|
|
const onSnap = useCallback(
|
|
(index) => {
|
|
setActiveIndex(index)
|
|
if (index >= (playbacks?.length || 0) - 6) {
|
|
loadMore?.()
|
|
}
|
|
},
|
|
[playbacks?.length, loadMore]
|
|
)
|
|
|
|
const triedLoadMoreRef = useRef(0)
|
|
const focusLoadAttemptsRef = useRef(0)
|
|
const hasAppliedFocusRef = useRef(false)
|
|
|
|
useEffect(() => {
|
|
focusLoadAttemptsRef.current = 0
|
|
hasAppliedFocusRef.current = false
|
|
if (!focusProjectId) {
|
|
setActiveIndex(0)
|
|
}
|
|
}, [focusProjectId])
|
|
|
|
useEffect(() => {
|
|
if (loadMore && triedLoadMoreRef.current < 6) {
|
|
triedLoadMoreRef.current += 1
|
|
loadMore()
|
|
}
|
|
}, [loadMore, playbacks])
|
|
|
|
useEffect(() => {
|
|
if (!focusProjectId) return
|
|
if (focusIndex >= 0 && !hasAppliedFocusRef.current) {
|
|
hasAppliedFocusRef.current = true
|
|
setActiveIndex(0)
|
|
return
|
|
}
|
|
if (loadMore && focusLoadAttemptsRef.current < 6) {
|
|
focusLoadAttemptsRef.current += 1
|
|
loadMore()
|
|
}
|
|
}, [focusIndex, focusProjectId, loadMore, playbacks])
|
|
|
|
useEffect(() => {
|
|
const nextFocusId = route?.params?.projectId || route?.params?.focusId || null
|
|
setFocusProjectId(nextFocusId)
|
|
if (nextFocusId) {
|
|
setViewMode('feed')
|
|
}
|
|
}, [route?.params?.focusId, route?.params?.projectId])
|
|
|
|
useEffect(() => {
|
|
if (isFocused && !wasFocusedRef.current) {
|
|
stop?.().catch(() => {})
|
|
}
|
|
wasFocusedRef.current = isFocused
|
|
}, [isFocused, stop])
|
|
|
|
useEffect(() => {
|
|
if (viewMode !== 'feed') {
|
|
return
|
|
}
|
|
setActiveIndex(0)
|
|
}, [viewMode])
|
|
|
|
const showFeed = viewMode === 'feed'
|
|
|
|
const openFeedForPlayback = useCallback((project) => {
|
|
const nextId =
|
|
project && typeof project === 'object'
|
|
? project?.id || project?.projectId || null
|
|
: project || null
|
|
if (!nextId) {
|
|
return
|
|
}
|
|
setFocusProjectId(nextId)
|
|
setViewMode('feed')
|
|
}, [])
|
|
|
|
if (!showFeed) {
|
|
return <PlaybackCharts onPlaybackPress={openFeedForPlayback} />
|
|
}
|
|
|
|
return (
|
|
<View style={{ flex: 1, backgroundColor: 'black' }}>
|
|
<Carousel
|
|
data={playbacks}
|
|
vertical
|
|
height={responsiveHeight(100)}
|
|
pagingEnabled
|
|
windowSize={5}
|
|
onSnapToItem={onSnap}
|
|
renderItem={({ item, index }) => (
|
|
<PlaybackItem
|
|
key={item?.id || index}
|
|
item={item}
|
|
userCache={userCache}
|
|
isActive={isFocused && index === activeIndex}
|
|
/>
|
|
)}
|
|
/>
|
|
<Pressable
|
|
style={styles.backToCharts}
|
|
hitSlop={12}
|
|
onPress={() => setViewMode('charts')}
|
|
accessibilityLabel="Revenir au classement des playbacks"
|
|
>
|
|
<Text style={styles.backToChartsText}>Classement</Text>
|
|
</Pressable>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default Playbacks
|
|
|
|
const styles = StyleSheet.create({
|
|
backToCharts: {
|
|
position: 'absolute',
|
|
top: 32,
|
|
right: 20,
|
|
paddingVertical: 8,
|
|
paddingHorizontal: 12,
|
|
borderRadius: 12,
|
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
|
zIndex: 20,
|
|
},
|
|
backToChartsText: {
|
|
color: Palette.white,
|
|
fontSize: 12,
|
|
fontFamily: FONT_FAMILY.InterSemiBold,
|
|
},
|
|
})
|