diff --git a/Views/Slideshow.js b/Views/Slideshow.js index cb2861f..a54237e 100644 --- a/Views/Slideshow.js +++ b/Views/Slideshow.js @@ -1,7 +1,7 @@ import React, { useRef } from 'react'; -import { StyleSheet, View, Text, Animated, PanResponder, Dimensions, TouchableOpacity } from 'react-native'; +import { StyleSheet, View, Text, Animated, PanResponder, Dimensions, FlatList, TouchableOpacity } from 'react-native'; import { Image } from 'expo-image'; // Import Image from expo-image -import { Button, Card, Chip } from 'react-native-paper'; +import { Button } from 'react-native-paper'; import * as Sharing from 'expo-sharing'; import * as FileSystem from 'expo-file-system'; @@ -9,6 +9,7 @@ const { width: SCREEN_WIDTH } = Dimensions.get('window'); let Slideshow = (props) => { const images = props.route.params.images; + const imagesTumb = images.map((imageUrl) => imageUrl[1] + '?width=100&height=100`'); const [imageIndex, setImageIndex] = React.useState(props.route.params.startIndex); // Animated value for horizontal translation @@ -47,8 +48,7 @@ let Slideshow = (props) => { if (prevIndex > 0) return prevIndex - 1 return prevIndex - } - ); + }); translateX.setValue(0); }); } else { @@ -68,30 +68,16 @@ let Slideshow = (props) => { const { uri } = await FileSystem.downloadAsync(images[imageIndex][1], fileUri); await Sharing.shareAsync(uri); } catch (error) { - //Alert.alert('Error', 'Failed to share image. Please try again later.'); console.error(error) } }; const repostImage = () => { - // Repost logic goes here (for now, just showing an alert) - //Alert.alert('Repost', 'Repost functionality is not yet implemented.'); props.navigation.navigate('NewPost', { intialContent: '@image:' + images[imageIndex][1] }); }; return ( {imageIndex + 1}/{images.length} - - {/* Left arrow */} - {(imageIndex > 0) && ( - {'|'} - )} - - {/* Right arrow */} - {imageIndex < images.length - 1 && ( - {'|'} - )} - { {/* Share and Repost Buttons */} - - + {/* Thumbnails */} + index.toString()} + renderItem={({ item, index }) => ( + { + setImageIndex(index); + }}> + + + )} + initialNumToRender={6} + style={styles.thumbnailList} + showsHorizontalScrollIndicator={false} + /> ); }; @@ -148,37 +157,31 @@ const styles = StyleSheet.create({ backgroundColor: 'rgba(255, 255, 255, 0.5)', padding: 10, }, - arrow: { - position: 'absolute', - top: '45%', - fontSize: 40, - color: 'rgba(255, 255, 255, 0.7)', - zIndex: 1, - }, - leftArrow: { - left: 10, - }, - rightArrow: { - right: 10, - }, buttonsContainer: { - flexDirection: 'row', + flexDirection: 'column', justifyContent: 'space-around', position: 'absolute', - bottom: 20, + right: -20, + bottom: 90, + paddingHorizontal: 10, + }, + thumbnailList: { + position: 'absolute', + bottom: 15, width: '100%', - paddingHorizontal: 20, + paddingHorizontal: 10, }, - button: { - paddingVertical: 10, - paddingHorizontal: 20, - backgroundColor: 'rgba(255, 255, 255, 0.7)', - borderRadius: 5, + thumbnail: { + width: 60, + height: 60, + marginHorizontal: 5, + borderRadius: 10, + borderWidth: 2, + borderColor: 'white', }, - buttonText: { - color: '#fff', - fontSize: 16, + currentThumbnail: { + borderColor: 'rgba(50,255,50,0.8)', }, }); -export default Slideshow; +export default Slideshow; \ No newline at end of file diff --git a/components/Media.js b/components/Media.js index 4cd7744..f63991e 100644 --- a/components/Media.js +++ b/components/Media.js @@ -1,3 +1,4 @@ +// Import necessary dependencies import React, { useState, useEffect } from 'react'; import { View, TouchableHighlight, StyleSheet, FlatList, TouchableWithoutFeedback, Share } from 'react-native'; import { Button, Text, ProgressBar } from 'react-native-paper'; @@ -13,6 +14,7 @@ import { Image } from 'expo-image'; // Import Image from expo-image import * as FileSystem from 'expo-file-system'; import * as Sharing from 'expo-sharing'; +// Extract Vimeo video ID from content string const videoIdF = (content) => { let vimeoTag = content.match(/@vimeo:[0-9]+/); if (!vimeoTag) return []; @@ -21,6 +23,7 @@ const videoIdF = (content) => { return tag.split(':'); }; +// Extract YouTube video ID from content string const youtubeIdF = (content) => { let youtubeTag = content.match(/@youtube:[0-z]+/); if (!youtubeTag) return ''; @@ -29,6 +32,7 @@ const youtubeIdF = (content) => { return tag.split(':')[1]; }; +// Extract HLS URL from content string const hlsIdF = (content) => { let hslTag = content.match(/@hls:.+\w/); if (!hslTag) return ''; @@ -37,19 +41,21 @@ const hlsIdF = (content) => { return tag; }; -const imagesTagF = (content) => { +// Extract image tags from content string +const imagesTagF = (content, width = 1000, height = 1000) => { 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] + '?width=1000&height=1000'; + if (parts[1].substring(0, 4) != "http") parts[1] = `https://social.emmint.com/${parts[1]}?width=${width}&height=${height}`; Tags.push(parts); }); return Tags; }; +// Extract iframe source from content string const iframeTagF = (content) => { let iframeMatch = content.match(/@iframe:.+\w/g); if (!iframeMatch) return []; @@ -58,25 +64,32 @@ const iframeTagF = (content) => { return parts; }; - +// Media Component let Media = (props) => { const gState = useSnapshot(GlobalState); const viewer = gState.me; - const imagesTag = imagesTagF(props.content); + + // Extracting tags from content + const imagesTag = imagesTagF(props.content, props.imageWidth || 1000, props.imageHeight || 1000); const imagesTagLimited = imagesTag.slice(0, 10); - const imageStyle = imagesTag.length == 1 ? styles.image : styles.multipleImage; + 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(); + + let interactive = props.interactive || true; + + // Fetch video data from API useEffect(() => { let subscribed = true; let getData = async () => { - if (!videosId[1]) return 0; + if (!videosId[1]) return; let videoObj = await API.getVideo(videosId[1]); if (videoObj && videoObj.files && subscribed) { setVideosFiles(videoObj.files); @@ -87,69 +100,95 @@ let Media = (props) => { return () => { subscribed = false; }; - }, [props.content]) - const video = (videosFiles.length && !props.skiptVideo) ? ( - loaded ? : - ( + }, [props.content]); + + // Render video component + const renderVideo = () => { + if (videosFiles.length && !props.skiptVideo) { + return loaded ? ( + + ) : ( setLoaded(true)}> - ) - ) : - (videosId.length ? : <>); - const video2 = (hlsUrl && !props.skiptVideo) ? ( - loaded ? - : - { - //setLoaded(true) - GlobalState.currentMedia = hlsUrl; - GlobalState.mediaPost = props.post; - }}> - {poster ? - : - - } - - ) : <>; - const iframe = iframeSrc.length ? - : <>; - const youtubeEmb = youtubeId.length ? - : <>; - const renderImages = (({ item, index }) => { - return ( - { - //alert("hello"); - navigation.navigate('Slideshow', { images: imagesTag, startIndex: index }); - }} - onLongPress={async () => { - await shareImage(item[1]); + ); + } + if (videosId.length) { + return ; + } + return null; + }; + + // Render HLS video component + const renderHlsVideo = () => { + if (hlsUrl && !props.skiptVideo) { + return loaded ? ( + + ) : ( + { + GlobalState.currentMedia = hlsUrl; + GlobalState.mediaPost = props.post; }}> - - - ); - }); - 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 = - <> - {percent}% {Moment(viewer.data[props.postId].ts).fromNow()} - - ; - } + {poster ? ( + + ) : ( +