import React, { useCallback, useEffect, useMemo, useState } from 'react' import { View, StyleSheet } from 'react-native' import { responsiveHeight } from 'react-native-responsive-dimensions' import { SheetManager } from 'react-native-actions-sheet' import { useUser } from '../../../providers/UserDataProvider' import { Routes } from '../../../navigation' import { navigate } from '../../../navigation/NavigationService' import { openComments } from '../../../components/bottomsheets/CommentsBottomSheet' import { createPlaybackSharePayload, openShareSheet } from '../../../utils/shareSheet' import { getProjectLikes, LIKE_TARGET, toggleProjectLike } from '../../../utils/likes' import { ensureAuthenticated } from '../../../utils/authRedirect' import PlaybackVideo from './PlaybackVideo' import PlaybackActions from './PlaybackActions' import PlaybackLyricsCard from './PlaybackLyricsCard' import usePlaybackOwner from './usePlaybackOwner' import usePlaybackPlayer from './usePlaybackPlayer' const PlaybackItem = ({ item, isActive, userCache }) => { const { currentUID, followUser, unfollowUser, getUserByUid } = useUser() || {} const { owner, isFollowing, isFollowActionPending, toggleFollow } = usePlaybackOwner({ item, userCache, getUserByUid, currentUID, followUser, unfollowUser, }) const initialLikedBy = getProjectLikes(item, LIKE_TARGET.PLAYBACK) const [isLiked, setIsLiked] = useState(currentUID ? initialLikedBy.includes(currentUID) : false) const [likesCount, setLikesCount] = useState(initialLikedBy.length) useEffect(() => { const lb = getProjectLikes(item, LIKE_TARGET.PLAYBACK) setLikesCount(lb.length) setIsLiked(currentUID ? lb.includes(currentUID) : false) }, [item?.likes?.playback, currentUID]) const commentsCount = useMemo(() => Number(item?.commentsCount || 0), [item?.commentsCount]) const projectTitle = typeof item?.title === 'string' ? item.title.trim() : '' const creatorName = useMemo(() => { if (owner?.displayName) return owner.displayName if (owner?.artistName) return owner.artistName if (owner?.userName) return owner.userName if (typeof item?.userName === 'string') return item.userName return '' }, [item?.userName, owner?.artistName, owner?.displayName, owner?.userName]) const { videoUrl, videoPlayer, currentTimeS } = usePlaybackPlayer({ item, isActive, }) const alignedWords = useMemo(() => { const idx = Number(item?.songIndex) || 0 const ts = item?.musicTimestamps?.[idx] const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [] return arr.map((w) => ({ word: String(w?.word ?? ''), startS: Number(w?.startS ?? 0), endS: Number(w?.endS ?? 0), })) }, [item?.musicTimestamps, item?.songIndex]) const sharePayload = useMemo(() => { if (!item?.id) return null return createPlaybackSharePayload({ projectId: item.id, title: projectTitle || undefined, artist: creatorName || undefined, playbackUrl: videoUrl || undefined, }) }, [creatorName, item?.id, projectTitle, videoUrl]) const handleShare = useCallback(() => { if (sharePayload) { openShareSheet(sharePayload) } }, [sharePayload]) const handleReport = useCallback(() => { if (!item?.id) return SheetManager.show('Report', { payload: { targetType: 'playback', projectId: item?.id || null, playbackId: item?.id || null, title: item?.title || '', ownerId: item?.userId || null, }, }) }, [item?.id, item?.title, item?.userId]) const handleLike = useCallback(async () => { try { if (!item?.id) return if (!ensureAuthenticated(currentUID)) { return } const nextLiked = !isLiked setIsLiked(nextLiked) setLikesCount((c) => Math.max(0, c + (nextLiked ? 1 : -1))) await toggleProjectLike({ projectId: item.id, currentUID, target: LIKE_TARGET.PLAYBACK, next: nextLiked, }) } catch (e) { setIsLiked((v) => !v) setLikesCount((c) => (isLiked ? c + 1 : Math.max(0, c - 1))) } }, [currentUID, isLiked, item?.id]) const handleCommentPress = useCallback(() => { if (item?.id) openComments(item.id) }, [item?.id]) const onOpenProfile = useCallback(() => { navigate(Routes.SingerProfile, { userId: item?.userId }) }, [item?.userId]) return ( ) } const styles = StyleSheet.create({ container: { height: responsiveHeight(100), position: 'relative', backgroundColor: 'black', }, overlay: { position: 'absolute', width: '100%', bottom: 130, gap: 18, }, }) export default PlaybackItem