Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
364 changes: 364 additions & 0 deletions Examples/LargeListExamples/CompleteVideoExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,364 @@
import React from "react";
import { StyleSheet, Text, View, Image, FlatList, TouchableOpacity, Dimensions } from "react-native";
import { LargeList } from "../../src";
import { MediaWrapper } from "../../src";
import Video from "react-native-video";

const { width } = Dimensions.get("window");

export class CompleteVideoExample extends React.Component {
static navigationOptions = {
title: "Complete Video Example",
};

state = {
likedItems: {},
comments: {},
playingVideoId: null,
};

render() {
return (
<LargeList
data={this._getData()}
heightForSection={() => 0}
heightForIndexPath={this._heightForIndexPath}
renderIndexPath={this._renderIndexPath}
contentStyle={styles.listContent}
/>
);
}

_getData = () => {
return [
{
items: [
// Banner at the top
{ type: "banner", id: "banner-1", images: this._getBannerImages() },
// Video items
{
type: "video",
id: "video-1",
url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
title: "Big Buck Bunny",
user: "Nature Channel",
avatar: "https://ui-avatars.com/api/?name=Nature+Channel&background=random"
},
{
type: "video",
id: "video-2",
url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4",
title: "Elephants Dream",
user: "Wildlife World",
avatar: "https://ui-avatars.com/api/?name=Wildlife+World&background=random"
},
{
type: "video",
id: "video-3",
url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4",
title: "For Bigger Blazes",
user: "Fire Safety",
avatar: "https://ui-avatars.com/api/?name=Fire+Safety&background=random"
},
{
type: "video",
id: "video-4",
url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4",
title: "For Bigger Escapes",
user: "Adventure Club",
avatar: "https://ui-avatars.com/api/?name=Adventure+Club&background=random"
},
],
},
];
};

_getBannerImages = () => {
return [
{ id: "banner-img-1", url: "https://images.unsplash.com/photo-1501426026826-31c667bdf23d?w=300", title: "Nature" },
{ id: "banner-img-2", url: "https://images.unsplash.com/photo-1518717758536-85ae29035b6d?w=300", title: "Wildlife" },
{ id: "banner-img-3", url: "https://images.unsplash.com/photo-1500049517218-60249511432c?w=300", title: "Adventure" },
{ id: "banner-img-4", url: "https://images.unsplash.com/photo-1530281700549-e82e7bf110d6?w=300", title: "Mountains" },
];
};

_heightForIndexPath = ({ section, row }) => {
const item = this._getData()[section].items[row];
if (item.type === "banner") {
return 220;
} else if (item.type === "video") {
return 520;
}
return 100;
};

_renderIndexPath = ({ section, row }, mediaWrapperParam) => {
const item = this._getData()[section].items[row];

if (item.type === "banner") {
return this._renderBanner(item);
} else if (item.type === "video") {
return this._renderVideoItem(item, mediaWrapperParam);
}

return null;
};

_renderBanner = (bannerItem) => {
return (
<View style={styles.bannerContainer}>
<Text style={styles.bannerTitle}>Featured</Text>
<FlatList
data={bannerItem.images}
horizontal
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => (
<TouchableOpacity style={styles.bannerItem} onPress={() => console.log("Banner pressed:", item.title)}>
<Image
style={styles.bannerImage}
source={{ uri: item.url }}
resizeMode="cover"
/>
<Text style={styles.bannerImageTitle}>{item.title}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.bannerList}
/>
</View>
);
};

_renderVideoItem = (videoItem, mediaWrapperParam) => {
const isLiked = this.state.likedItems[videoItem.id] || false;
const commentCount = this.state.comments[videoItem.id] || 0;
const isPlaying = this.state.playingVideoId === videoItem.id;

return (
<View style={styles.videoContainer}>
{/* User Info */}
<View style={styles.userInfo}>
<Image
style={styles.avatar}
source={{ uri: videoItem.avatar }}
/>
<Text style={styles.userName}>{videoItem.user}</Text>
<TouchableOpacity style={styles.followButton}>
<Text style={styles.followButtonText}>Follow</Text>
</TouchableOpacity>
</View>

{/* Video */}
<MediaWrapper
style={styles.mediaWrapper}
mediaWrapperParam={mediaWrapperParam}
renderLoading={() => (
<View style={styles.loadingContainer}>
<Image
style={styles.loadingGif}
source={require("./icons/loading.gif")}
/>
</View>
)}
loadEndFunc="onLoad"
>
<Video
source={{ uri: videoItem.url }}
style={styles.video}
controls
resizeMode="contain"
paused={!isPlaying}
onLoad={() => console.log("Video loaded:", videoItem.title)}
onPlay={() => this.setState({ playingVideoId: videoItem.id })}
onPause={() => this.setState({ playingVideoId: null })}
/>
</MediaWrapper>

{/* Video Info */}
<View style={styles.videoInfo}>
<Text style={styles.videoTitle}>{videoItem.title}</Text>
</View>

{/* Interaction Bar */}
<View style={styles.interactionBar}>
<TouchableOpacity
style={styles.interactionButton}
onPress={() => this._toggleLike(videoItem.id)}
>
<Image
style={[styles.interactionIcon, isLiked && styles.likedIcon]}
source={{ uri: isLiked ? "https://img.icons8.com/color/48/000000/like--v1.png" : "https://img.icons8.com/ios-glyphs/48/000000/like--v1.png" }}
/>
<Text style={[styles.interactionText, isLiked && styles.likedText]}>
{isLiked ? "Liked" : "Like"}
</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.interactionButton}
onPress={() => this._addComment(videoItem.id)}
>
<Image
style={styles.interactionIcon}
source={{ uri: "https://img.icons8.com/ios-glyphs/48/000000/comments.png" }}
/>
<Text style={styles.interactionText}>
Comment ({commentCount})
</Text>
</TouchableOpacity>

<TouchableOpacity
style={styles.interactionButton}
onPress={() => console.log("Share")}
>
<Image
style={styles.interactionIcon}
source={{ uri: "https://img.icons8.com/ios-glyphs/48/000000/share--v1.png" }}
/>
<Text style={styles.interactionText}>Share</Text>
</TouchableOpacity>
</View>
</View>
);
};

