diff --git a/packages/create/src/components/FlashList/index.tsx b/packages/create/src/components/FlashList/index.tsx index 65339be31..71a1bf1e6 100644 --- a/packages/create/src/components/FlashList/index.tsx +++ b/packages/create/src/components/FlashList/index.tsx @@ -1,5 +1,5 @@ import React, { ForwardedRef, useEffect, useRef, useState } from 'react'; -import { View as RNView } from 'react-native'; +import { View as RNView, Platform } from 'react-native'; import { FlashList as FlashListComp, ListRenderItemInfo, CellContainer } from '@flexn/shopify-flash-list'; import BaseScrollComponent from '@flexn/recyclerlistview/dist/reactnative/core/scrollcomponent/BaseScrollComponent'; import Grid from '../../focusManager/model/grid'; @@ -167,7 +167,7 @@ const FlashList = (props: FlashListProps) => { model.remeasureSelfAndChildrenLayouts(children); } }} - CellRendererComponent={ItemContainer} + CellRendererComponent={Platform.OS === 'web' ? undefined : ItemContainer} overrideProps={{ ...scrollViewProps, ref: (ref: BaseScrollComponent) => { diff --git a/packages/create/src/focusManager/model/screen.ts b/packages/create/src/focusManager/model/screen.ts index 139d9bf0d..eab3251f6 100644 --- a/packages/create/src/focusManager/model/screen.ts +++ b/packages/create/src/focusManager/model/screen.ts @@ -178,6 +178,8 @@ class Screen extends FocusModel { } public onViewRemoved(model: View): void { + // If layout was not yet measured and view removed, we must also remove it from pending layout map + this.removeComponentFromPendingLayoutMap(model.getId()); this._unmountingComponents++; setTimeout(() => { @@ -191,12 +193,13 @@ class Screen extends FocusModel { if (model.getId() === this._precalculatedFocus?.getId()) { this._precalculatedFocus = null; } - if (this._unmountingComponents <= 0 && !this._currentFocus && this.isInBackground()) { + if (this._unmountingComponents <= 0 && !this._currentFocus) { const view = this.getFirstFocusableOnScreen(); if (view) { this.setFocus(view); - } else { + } else if (CoreManager.getScreens()[this.getId()]) { + // If there is no elements wait while first appears // If there is no elements wait while first appears this._interval = setInterval(() => { const view = this.getFirstFocusableOnScreen(); diff --git a/packages/template-starter/package.json b/packages/template-starter/package.json index 57eac6717..32594bab4 100644 --- a/packages/template-starter/package.json +++ b/packages/template-starter/package.json @@ -60,7 +60,8 @@ "watch": "tsc --watch --preserveWatchOutput --noEmit" }, "dependencies": { - "@lightningjs/sdk": "5.2.0" + "@lightningjs/sdk": "5.2.0", + "raf": "3.4.1" }, "devDependencies": { "@flexn/assets-create-outline": "0.3.3", diff --git a/packages/template-starter/renative.json b/packages/template-starter/renative.json index cdbad9eb0..25354868e 100644 --- a/packages/template-starter/renative.json +++ b/packages/template-starter/renative.json @@ -212,25 +212,21 @@ "web": { "engine": "engine-rn-next", "webpackConfig": { - "nextTranspileModules": [ - "lodash-es" - ] + "nextTranspileModules": ["lodash-es"] } }, "chromecast": { "engine": "engine-rn-next", "webpackConfig": { - "nextTranspileModules": [ - "lodash-es" - ] + "nextTranspileModules": ["lodash-es"] } }, "tizen": { - "engine": "engine-lightning", + "engine": "engine-rn-web", "target": "es5" }, "webos": { - "engine": "engine-lightning" + "engine": "engine-rn-web" }, "tvos": { "engine": "engine-rn-tvos", @@ -239,9 +235,7 @@ }, "macos": { "engine": "engine-rn-electron", - "excludedPlugins": [ - "react-native-linear-gradient" - ] + "excludedPlugins": ["react-native-linear-gradient"] }, "windows": { "engine": "engine-rn-electron" diff --git a/packages/template-starter/src/components/menu.tv.web.tsx b/packages/template-starter/src/components/menu.tv.web.tsx new file mode 100644 index 000000000..24642b2ce --- /dev/null +++ b/packages/template-starter/src/components/menu.tv.web.tsx @@ -0,0 +1,3 @@ +import menu from './menu.tv.native'; + +export default menu; diff --git a/packages/template-starter/src/navigation/index.tv.native.tsx b/packages/template-starter/src/navigation/index.tv.native.tsx index 6868f6c3b..05e53596d 100644 --- a/packages/template-starter/src/navigation/index.tv.native.tsx +++ b/packages/template-starter/src/navigation/index.tv.native.tsx @@ -1,7 +1,8 @@ import React, { useEffect } from 'react'; -import { disableTVMenuKey, enableTVMenuKey, View } from '@flexn/create'; +import { disableTVMenuKey, enableTVMenuKey, setFocusManagerEnabled, View } from '@flexn/create'; +import { isPlatformTizen, isPlatformWebos } from '@rnv/renative'; import { enableScreens } from 'react-native-screens'; -import { StyleSheet } from 'react-native'; +import { StyleSheet, Dimensions } from 'react-native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { NavigationContainer, @@ -18,6 +19,9 @@ import Menu from '../components/menu'; import { ROUTES } from '../config'; import { SafeAreaProvider } from 'react-native-safe-area-context'; +const { height } = Dimensions.get('window'); + +setFocusManagerEnabled(true); enableScreens(); const createTVSideNavigator = createNavigatorFactory(Navigator); @@ -50,13 +54,13 @@ function Navigator({ initialRouteName, children, screenOptions, drawerContent, . {state.routes.map((route, i) => { const isFocused = state.index === i; + const style = + isPlatformTizen || isPlatformWebos + ? { opacity: isFocused ? 1 : 0 } + : [StyleSheet.absoluteFill, { opacity: isFocused ? 1 : 0 }]; return ( - + {descriptors[route.key].render()} ); @@ -99,6 +103,7 @@ const styles = StyleSheet.create({ zIndex: 2, opacity: 1, position: 'absolute', + ...((isPlatformTizen || isPlatformWebos) && { height }), }, content: { flex: 1 }, main: { flex: 1 }, diff --git a/packages/template-starter/src/navigation/index.tv.web.tsx b/packages/template-starter/src/navigation/index.tv.web.tsx index dd6c09d6a..c60dc6e6d 100644 --- a/packages/template-starter/src/navigation/index.tv.web.tsx +++ b/packages/template-starter/src/navigation/index.tv.web.tsx @@ -1,42 +1,3 @@ -import React, { useContext } from 'react'; -import { createStackNavigator, CardStyleInterpolators } from '@react-navigation/stack'; -import { NavigationContainer } from '@react-navigation/native'; -import ScreenHome from '../screens/home'; -import ScreenCarousels from '../screens/carousels'; -import ScreenDetails from '../screens/details'; -import ScreenModal from '../screens/modal'; -import { ROUTES, ThemeContext } from '../config'; +import navigation from './index.tv.native'; -const ModalStack = createStackNavigator(); -const Stack = createStackNavigator(); - -const CarouselsStack = () => ( - - - - -); - -const App = () => { - // eslint-disable-next-line - const { theme } = useContext(ThemeContext); - - return ( - - - - - - - - ); -}; - -export default App; +export default navigation; diff --git a/packages/template-starter/src/screens/details.tsx b/packages/template-starter/src/screens/details.tsx index 425e76587..bd4e72462 100644 --- a/packages/template-starter/src/screens/details.tsx +++ b/packages/template-starter/src/screens/details.tsx @@ -5,8 +5,10 @@ import { ThemeContext, ROUTES } from '../config'; import { usePop, useReplace } from '../hooks'; import { DataItem, getRandomItem, testProps } from '../utils'; import Screen from './screen'; +import { useWindowDimensions } from 'react-native'; const ScreenDetails = ({ route, navigation, router }: { navigation?: any; router?: any; route?: any }) => { + const { height } = useWindowDimensions(); const replace = useReplace({ navigation }); const pop = usePop({ navigation }); const [item, setItem] = useState(); @@ -28,7 +30,7 @@ const ScreenDetails = ({ route, navigation, router }: { navigation?: any; router } return ( - + diff --git a/packages/template-starter/src/screens/home.tsx b/packages/template-starter/src/screens/home.tsx index 2954b7773..26137b9e4 100644 --- a/packages/template-starter/src/screens/home.tsx +++ b/packages/template-starter/src/screens/home.tsx @@ -1,5 +1,5 @@ import React, { useContext, useRef } from 'react'; -import { ScrollView as RNScrollView } from 'react-native'; +import { ScrollView as RNScrollView, useWindowDimensions } from 'react-native'; import { Text, View, ScrollView, TouchableOpacity, Image, ANIMATION_TYPES, AnimatorBackground } from '@flexn/create'; import { Api } from '@rnv/renative'; import Icon from 'react-native-vector-icons/FontAwesome'; @@ -10,6 +10,7 @@ import Screen from './screen'; import packageJson from '../../package.json'; const ScreenHome = ({ navigation }: { navigation?: any }) => { + const { height } = useWindowDimensions(); const swRef = useRef() as React.MutableRefObject; const navigate = useNavigate({ navigation }); const openURL = useOpenURL(); @@ -24,7 +25,10 @@ const ScreenHome = ({ navigation }: { navigation?: any }) => { }; return ( - +