Skip to content

Commit

Permalink
Update TV examples for SDK 52 release (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
douglowder authored Nov 12, 2024
1 parent 42420a8 commit 83af945
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 127 deletions.
25 changes: 13 additions & 12 deletions with-router-tv/app.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"expo": {
"scheme": "routertv",
"plugins": [
[
"@react-native-tvos/config-tv",
Expand All @@ -16,19 +17,19 @@
}
}
],
[
"expo-build-properties",
{
"ios": {
"newArchEnabled": false
},
"android": {
"newArchEnabled": false
}
}
],
"expo-router"
"expo-router",
"expo-font"
],
"android": {
"splash": {
"image": "./assets/images/splash.png"
}
},
"ios": {
"splash": {
"image": "./assets/images/splash.png"
}
},
"experiments": {
"typedRoutes": true
}
Expand Down
13 changes: 8 additions & 5 deletions with-router-tv/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import { TabBarIcon } from '@/components/navigation/TabBarIcon';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useTextStyles } from '@/hooks/useTextStyles';
import { useScale } from '@/hooks/useScale';

export default function TabLayout() {
const colorScheme = useColorScheme();
const textStyles = useTextStyles();
const scale = useScale();

const tabBarButton = (props: BottomTabBarButtonProps) => {
const style: any = props.style ?? {};
Expand All @@ -32,7 +34,11 @@ export default function TabLayout() {
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
tabBarStyle: {
height: textStyles.title.lineHeight * 2,
marginBottom: 0,
},
tabBarPosition: 'top',
tabBarIconStyle: {
height: textStyles.title.lineHeight,
width: 30 * scale,
},
headerShown: false,
}}
Expand Down Expand Up @@ -72,10 +78,7 @@ export default function TabLayout() {
tabBarButton,
tabBarLabelStyle: textStyles.default,
tabBarIcon: ({ color, focused }) => (
<TabBarIcon
name={focused ? 'code-slash' : 'code-slash-outline'}
color={color}
/>
<TabBarIcon name={focused ? 'tv' : 'tv-outline'} color={color} />
),
}}
/>
Expand Down
22 changes: 15 additions & 7 deletions with-router-tv/app/(tabs)/tv_focus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,25 @@ export default function FocusDemoScreen() {
</ThemedText>
<Collapsible title="How it works">
<ThemedText>
On TV platforms, these components have "onFocus()" and "onBlur()"
On TV platforms, these components have "onFocus()" and "onBlur()"
props, in addition to the usual "onPress()". These can be used to
modify the style of the component when it is navigated to or navigated
away from by the TV focus engine. In addition, the functional forms of
the Pressable style prop and the Pressable content, which in React
Native core take a "pressed" boolean parameter, can also take
"focused" as a parameter on TV platforms.
away from by the TV focus engine.
</ThemedText>
<ThemedText>
As you use the arrow keys to navigate around the screen, the demo uses
the above props to update lists of recent events.
• In addition, the functional forms of the Pressable style prop and
the Pressable content, which in React Native core take a "pressed"
boolean parameter, can also take "focused" as a parameter on TV
platforms.
</ThemedText>
<ThemedText>
• As you use the arrow keys to navigate around the screen, the demo
uses the above props to update lists of recent events.
</ThemedText>
<ThemedText>
In RNTV 0.76, `Pressable` and `Touchable` components receive "focus",
"blur", "pressIn", and "pressOut" events directly from native code,
for improved performance when navigating around the screen.
</ThemedText>
</Collapsible>
{Platform.isTV ? (
Expand Down
120 changes: 47 additions & 73 deletions with-router-tv/components/EventHandlingDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
TouchableHighlight,
TouchableNativeFeedback,
TouchableOpacity,
GestureResponderEvent,
} from 'react-native';
import { useState } from 'react';

Expand All @@ -22,9 +21,9 @@ export function EventHandlingDemo() {
const [pressableEventLog, setPressableEventLog] = useState<string[]>([]);

const logWithAppendedEntry = (log: string[], entry: string) => {
const limit = 3;
const newEventLog = log.slice(0, limit - 1);
newEventLog.unshift(entry);
const limit = 10;
const newEventLog = log.slice(log.length === limit ? 1 : 0, limit);
newEventLog.push(entry);
return newEventLog;
};

Expand All @@ -50,36 +49,37 @@ export function EventHandlingDemo() {

return (
<ThemedView style={styles.container}>
<PressableButton title="Pressable" log={updatePressableLog} />
<TouchableOpacityButton
title="TouchableOpacity"
log={updatePressableLog}
/>
<TouchableHighlightButton
title="TouchableHighlight"
log={updatePressableLog}
/>
{Platform.OS === 'android' ? (
<TouchableNativeFeedbackButton
title="TouchableNativeFeedback"
log={updatePressableLog}
/>
) : null}

<ThemedView style={styles.logContainer}>
<View>
<ThemedText type="defaultSemiBold">Focus/press events</ThemedText>
<ThemedText type="defaultSemiBold">TV remote events</ThemedText>
<ThemedText style={styles.logText}>
{remoteEventLog.join('\n')}
</ThemedText>
</View>
<View>
<ThemedText type="defaultSemiBold">Remote control events</ThemedText>
<ThemedText type="defaultSemiBold">Native events</ThemedText>
<ThemedText style={styles.logText}>
{pressableEventLog.join('\n')}
</ThemedText>
</View>
</ThemedView>
<ThemedView>
<PressableButton title="Pressable" log={updatePressableLog} />
<TouchableOpacityButton
title="TouchableOpacity"
log={updatePressableLog}
/>
<TouchableHighlightButton
title="TouchableHighlight"
log={updatePressableLog}
/>
{Platform.OS === 'android' ? (
<TouchableNativeFeedbackButton
title="TouchableNativeFeedback"
log={updatePressableLog}
/>
) : null}
</ThemedView>
</ThemedView>
);
}
Expand All @@ -92,18 +92,12 @@ const PressableButton = (props: {

return (
<Pressable
onFocus={() => props.log(`${props.title} focus`)}
onBlur={() => props.log(`${props.title} blur`)}
onPress={() => props.log(`${props.title} pressed`)}
onLongPress={(
event: GestureResponderEvent & { eventKeyAction?: number },
) =>
props.log(
`${props.title} long press ${
event.eventKeyAction === 0 ? 'start' : 'end'
}`,
)
}
onFocus={() => props.log(`${props.title} onFocus`)}
onBlur={() => props.log(`${props.title} onBlur`)}
onPress={() => props.log(`${props.title} onPress`)}
onPressIn={() => props.log(`${props.title} onPressIn`)}
onPressOut={() => props.log(`${props.title} onPressOut`)}
onLongPress={() => props.log(`${props.title} onLongPress`)}
style={({ pressed, focused }) =>
pressed || focused ? styles.pressableFocused : styles.pressable
}
Expand All @@ -129,18 +123,11 @@ const TouchableOpacityButton = (props: {
<TouchableOpacity
activeOpacity={0.6}
style={styles.pressable}
onFocus={() => props.log(`${props.title} focus`)}
onBlur={() => props.log(`${props.title} blur`)}
onPress={() => props.log(`${props.title} pressed`)}
onLongPress={(
event: GestureResponderEvent & { eventKeyAction?: number },
) =>
props.log(
`${props.title} long press ${
event.eventKeyAction === 0 ? 'start' : 'end'
}`,
)
}
onFocus={() => props.log(`${props.title} onFocus`)}
onBlur={() => props.log(`${props.title} onBlur`)}
onPressIn={() => props.log(`${props.title} onPressIn`)}
onPressOut={() => props.log(`${props.title} onPressOut`)}
onLongPress={() => props.log(`${props.title} onLongPress`)}
>
<Text style={styles.pressableText}>{props.title}</Text>
</TouchableOpacity>
Expand All @@ -158,18 +145,11 @@ const TouchableHighlightButton = (props: {
<TouchableHighlight
style={styles.pressable}
underlayColor={underlayColor}
onFocus={() => props.log(`${props.title} focus`)}
onBlur={() => props.log(`${props.title} blur`)}
onPress={() => props.log(`${props.title} pressed`)}
onLongPress={(
event: GestureResponderEvent & { eventKeyAction?: number },
) =>
props.log(
`${props.title} long press ${
event.eventKeyAction === 0 ? 'start' : 'end'
}`,
)
}
onFocus={(event) => props.log(`${props.title} onFocus`)}
onBlur={(event) => props.log(`${props.title} onBlur`)}
onPressIn={() => props.log(`${props.title} onPressIn`)}
onPressOut={() => props.log(`${props.title} onPressOut`)}
onLongPress={() => props.log(`${props.title} onLongPress`)}
>
<Text style={styles.pressableText}>{props.title}</Text>
</TouchableHighlight>
Expand All @@ -185,18 +165,10 @@ const TouchableNativeFeedbackButton = (props: {
return (
<TouchableNativeFeedback
background={TouchableNativeFeedback.SelectableBackground()}
onFocus={() => props.log(`${props.title} focus`)}
onBlur={() => props.log(`${props.title} blur`)}
onPress={() => props.log(`${props.title} pressed`)}
onLongPress={(
event: GestureResponderEvent & { eventKeyAction?: number },
) =>
props.log(
`${props.title} long press ${
event.eventKeyAction === 0 ? 'start' : 'end'
}`,
)
}
onPress={() => props.log(`${props.title} onPress`)}
onPressIn={() => props.log(`${props.title} onPressIn`)}
onPressOut={() => props.log(`${props.title} onPressOut`)}
onLongPress={() => props.log(`${props.title} onLongPress`)}
>
<View style={styles.pressable}>
<Text style={styles.pressableText}>{props.title}</Text>
Expand All @@ -214,7 +186,8 @@ const useDemoStyles = function () {
return StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'center',
},
logContainer: {
Expand All @@ -225,10 +198,11 @@ const useDemoStyles = function () {
justifyContent: 'flex-start',
},
logText: {
height: 100 * scale,
width: 200 * scale,
maxHeight: 300 * scale,
width: 300 * scale,
fontSize: 10 * scale,
margin: 5 * scale,
lineHeight: 12 * scale,
alignSelf: 'flex-start',
justifyContent: 'flex-start',
},
Expand Down
41 changes: 20 additions & 21 deletions with-router-tv/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,33 @@
},
"dependencies": {
"@expo/vector-icons": "^14.0.2",
"@react-navigation/native": "^6.0.2",
"expo": "~51.0.31",
"expo-build-properties": "~0.12.3",
"expo-constants": "~16.0.2",
"expo-font": "~12.0.9",
"expo-linking": "~6.3.1",
"expo-router": "~3.5.23",
"expo-splash-screen": "~0.27.5",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"expo-web-browser": "~13.0.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "npm:react-native-tvos@~0.74.5-0",
"react-native-gesture-handler": "~2.16.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"expo": "~52.0.2",
"expo-build-properties": "~0.13.1",
"expo-constants": "~17.0.2",
"expo-font": "~13.0.1",
"expo-linking": "~7.0.2",
"expo-router": "~4.0.2",
"expo-splash-screen": "~0.29.6",
"expo-status-bar": "~2.0.0",
"expo-system-ui": "~4.0.2",
"expo-web-browser": "~14.0.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "npm:react-native-tvos@0.76.1-1",
"react-native-gesture-handler": "~2.20.2",
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.0.0",
"react-native-web": "~0.19.10"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@react-native-tvos/config-tv": "^0.0.10",
"@react-native-tvos/config-tv": "^0.1.0",
"@types/jest": "^29.5.12",
"@types/react": "~18.2.45",
"@types/react": "~18.3.12",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~51.0.1",
"jest-expo": "~52.0.0-preview.4",
"react-test-renderer": "18.2.0",
"typescript": "~5.3.3"
},
Expand Down
12 changes: 11 additions & 1 deletion with-tv/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@
}
}
]
]
],
"android": {
"splash": {
"image": "./assets/images/icon-1920x720.png"
}
},
"ios": {
"splash": {
"image": "./assets/images/icon-1920x720.png"
}
}
}
}
Loading

0 comments on commit 83af945

Please sign in to comment.