Refactor app flows and refresh UI components
This commit is contained in:
@@ -8,8 +8,10 @@ import useDataFromRef from '../../hooks/useDataFromRef'
|
||||
import usePlayer from '../../hooks/usePlayer'
|
||||
import PlaybackItem from './components/PlaybackItem'
|
||||
import PlaybackCharts from './components/PlaybackCharts'
|
||||
import PlaybackTypeTabs from './components/PlaybackTypeTabs'
|
||||
import { Palette } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import { getPlaybackType, matchesPlaybackType, PLAYBACK_TYPE } from '../../utils/playbackType'
|
||||
|
||||
const Playbacks = () => {
|
||||
const [activeIndex, setActiveIndex] = useState(0)
|
||||
@@ -21,25 +23,36 @@ const Playbacks = () => {
|
||||
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({
|
||||
const [playbackType, setPlaybackType] = useState(PLAYBACK_TYPE.LIVE)
|
||||
const {
|
||||
data: rawPlaybacks = [],
|
||||
loadMore,
|
||||
hasMore,
|
||||
loading,
|
||||
} = useDataFromRef({
|
||||
ref: projectsRef.where('playbackUrl', '!=', null),
|
||||
simpleRef: false,
|
||||
listener: false,
|
||||
usePagination: true,
|
||||
batchSize: 6,
|
||||
})
|
||||
const filteredPlaybacks = useMemo(
|
||||
() => rawPlaybacks.filter((item) => matchesPlaybackType(item, playbackType)),
|
||||
[playbackType, rawPlaybacks]
|
||||
)
|
||||
|
||||
const focusIndex = useMemo(() => {
|
||||
if (!focusProjectId) return -1
|
||||
return rawPlaybacks.findIndex((p) => p?.id === focusProjectId)
|
||||
}, [focusProjectId, rawPlaybacks])
|
||||
return filteredPlaybacks.findIndex((p) => p?.id === focusProjectId)
|
||||
}, [filteredPlaybacks, focusProjectId])
|
||||
|
||||
const playbacks = useMemo(() => {
|
||||
if (focusIndex < 0) return rawPlaybacks
|
||||
const target = rawPlaybacks[focusIndex]
|
||||
const before = rawPlaybacks.slice(0, focusIndex)
|
||||
const after = rawPlaybacks.slice(focusIndex + 1)
|
||||
if (focusIndex < 0) return filteredPlaybacks
|
||||
const target = filteredPlaybacks[focusIndex]
|
||||
const before = filteredPlaybacks.slice(0, focusIndex)
|
||||
const after = filteredPlaybacks.slice(focusIndex + 1)
|
||||
return [target, ...after, ...before]
|
||||
}, [focusIndex, rawPlaybacks])
|
||||
}, [filteredPlaybacks, focusIndex])
|
||||
|
||||
const onSnap = useCallback(
|
||||
(index) => {
|
||||
@@ -63,6 +76,14 @@ const Playbacks = () => {
|
||||
}
|
||||
}, [focusProjectId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!focusProjectId) return
|
||||
const focusedPlayback = rawPlaybacks.find((item) => item?.id === focusProjectId)
|
||||
if (focusedPlayback) {
|
||||
setPlaybackType(getPlaybackType(focusedPlayback))
|
||||
}
|
||||
}, [focusProjectId, rawPlaybacks])
|
||||
|
||||
useEffect(() => {
|
||||
if (loadMore && triedLoadMoreRef.current < 6) {
|
||||
triedLoadMoreRef.current += 1
|
||||
@@ -70,6 +91,12 @@ const Playbacks = () => {
|
||||
}
|
||||
}, [loadMore, playbacks])
|
||||
|
||||
useEffect(() => {
|
||||
if (playbacks.length === 0 && hasMore && !loading) {
|
||||
loadMore?.()
|
||||
}
|
||||
}, [hasMore, loadMore, loading, playbacks.length])
|
||||
|
||||
useEffect(() => {
|
||||
if (!focusProjectId) return
|
||||
if (focusIndex >= 0 && !hasAppliedFocusRef.current) {
|
||||
@@ -107,6 +134,12 @@ const Playbacks = () => {
|
||||
|
||||
const showFeed = viewMode === 'feed'
|
||||
|
||||
const handlePlaybackTypeChange = useCallback((nextType) => {
|
||||
setFocusProjectId(null)
|
||||
setPlaybackType(nextType)
|
||||
setActiveIndex(0)
|
||||
}, [])
|
||||
|
||||
const openFeedForPlayback = useCallback((project) => {
|
||||
const nextId =
|
||||
project && typeof project === 'object'
|
||||
@@ -115,17 +148,27 @@ const Playbacks = () => {
|
||||
if (!nextId) {
|
||||
return
|
||||
}
|
||||
if (project && typeof project === 'object') {
|
||||
setPlaybackType(getPlaybackType(project))
|
||||
}
|
||||
setFocusProjectId(nextId)
|
||||
setViewMode('feed')
|
||||
}, [])
|
||||
|
||||
if (!showFeed) {
|
||||
return <PlaybackCharts onPlaybackPress={openFeedForPlayback} />
|
||||
return (
|
||||
<PlaybackCharts
|
||||
onPlaybackPress={openFeedForPlayback}
|
||||
playbackType={playbackType}
|
||||
onPlaybackTypeChange={handlePlaybackTypeChange}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: 'black' }}>
|
||||
<Carousel
|
||||
key={playbackType}
|
||||
data={playbacks}
|
||||
vertical
|
||||
height={responsiveHeight(100)}
|
||||
@@ -141,14 +184,28 @@ const Playbacks = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Pressable
|
||||
style={styles.backToCharts}
|
||||
hitSlop={12}
|
||||
onPress={() => setViewMode('charts')}
|
||||
accessibilityLabel="Revenir au classement des playbacks"
|
||||
>
|
||||
<Text style={styles.backToChartsText}>Classement</Text>
|
||||
</Pressable>
|
||||
{playbacks.length === 0 && !loading ? (
|
||||
<View style={styles.emptyState} pointerEvents="none">
|
||||
<Text style={styles.emptyStateText}>
|
||||
Aucun {playbackType === PLAYBACK_TYPE.AI ? 'playback IA' : 'playback live'} pour le moment.
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
<View style={styles.feedHeader}>
|
||||
<PlaybackTypeTabs
|
||||
value={playbackType}
|
||||
onChange={handlePlaybackTypeChange}
|
||||
compact
|
||||
/>
|
||||
<Pressable
|
||||
style={styles.backToCharts}
|
||||
hitSlop={12}
|
||||
onPress={() => setViewMode('charts')}
|
||||
accessibilityLabel="Revenir au classement des playbacks"
|
||||
>
|
||||
<Text style={styles.backToChartsText}>Classement</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -156,10 +213,18 @@ const Playbacks = () => {
|
||||
export default Playbacks
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
backToCharts: {
|
||||
feedHeader: {
|
||||
position: 'absolute',
|
||||
top: 32,
|
||||
right: 20,
|
||||
left: 16,
|
||||
right: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: 8,
|
||||
zIndex: 20,
|
||||
},
|
||||
backToCharts: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 12,
|
||||
@@ -171,4 +236,16 @@ const styles = StyleSheet.create({
|
||||
fontSize: 12,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
emptyState: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
emptyStateText: {
|
||||
color: Palette.white,
|
||||
fontSize: 15,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
textAlign: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user