Refactor app flows and refresh UI components

This commit is contained in:
Jacques_tirot
2026-09-08 14:20:23 +02:00
parent 4e14a38d4e
commit 814e1d27fb
71 changed files with 1984 additions and 509 deletions
+96 -19
View File
@@ -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',
},
})