Files
EMI-ExpoAPP/components/Media.js
Adolfo Reyna 0b57db225d Add slideshow
2023-05-06 22:58:16 -04:00

219 lines
7.6 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { View, TouchableHighlight, Image, StyleSheet, FlatList, TouchableWithoutFeedback, Share } from 'react-native';
import { Button, Text, ProgressBar } from 'react-native-paper';
import API from './../API.js';
import VideoPlayer from './VideoPlayer.js';
import VimeoPlayer from './VimeoPlayer.js';
import { WebView } from 'react-native-webview';
import { useSnapshot } from 'valtio';
import GlobalState from '../contexts/GlobalState.js';
import Moment from 'moment';
import { useNavigation } from '@react-navigation/native';
const videoIdF = (content) => {
let vimeoTag = content.match(/@vimeo:[0-9]+/);
if (!vimeoTag) return [];
let tag = vimeoTag;
tag = tag[0].substring(1);
return tag.split(':');
};
const youtubeIdF = (content) => {
let youtubeTag = content.match(/@youtube:[0-z]+/);
if (!youtubeTag) return '';
let tag = youtubeTag;
tag = tag[0].substring(1);
return tag.split(':')[1];
};
const hlsIdF = (content) => {
let hslTag = content.match(/@hls:.+\w/);
if (!hslTag) return '';
let tag = hslTag;
tag = tag[0].substring(5);
return tag;
};
const imagesTagF = (content) => {
let images = content.match(/@image:[0-z|/|.|]+/g);
if (!images) return [];
let Tags = [];
images.forEach(i => {
let tag = i.substring(1);
let parts = [tag.substring(1, tag.indexOf(":")), tag.substring(tag.indexOf(":") + 1)];
if (parts[1].substring(0, 4) != "http") parts[1] = "https://social.emmint.com/" + parts[1];
Tags.push(parts);
});
return Tags;
};
const iframeTagF = (content) => {
let iframeMatch = content.match(/@iframe:.+\w/g);
if (!iframeMatch) return [];
let tag = iframeMatch[0].substring(1);
let parts = [tag.substring(1, tag.indexOf(":")), tag.substring(tag.indexOf(":") + 1)];
return parts;
};
let Media = (props) => {
const gState = useSnapshot(GlobalState);
const viewer = gState.me;
const imagesTag = imagesTagF(props.content);
const imageStyle = imagesTag.length == 1 ? styles.image : styles.multipleImage;
const videosId = videoIdF(props.content);
const hlsUrl = hlsIdF(props.content);
const iframeSrc = iframeTagF(props.content) || [];
const youtubeId = youtubeIdF(props.content);
const [videosFiles, setVideosFiles] = useState([]);
const [poster, setPoster] = useState('');
const [loaded, setLoaded] = useState(false);
const navigation = useNavigation();
useEffect(() => {
let subscribed = true;
let getData = async () => {
if (!videosId[1]) return 0;
let videoObj = await API.getVideo(videosId[1]);
if (videoObj && videoObj.files && subscribed) {
setVideosFiles(videoObj.files);
setPoster(videoObj.pictures.sizes[4].link);
}
};
getData();
return () => {
subscribed = false;
};
}, [props.content])
const video = (videosFiles.length && !props.skiptVideo) ? (
loaded ? <VideoPlayer videosFiles={videosFiles} poster={poster} videoId={videosId[1]} /> :
(
<TouchableHighlight onPress={() => setLoaded(true)}>
<Image source={poster ? { uri: poster } : {}} key={poster} style={styles.poster} />
</TouchableHighlight>
)
) :
(videosId.length ? <VimeoPlayer videoId={videosId[1]} /> : <></>);
const video2 = (hlsUrl && !props.skiptVideo) ? (
loaded ?
<VideoPlayer videoUrl={hlsUrl} postId={props.postId} /> :
<TouchableHighlight onPress={() => {
//setLoaded(true)
GlobalState.currentMedia = hlsUrl;
GlobalState.mediaPost = props.post;
}}>
{poster ?
<Image source={poster ? { uri: poster } : {}} key={poster} style={styles.poster} /> :
<Button
icon={"subscriptions"}
labelStyle={{ fontSize: 58 }}
style={{ flow: 1 }}
></Button>
}
</TouchableHighlight>
): <></>;
const iframe = iframeSrc.length ?
<WebView
style={styles.iframe}
source={{ uri: iframeSrc[1] }}
/> : <></>;
const youtubeEmb = youtubeId.length ?
<WebView
style={styles.iframe}
source={{ uri: "https://www.youtube.com/embed/" + youtubeId + "?fs=0" }}
/> : <></>;
const renderImages = (({ item, index }) => {
return (
<TouchableWithoutFeedback style={styles.flatlistImages}
onPress={()=>{
//alert("hello");
navigation.navigate('Slideshow', { images: imagesTag, startIndex: index});
}}
onLongPress={()=>{
Share.share({
//message: image[1],
url: item[1],
});
}}>
<Image source={{ uri: item[1] }} style={styles.flatlistImages}/>
</TouchableWithoutFeedback>
);
});
let progress = <></>;
if(viewer.data && viewer.data[props.postId]) {
const percent = Math.round(viewer.data[props.postId].time / viewer.data[props.postId].duration * 100);
if(percent)
progress =
<>
<Text>{percent}% {Moment(viewer.data[props.postId].ts).fromNow()}</Text>
<ProgressBar progress={viewer.data[props.postId].time / viewer.data[props.postId].duration} />
</>;
}
return (
<View>
{
(imagesTag.length > 2) ?
<FlatList
horizontal={true}
data={imagesTag}
renderItem={renderImages}
keyExtractor={item => item[1]}
initialNumToRender={2}
/> :
<View style={{ flexDirection: "row" }}>
{
imagesTag.map((image, i) => {
return (
//<Text key={i}>{post.content}</Text>
<TouchableWithoutFeedback
onPress={()=>{
navigation.navigate('Slideshow', { images: imagesTag, startIndex: i });
}}
onLongPress={()=>{
Share.share({
//message: image[1],
url: image[1],
});
}}>
<Image source={{ uri: image[1] }} key={image[1]} style={imageStyle} />
</TouchableWithoutFeedback>
)
})
}
</View>
}
{video}
{video2}
{iframe}
{youtubeEmb}
{progress}
</View>
);
}
export default Media;
const styles = StyleSheet.create({
image: {
width: "100%",
aspectRatio: 1,
},
poster: {
width: "100%",
aspectRatio: 9 / 6,
},
multipleImage: {
width: "49%",
aspectRatio: 1,
margin: 2,
},
flatlistImages: {
width: 300,
aspectRatio: 1,
margin: 2,
},
iframe: {
width: "100%",
minHeight: 300,
}
});