_toggleLike = (videoId) => {
this.setState((prevState) => ({
likedItems: {
...prevState.likedItems,
[videoId]: !prevState.likedItems[videoId],
},
}));
};

_addComment = (videoId) => {
this.setState((prevState) => ({
comments: {
...prevState.comments,
[videoId]: (prevState.comments[videoId] || 0) + 1,
},
}));
};
}

const styles = StyleSheet.create({
listContent: {
backgroundColor: "#f5f5f5",
},
bannerContainer: {
paddingVertical: 16,
backgroundColor: "white",
},
bannerTitle: {
fontSize: 20,
fontWeight: "bold",
marginLeft: 16,
marginBottom: 12,
},
bannerList: {
paddingHorizontal: 16,
},
bannerItem: {
marginRight: 12,
width: width - 100,
height: 180,
borderRadius: 12,
overflow: "hidden",
},
bannerImage: {
width: "100%",
height: "100%",
},
bannerImageTitle: {
position: "absolute",
bottom: 12,
left: 12,
color: "white",
fontSize: 18,
fontWeight: "bold",
textShadowColor: "rgba(0, 0, 0, 0.5)",
textShadowOffset: { width: 1, height: 1 },
textShadowRadius: 3,
},
videoContainer: {
backgroundColor: "white",
marginBottom: 12,
padding: 12,
},
userInfo: {
flexDirection: "row",
alignItems: "center",
marginBottom: 12,
},
avatar: {
width: 40,
height: 40,
borderRadius: 20,
marginRight: 12,
},
userName: {
fontSize: 16,
fontWeight: "bold",
flex: 1,
},
followButton: {
backgroundColor: "#007AFF",
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 20,
},
followButtonText: {
color: "white",
fontSize: 14,
fontWeight: "bold",
},
mediaWrapper: {
width: "100%",
height: 320,
backgroundColor: "#000",
borderRadius: 12,
overflow: "hidden",
},
video: {
flex: 1,
},
loadingContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
loadingGif: {
width: 64,
height: 64,
},
videoInfo: {
marginVertical: 12,
},
videoTitle: {
fontSize: 16,
lineHeight: 22,
},
interactionBar: {
flexDirection: "row",
},
interactionButton: {
flexDirection: "row",
alignItems: "center",
marginRight: 32,
},
interactionIcon: {
width: 24,
height: 24,
marginRight: 8,
},
likedIcon: {
tintColor: "red",
},
interactionText: {
fontSize: 14,
color: "#333",
},
likedText: {
color: "red",
},
});
Loading