Part 1: Final Code
Open Beta Documentation Amazon offers this technical
documentation as part of a pre-release, open beta. The features described might change as Amazon receives feedback
and iterates on the features. For the most current feature information, see the Release
Notes.
Here is the final code for part one.
Folder Structure
src/
├── components/
│ ├── Header.tsx
│ └── VideoCard.tsx
├── screens
│ ├── LandingScreen.tsx
└── App.tsx
Components
Header.tsx
import * as React from 'react';
import {StyleSheet, Text, View} from 'react-native';
const Header = () => {
return (
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Welcome to Vega!</Text>
</View>
);
};
const styles = StyleSheet.create({
headerContainer: {
padding: 10,
alignItems: 'center',
backgroundColor: '#232F3E',
width: '100%',
},
headerText: {
fontSize: 50,
fontWeight: '700',
color: '#FF9900',
},
});
export default Header;
VideoCard.tsx
import React, {useState} from 'react';
import {StyleSheet, Text, TouchableOpacity, Image, View} from 'react-native';
interface IProps {
title: string;
imgURL: string;
description: string;
pressFunction: Function;
}
const VideoCard = ({title, imgURL, description, pressFunction}: IProps) => {
const [focused, setFocused] = useState(false);
return (
<TouchableOpacity
style={[
styles.videoCardContainer,
focused ? styles.focused : styles.unfocused,
]}
onPress={() => pressFunction()}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}>
<Image style={styles.videoImage} source={{uri: imgURL}} />
<View style={styles.videoTextContainer}>
<Text style={styles.videoTitle}>{title}</Text>
<Text style={styles.videoDescription}>{description}</Text>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
videoCardContainer: {
height: 400,
width: 550,
margin: 10,
borderRadius: 5,
},
unfocused: {
borderWidth: 1,
borderColor: 'white',
},
focused: {
borderWidth: 5,
borderColor: 'yellow',
},
videoTextContainer: {
height: '25%',
display: 'flex',
justifyContent: 'space-around',
padding: 10,
},
videoImage: {
height: '75%',
},
videoTitle: {
fontSize: 20,
fontWeight: 'bold',
color: 'white',
},
videoDescription: {
color: 'white',
},
});
export default VideoCard;
Screens
LandingScreen.tsx
import React, {useState, useEffect} from 'react';
import {FlatList, StyleSheet, View, Text} from 'react-native';
import Header from '../components/Header';
import VideoCard from '../components/VideoCard';
import {TVFocusGuideView} from '@amazon-devices/react-native-kepler';
interface IVideo {
id: string;
title: string;
description: string;
duration: number;
thumbURL: string;
imgURL: string;
videoURL: string;
categories: Array<string>;
channel_id: number;
}
const LandingScreen = () => {
const [islandVideos, setIslandVideos] = useState<IVideo[]>([]);
const [underwaterVideos, setUnderwaterVideos] = useState<IVideo[]>([]);
const url = 'https://d2ob7xfxpe6plv.cloudfront.net/TestData.json';
const getAllVideos = () => {
fetch(url)
.then((response) => response.json())
.then((data) => {
// Filter videos for each category
const islands = data.testData.filter(
(video: IVideo) =>
video.categories && video.categories.includes('Costa Rica Islands'),
);
const underwater = data.testData.filter(
(video: IVideo) =>
video.categories &&
video.categories.includes('Costa Rica Underwater'),
);
setIslandVideos(islands);
setUnderwaterVideos(underwater);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
getAllVideos();
}, []);
return (
<>
<Header />
<TVFocusGuideView autoFocus={true}>
<Text style={styles.categoryTitle}>Costa Rica Islands</Text>
<FlatList
style={styles.flatList}
horizontal
data={islandVideos}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<VideoCard
title={item.title}
description={
item.description.split(' ').slice(0, 20).join(' ') + '...'
}
imgURL={item.imgURL}
pressFunction={() => {}}
/>
</View>
)}
/>
</TVFocusGuideView>
<TVFocusGuideView autoFocus={true}>
<Text style={styles.categoryTitle}>Costa Rica Underwater</Text>
<FlatList
style={styles.flatList}
horizontal
data={underwaterVideos}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<VideoCard
title={item.title}
description={
item.description.split(' ').slice(0, 20).join(' ') + '...'
}
imgURL={item.imgURL}
pressFunction={() => {}}
/>
</View>
)}
/>
</TVFocusGuideView>
</>
);
};
const styles = StyleSheet.create({
flatList: {
padding: 10,
},
itemContainer: {
margin: 10,
},
categoryTitle: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
marginLeft: 30,
},
});
export default LandingScreen;
App.tsx
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import LandingScreen from './screens/LandingScreen';
export const App = () => {
return (
<View style={styles.container}>
<LandingScreen />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#232F3E',
},
});