Skip to content

Commit

Permalink
fix: feed map media player
Browse files Browse the repository at this point in the history
  • Loading branch information
WaDadidou committed Sep 17, 2024
1 parent 8adc320 commit ebaa1d7
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 60 deletions.
4 changes: 1 addition & 3 deletions packages/components/FilePreview/AudioView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,19 @@ export const AudioView: React.FC<{
imageURI?: string;
duration: number;
waveform: number[];
authorId: string;
postId: string;
fallbackImageURI?: string;
}> = ({
fileUrl,
imageURI,
duration,
waveform,
authorId,
postId,
fallbackImageURI: fallbackImageSource,
}) => {
const { media, handlePlayPause, loadAndPlaySoundsQueue, playbackStatus } =
useMediaPlayer();
const isInMediaPlayer = media?.postId === postId;
const isInMediaPlayer = !!media && postId === media.postId;

const onPressPlayPause = async () => {
if (isInMediaPlayer) {
Expand Down
30 changes: 8 additions & 22 deletions packages/components/mediaPlayer/MediaPlayerBarRefined.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AVPlaybackStatusSuccess } from "expo-av";
import React, { FC } from "react";
import { View } from "react-native";

Expand All @@ -8,21 +9,12 @@ import { SpacerRow } from "../spacer";
import pauseSVG from "@/assets/icons/pause.svg";
import playSVG from "@/assets/icons/play.svg";
import { TimerSliderAlt } from "@/components/mediaPlayer/TimerSliderAlt";
import { useMediaPlayer } from "@/context/MediaPlayerProvider";
import { secondaryColor } from "@/utils/style/colors";
import { Media } from "@/utils/types/mediaPlayer";
export const MediaPlayerBarRefined: FC<{
mediaToPlay: Media;
}> = ({ mediaToPlay }) => {
const { handlePlayPause, media, loadAndPlaySoundsQueue, playbackStatus } =
useMediaPlayer();
const isInMediaPlayer = media?.postId === mediaToPlay.postId;

const onPressPlayPause = async () => {
if (isInMediaPlayer) await handlePlayPause();
else await loadAndPlaySoundsQueue([mediaToPlay]);
};

playbackStatus?: AVPlaybackStatusSuccess;
onPressPlayPause: () => void;
isInMediaPlayer: boolean;
}> = ({ playbackStatus, onPressPlayPause }) => {
return (
<View
style={{
Expand All @@ -34,9 +26,7 @@ export const MediaPlayerBarRefined: FC<{
<CustomPressable onPress={onPressPlayPause}>
<SVG
source={
isInMediaPlayer &&
playbackStatus?.isPlaying &&
!playbackStatus?.didJustFinish
playbackStatus?.isPlaying && !playbackStatus?.didJustFinish
? pauseSVG
: playSVG
}
Expand All @@ -48,12 +38,8 @@ export const MediaPlayerBarRefined: FC<{
<SpacerRow size={0.5} />

<TimerSliderAlt
duration={
(isInMediaPlayer
? playbackStatus?.durationMillis
: mediaToPlay.duration) || 0
}
playbackStatus={isInMediaPlayer ? playbackStatus : undefined}
duration={playbackStatus?.durationMillis || 0}
playbackStatus={playbackStatus}
/>
</View>
);
Expand Down
26 changes: 10 additions & 16 deletions packages/components/mediaPlayer/MediaPlayerVideo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import React, {
FC,
RefObject,
SetStateAction,
useEffect,
useMemo,
useRef,
useState,
Expand Down Expand Up @@ -56,7 +55,6 @@ interface MediaPlayerVideoProps {
resizeMode?: ResizeMode;
style?: StyleProp<ViewStyle>;
hideControls?: boolean;
isThumbnailShown?: boolean;
}

const CONTROLS_HEIGHT = 68;
Expand All @@ -69,11 +67,14 @@ export const MediaPlayerVideo: FC<MediaPlayerVideoProps> = ({
resizeMode,
style,
hideControls,
isThumbnailShown,
}) => {
const { media, onLayoutPlayerVideo } = useMediaPlayer();
const { current: id } = useRef(uuidv4());
const isInMediaPlayer = useMemo(() => media?.id === id, [id, media?.id]);
// TODO: Really need useMemo here ?
const isInMediaPlayer = useMemo(
() => !!media && (postId === media?.postId || media?.id === id),
[media, postId, id],
);

const containerRef = useRef<View>(null);
const videoRef = useRef<Video>(null);
Expand Down Expand Up @@ -107,7 +108,6 @@ export const MediaPlayerVideo: FC<MediaPlayerVideoProps> = ({
id={id}
borderRadius={borderRadius}
setControlsShown={setControlsShown}
isThumbnailShown={isThumbnailShown}
/>
</View>
);
Expand All @@ -126,7 +126,6 @@ type ExpoAvVideoType = {
resizeMode?: ResizeMode;
id: string;
setControlsShown: Dispatch<SetStateAction<boolean>>;
isThumbnailShown?: boolean;
};

function ExpoAvVideo({
Expand All @@ -142,7 +141,6 @@ function ExpoAvVideo({
id,
containerRef,
setControlsShown,
isThumbnailShown,
}: ExpoAvVideoType) {
const {
onVideoStatusUpdate,
Expand All @@ -156,11 +154,7 @@ function ExpoAvVideo({
const [localStatus, setLocalStatus] = useState<AVPlaybackStatusSuccess>();
const [extraPressCount, setExtraPressCount] = useState(0);
const [pressTimer, setPressTimer] = useState<NodeJS.Timeout>();
const [localIsThumbnailShown, setLocalThumbnailShown] = useState(false);

useEffect(() => {
setLocalThumbnailShown(!!isThumbnailShown);
}, [isThumbnailShown]);
const [isThumbnailShown, setThumbnailShown] = useState(false);

// Handle show/hide controls by hovering the video area with mouse
const mousePosition = useMousePosition();
Expand All @@ -185,13 +179,13 @@ function ExpoAvVideo({
id,
fileUrl: videoMetadata.videoFile.url,
duration: videoMetadata.videoFile.videoMetadata?.duration,
// postId is used to difference videos from Social Feed (News feed or Article consultation)
// postId is used to difference videos from Social Feed
postId,
isVideo: true,
};

const onPressPlayPause = async () => {
setLocalThumbnailShown(false);
setThumbnailShown(false);
if (isInMediaPlayer || !videoRef.current) {
await handlePlayPause();
} else {
Expand All @@ -201,7 +195,7 @@ function ExpoAvVideo({

// Handle play/pause and trigger fullscreen on double press
const onPressVideoWrapper = () => {
setLocalThumbnailShown(false);
setThumbnailShown(false);
setExtraPressCount((backCount) => backCount + 1);
if (extraPressCount === 1) {
if (isInMediaPlayer) {
Expand Down Expand Up @@ -257,7 +251,7 @@ function ExpoAvVideo({
height: "100%",
}}
>
{localIsThumbnailShown && (
{isThumbnailShown && (
<OptimizedImage
sourceURI={thumbnailURI}
fallbackURI={defaultThumbnailImage}
Expand Down
16 changes: 15 additions & 1 deletion packages/components/socialFeed/Map/MapPosts/MusicMapPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MediaPlayerBarRefined } from "@/components/mediaPlayer/MediaPlayerBarRe
import { Separator } from "@/components/separators/Separator";
import { MapPostWrapper } from "@/components/socialFeed/Map/MapPosts/MapPostWrapper";
import { SpacerColumn } from "@/components/spacer";
import { useMediaPlayer } from "@/context/MediaPlayerProvider";
import { zodTryParseJSON } from "@/utils/sanitize";
import { errorColor, neutralFF, withAlpha } from "@/utils/style/colors";
import { fontSemibold10 } from "@/utils/style/fonts";
Expand All @@ -22,6 +23,10 @@ export const MusicMapPost: FC<{
post: Post;
}> = ({ post }) => {
const { current: id } = useRef(uuidv4());
const { handlePlayPause, playbackStatus, loadAndPlaySoundsQueue, media } =
useMediaPlayer();
const isInMediaPlayer =
!!media && (post.id === media.postId || media.id === id);
const musicAudioNotePostMetadata = zodTryParseJSON(
ZodSocialFeedTrackMetadata,
post.metadata,
Expand Down Expand Up @@ -53,6 +58,11 @@ export const MusicMapPost: FC<{
}
: undefined;

const onPressPlayPause = async () => {
if (isInMediaPlayer) await handlePlayPause();
else if (mediaToPlay) await loadAndPlaySoundsQueue([mediaToPlay]);
};

return (
<MapPostWrapper post={post} style={{ width: 185 }}>
<View style={{ width: "100%" }}>
Expand All @@ -63,7 +73,11 @@ export const MusicMapPost: FC<{
<SpacerColumn size={0.5} />

{mediaToPlay ? (
<MediaPlayerBarRefined mediaToPlay={mediaToPlay} />
<MediaPlayerBarRefined
playbackStatus={isInMediaPlayer ? playbackStatus : undefined}
onPressPlayPause={onPressPlayPause}
isInMediaPlayer={isInMediaPlayer}
/>
) : (
<BrandText style={[fontSemibold10, { color: errorColor }]}>
No media to play
Expand Down
89 changes: 74 additions & 15 deletions packages/components/socialFeed/Map/MapPosts/VideoMapPost.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { ResizeMode } from "expo-av";
import React, { FC, useRef } from "react";
import {
AVPlaybackStatus,
AVPlaybackStatusSuccess,
ResizeMode,
Video,
} from "expo-av";
import React, { FC, useRef, useState } from "react";
import { View } from "react-native";
import { v4 as uuidv4 } from "uuid";

import { Post } from "@/api/feed/v1/feed";
import { BrandText } from "@/components/BrandText";
import { MediaPlayerBarRefined } from "@/components/mediaPlayer/MediaPlayerBarRefined";
import { MediaPlayerVideo } from "@/components/mediaPlayer/MediaPlayerVideo";
import { Separator } from "@/components/separators/Separator";
import { MapPostWrapper } from "@/components/socialFeed/Map/MapPosts/MapPostWrapper";
import { SpacerColumn } from "@/components/spacer";
import { useFeedbacks } from "@/context/FeedbacksProvider";
import { useMediaPlayer } from "@/context/MediaPlayerProvider";
import { web3ToWeb2URI } from "@/utils/ipfs";
import { zodTryParseJSON } from "@/utils/sanitize";
import { errorColor, neutralFF, withAlpha } from "@/utils/style/colors";
import { fontSemibold10 } from "@/utils/style/fonts";
Expand All @@ -25,8 +31,22 @@ import { Media } from "@/utils/types/mediaPlayer";
export const VideoMapPost: FC<{
post: Post;
}> = ({ post }) => {
const { media } = useMediaPlayer();
const { current: id } = useRef(uuidv4());
const videoRef = useRef<Video>(null);
const {
onVideoStatusUpdate,
onLayoutPlayerVideo,
handlePlayPause,
playbackStatus,
firstPlayVideo,
media,
} = useMediaPlayer();
const { setToast } = useFeedbacks();
const [localStatus, setLocalStatus] = useState<AVPlaybackStatusSuccess>();
const isInMediaPlayer =
!!media && (post.id === media.postId || media.id === id);
const statusToUse = isInMediaPlayer ? playbackStatus : localStatus;

const videoPostMetadata = zodTryParseJSON(
ZodSocialFeedVideoMetadata,
post.metadata,
Expand All @@ -48,13 +68,15 @@ export const VideoMapPost: FC<{
fileUrl: videoPostMetadata.videoFile.url,
duration: videoPostMetadata.videoFile.videoMetadata?.duration, // FIXME: Known issue: Always 0. So, for videos, duration is set by playbackStatus, so it's 0 on the timer since the video is not started once
postId: post.id,
isVideo: true,
}
: videoNotePostMetadata?.files
? {
id,
fileUrl: videoNotePostMetadata.files[0].url,
duration: videoNotePostMetadata.files[0].videoMetadata?.duration,
postId: post.id,
isVideo: true,
}
: undefined;
const videoMetadata: SocialFeedVideoMetadata | undefined = videoPostMetadata
Expand All @@ -69,6 +91,29 @@ export const VideoMapPost: FC<{
}
: undefined;

const onLocalPlaybackStatusUpdate = async (status: AVPlaybackStatus) => {
if ("uri" in status && status.isLoaded) {
setLocalStatus(status);
if (isInMediaPlayer && status.positionMillis > 0) {
onVideoStatusUpdate(status);
}
}
if ("error" in status) {
console.error("Error while playbackStatus update: ", status.error);
setToast({
mode: "normal",
type: "error",
title: `Error while playbackStatus update : ${status.error}`,
});
}
};

const onPressPlayPause = async () => {
if (isInMediaPlayer) await handlePlayPause();
else if (mediaToPlay && videoRef.current)
firstPlayVideo(videoRef.current, mediaToPlay);
};

return (
<MapPostWrapper post={post} style={{ width: 185 }}>
<View>
Expand All @@ -79,23 +124,37 @@ export const VideoMapPost: FC<{
<SpacerColumn size={0.5} />

{mediaToPlay && videoMetadata ? (
<>
<MediaPlayerBarRefined mediaToPlay={mediaToPlay} />
<View
onLayout={() => {
if (isInMediaPlayer && videoRef.current) {
onLayoutPlayerVideo(videoRef.current);
}
}}
>
<MediaPlayerBarRefined
playbackStatus={statusToUse}
onPressPlayPause={onPressPlayPause}
isInMediaPlayer={isInMediaPlayer}
/>
<SpacerColumn size={0.5} />
<MediaPlayerVideo
videoMetadata={videoMetadata}
style={{

<Video
ref={videoRef}
status={statusToUse}
onPlaybackStatusUpdate={onLocalPlaybackStatusUpdate}
source={{
uri: web3ToWeb2URI(videoMetadata.videoFile.url),
}}
style={{ width: "100%", height: 100 }}
posterStyle={{ width: "100%", height: 100 }}
videoStyle={{
width: "100%",
height: 100,
borderRadius: 4,
}}
resizeMode={ResizeMode.CONTAIN}
postId={post.id}
hideControls
isThumbnailShown={
!media && !!videoMetadata.videoFile.thumbnailFileData?.url
}
/>
</>
</View>
) : (
<BrandText style={[fontSemibold10, { color: errorColor }]}>
No media to play
Expand Down
1 change: 0 additions & 1 deletion packages/components/socialFeed/RichText/RichText.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@ export const RichText: React.FC<RichTextProps> = ({
<View key={index}>
<SpacerColumn size={2} />
<AudioView
authorId={authorId}
postId={postId}
duration={file.audioMetadata?.duration || 0}
fileUrl={file.url}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const MusicPostTrackContent: FC<{
waveform={track.audioFile.audioMetadata?.waveform || []}
fallbackImageURI={defaultThumbnailImage}
imageURI={track.audioFile.thumbnailFileData?.url}
authorId={post.authorId}
postId={post.id}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ export const SocialMessageContent: React.FC<Props> = ({ post, isPreview }) => {
<Fragment key={index}>
{postMetadata.message && <SpacerColumn size={2} />}
<AudioView
authorId={post.authorId}
postId={post.id}
duration={file.audioMetadata?.duration || 0}
fileUrl={file.url}
Expand Down

0 comments on commit ebaa1d7

Please sign in to comment.