-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add short videos module and nostr video component * feat: add ShortVideo module to router * add short videos actions * add inner video styles * replace mock videos data with hook
- Loading branch information
1 parent
2c9d2a2
commit 0b31fc3
Showing
8 changed files
with
422 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import {NostrEvent} from '@nostr-dev-kit/ndk'; | ||
import {ResizeMode, Video} from 'expo-av'; | ||
import React, {useEffect, useState} from 'react'; | ||
import {Pressable, TouchableOpacity, View} from 'react-native'; | ||
|
||
import {BookmarkIcon, LikeIcon, RepostIcon} from '../../assets/icons'; | ||
import {useStyles} from '../../hooks'; | ||
import stylesheet from './styles'; | ||
|
||
const NostrVideo = ({item, shouldPlay}: {shouldPlay: boolean; item: NostrEvent}) => { | ||
const video = React.useRef<Video | null>(null); | ||
const [status, setStatus] = useState<any>(null); | ||
const styles = useStyles(stylesheet); | ||
|
||
useEffect(() => { | ||
if (!video.current) return; | ||
|
||
if (shouldPlay) { | ||
video.current.playAsync(); | ||
} else { | ||
video.current.pauseAsync(); | ||
video.current.setPositionAsync(0); | ||
} | ||
}, [shouldPlay]); | ||
|
||
const extractVideoURL = (event: NostrEvent) => { | ||
return event?.tags?.find((tag) => tag?.[0] === 'url')?.[1] || ''; | ||
}; | ||
|
||
const handleLike = () => { | ||
console.log('like'); | ||
//todo: integrate hook | ||
}; | ||
|
||
const handleRepost = () => { | ||
console.log('like'); | ||
//todo: integrate hook | ||
}; | ||
|
||
const handleBookmark = () => { | ||
console.log('like'); | ||
//todo: integrate hook | ||
}; | ||
|
||
return ( | ||
<> | ||
<Pressable | ||
onPress={() => | ||
status.isPlaying ? video.current?.pauseAsync() : video.current?.playAsync() | ||
} | ||
> | ||
<View style={styles.videoContainer}> | ||
<Video | ||
ref={video} | ||
source={{uri: extractVideoURL(item)}} | ||
style={styles.video} | ||
isLooping | ||
resizeMode={ResizeMode.COVER} | ||
useNativeControls={false} | ||
onPlaybackStatusUpdate={(status) => setStatus(() => status)} | ||
videoStyle={styles.innerVideo} | ||
/> | ||
</View> | ||
</Pressable> | ||
<View style={styles.actionsContainer}> | ||
<TouchableOpacity onPress={handleLike}> | ||
<LikeIcon width={20} height={20} color="white" /> | ||
</TouchableOpacity> | ||
<TouchableOpacity onPress={handleRepost}> | ||
<RepostIcon width={20} height={20} color="white" /> | ||
</TouchableOpacity> | ||
<TouchableOpacity style={{width: 15}} onPress={handleBookmark}> | ||
<BookmarkIcon width={15} height={20} color="white" /> | ||
</TouchableOpacity> | ||
</View> | ||
</> | ||
); | ||
}; | ||
|
||
export default NostrVideo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import {Dimensions} from 'react-native'; | ||
|
||
import {ThemedStyleSheet} from '../../styles'; | ||
|
||
export default ThemedStyleSheet(() => ({ | ||
videoContainer: { | ||
width: Dimensions.get('window').width, | ||
height: Dimensions.get('window').height - 60, | ||
}, | ||
video: { | ||
width: '100%', | ||
height: '100%', | ||
}, | ||
innerVideo: { | ||
height: Dimensions.get('window').height - 60, | ||
}, | ||
actionsContainer: { | ||
position: 'absolute', | ||
right: 20, | ||
bottom: 40, | ||
display: 'flex', | ||
flexDirection: 'column', | ||
gap: 20, | ||
alignItems: 'center', | ||
}, | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import {NostrEvent} from '@nostr-dev-kit/ndk'; | ||
import {useGetVideos} from 'afk_nostr_sdk'; | ||
import React, {useRef, useState} from 'react'; | ||
import {FlatList, Text, View} from 'react-native'; | ||
|
||
import {InfoIcon} from '../../assets/icons'; | ||
import NostrVideo from '../../components/NostrVideo'; | ||
import {useStyles, useTheme} from '../../hooks'; | ||
import {mockEvents} from '../../utils/dummyData'; | ||
import stylesheet from './styles'; | ||
|
||
const ShortVideosModule = () => { | ||
const styles = useStyles(stylesheet); | ||
const {theme} = useTheme(); | ||
const [currentViewableItemIndex, setCurrentViewableItemIndex] = useState(0); | ||
const viewabilityConfig = {viewAreaCoveragePercentThreshold: 50}; | ||
const videos = useGetVideos(); | ||
const [videosEvents, setVideosEvents] = useState<NostrEvent[]>( | ||
videos?.data?.pages?.flat() as NostrEvent[], | ||
); | ||
|
||
const fetchNostrEvents = async () => { | ||
// This mock should be replaced with actual implementation (hook integration to get videos) | ||
setVideosEvents(mockEvents); | ||
}; | ||
|
||
const onViewableItemsChanged = ({viewableItems}: any) => { | ||
if (viewableItems.length > 0) { | ||
setCurrentViewableItemIndex(viewableItems[0].index ?? 0); | ||
} | ||
}; | ||
|
||
const viewabilityConfigCallbackPairs = useRef([{viewabilityConfig, onViewableItemsChanged}]); | ||
|
||
return ( | ||
<View style={styles.container}> | ||
{videosEvents.length > 0 ? ( | ||
<FlatList | ||
style={styles.list} | ||
data={videosEvents} | ||
renderItem={({item, index}) => ( | ||
<NostrVideo item={item} shouldPlay={index === currentViewableItemIndex} /> | ||
)} | ||
keyExtractor={(item, index) => item.content + index} | ||
pagingEnabled | ||
horizontal={false} | ||
showsVerticalScrollIndicator={false} | ||
viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current} | ||
/> | ||
) : ( | ||
<View style={styles.noDataContainer}> | ||
<InfoIcon width={30} height={30} color={theme.colors.primary} /> | ||
<Text style={styles.noDataText}>No videos uploaded yet.</Text> | ||
</View> | ||
)} | ||
</View> | ||
); | ||
}; | ||
|
||
export default ShortVideosModule; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {ThemedStyleSheet} from '../../styles'; | ||
|
||
export default ThemedStyleSheet((theme) => ({ | ||
container: { | ||
flex: 1, | ||
height: '100%', | ||
}, | ||
list: { | ||
height: '100%', | ||
}, | ||
noDataContainer: { | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
gap: 20, | ||
marginTop: 20, | ||
}, | ||
noDataText: { | ||
color: theme.colors.text, | ||
textAlign: 'center', | ||
fontSize: 14, | ||
fontWeight: 'bold', | ||
}, | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.