diff --git a/app/(app)/(authorized)/(tabs)/_layout.tsx b/app/(app)/(authorized)/(tabs)/_layout.tsx new file mode 100644 index 00000000..970c045f --- /dev/null +++ b/app/(app)/(authorized)/(tabs)/_layout.tsx @@ -0,0 +1,15 @@ +import { useScreenOptions } from '~hooks' +import { ResponsiveNavigator } from '~navigation/tabNavigator/navigator' + +export const unstable_settings = { + initialRouteName: 'home', +} + +export default function TabsLayout() { + // It's added here not in higher layout because we only want to hide header only on this screen + useScreenOptions({ + headerShown: false, + }) + + return +} diff --git a/app/(app)/(tabs)/example/_layout.tsx b/app/(app)/(authorized)/(tabs)/example/_layout.tsx similarity index 100% rename from app/(app)/(tabs)/example/_layout.tsx rename to app/(app)/(authorized)/(tabs)/example/_layout.tsx diff --git a/app/(app)/(tabs)/example/colors.tsx b/app/(app)/(authorized)/(tabs)/example/colors.tsx similarity index 100% rename from app/(app)/(tabs)/example/colors.tsx rename to app/(app)/(authorized)/(tabs)/example/colors.tsx diff --git a/app/(app)/(tabs)/example/components.tsx b/app/(app)/(authorized)/(tabs)/example/components.tsx similarity index 100% rename from app/(app)/(tabs)/example/components.tsx rename to app/(app)/(authorized)/(tabs)/example/components.tsx diff --git a/app/(app)/(tabs)/example/data-from-be.tsx b/app/(app)/(authorized)/(tabs)/example/data-from-be.tsx similarity index 100% rename from app/(app)/(tabs)/example/data-from-be.tsx rename to app/(app)/(authorized)/(tabs)/example/data-from-be.tsx diff --git a/app/(app)/(tabs)/example/index.tsx b/app/(app)/(authorized)/(tabs)/example/index.tsx similarity index 100% rename from app/(app)/(tabs)/example/index.tsx rename to app/(app)/(authorized)/(tabs)/example/index.tsx diff --git a/app/(app)/(tabs)/example/test-form.tsx b/app/(app)/(authorized)/(tabs)/example/test-form.tsx similarity index 100% rename from app/(app)/(tabs)/example/test-form.tsx rename to app/(app)/(authorized)/(tabs)/example/test-form.tsx diff --git a/app/(app)/(tabs)/example/typography.tsx b/app/(app)/(authorized)/(tabs)/example/typography.tsx similarity index 100% rename from app/(app)/(tabs)/example/typography.tsx rename to app/(app)/(authorized)/(tabs)/example/typography.tsx diff --git a/app/(app)/(tabs)/home/_layout.tsx b/app/(app)/(authorized)/(tabs)/home/_layout.tsx similarity index 100% rename from app/(app)/(tabs)/home/_layout.tsx rename to app/(app)/(authorized)/(tabs)/home/_layout.tsx diff --git a/app/(app)/(tabs)/home/details.tsx b/app/(app)/(authorized)/(tabs)/home/details.tsx similarity index 100% rename from app/(app)/(tabs)/home/details.tsx rename to app/(app)/(authorized)/(tabs)/home/details.tsx diff --git a/app/(app)/(tabs)/home/index.tsx b/app/(app)/(authorized)/(tabs)/home/index.tsx similarity index 100% rename from app/(app)/(tabs)/home/index.tsx rename to app/(app)/(authorized)/(tabs)/home/index.tsx diff --git a/app/(app)/(tabs)/settings/_layout.tsx b/app/(app)/(authorized)/(tabs)/settings/_layout.tsx similarity index 100% rename from app/(app)/(tabs)/settings/_layout.tsx rename to app/(app)/(authorized)/(tabs)/settings/_layout.tsx diff --git a/app/(app)/(tabs)/settings/index.tsx b/app/(app)/(authorized)/(tabs)/settings/index.tsx similarity index 100% rename from app/(app)/(tabs)/settings/index.tsx rename to app/(app)/(authorized)/(tabs)/settings/index.tsx diff --git a/app/(app)/(authorized)/_layout.tsx b/app/(app)/(authorized)/_layout.tsx new file mode 100644 index 00000000..efe1be08 --- /dev/null +++ b/app/(app)/(authorized)/_layout.tsx @@ -0,0 +1,17 @@ +import { Redirect, Stack } from 'expo-router' + +import { useAuth } from '~hooks' + +export const unstable_settings = { + initialRouteName: '(tabs)', +} + +export default function AuthorizedLayout() { + const { isSignedIn } = useAuth() + + if (isSignedIn === false) { + return + } + + return +} diff --git a/app/(app)/(authorized)/big-form.tsx b/app/(app)/(authorized)/big-form.tsx new file mode 100644 index 00000000..16c87b63 --- /dev/null +++ b/app/(app)/(authorized)/big-form.tsx @@ -0,0 +1,3 @@ +import { TestFormScreen } from '~screens' + +export default TestFormScreen diff --git a/app/(app)/(common)/blog.tsx b/app/(app)/(common)/blog.tsx new file mode 100644 index 00000000..e56f2aee --- /dev/null +++ b/app/(app)/(common)/blog.tsx @@ -0,0 +1,3 @@ +import { BlogScreen } from '~screens/BlogScreen' + +export default BlogScreen diff --git a/app/(app)/(auth)/_layout.tsx b/app/(app)/(not-authorized)/_layout.tsx similarity index 85% rename from app/(app)/(auth)/_layout.tsx rename to app/(app)/(not-authorized)/_layout.tsx index df38fb8e..2eca7350 100644 --- a/app/(app)/(auth)/_layout.tsx +++ b/app/(app)/(not-authorized)/_layout.tsx @@ -6,7 +6,7 @@ export const unstable_settings = { initialRouteName: 'sign-in', } -export default function AuthLayout() { +export default function NotAuthorizedLayout() { const { isSignedIn } = useAuth() if (isSignedIn === true) { diff --git a/app/(app)/(auth)/sign-in.tsx b/app/(app)/(not-authorized)/sign-in.tsx similarity index 100% rename from app/(app)/(auth)/sign-in.tsx rename to app/(app)/(not-authorized)/sign-in.tsx diff --git a/app/(app)/(auth)/sign-up.tsx b/app/(app)/(not-authorized)/sign-up.tsx similarity index 100% rename from app/(app)/(auth)/sign-up.tsx rename to app/(app)/(not-authorized)/sign-up.tsx diff --git a/app/(app)/(tabs)/_layout.tsx b/app/(app)/(tabs)/_layout.tsx deleted file mode 100644 index 4209b19f..00000000 --- a/app/(app)/(tabs)/_layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Redirect } from 'expo-router' - -import { useAuth } from '~hooks' -import { ResponsiveNavigator } from '~navigation/tabNavigator/navigator' - -export const unstable_settings = { - initialRouteName: 'home', -} - -export default function TabLayout() { - const { isSignedIn } = useAuth() - - if (isSignedIn === false) { - return - } - - return -} diff --git a/app/(app)/_layout.tsx b/app/(app)/_layout.tsx index c4bc25a2..f62c2985 100644 --- a/app/(app)/_layout.tsx +++ b/app/(app)/_layout.tsx @@ -1,10 +1,15 @@ import { Stack } from 'expo-router' +export const unstable_settings = { + initialRouteName: 'index', +} + export default function AppLayout() { return ( - - - + + + + ) diff --git a/app/_layout.tsx b/app/_layout.tsx index 153fc6bc..0be0a5c3 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,7 +1,7 @@ import { ThemeProvider } from '@react-navigation/native' import { Slot } from 'expo-router' -import { AbsoluteFullFill, Loader } from '~components' +import { AbsoluteFullFill, Loader, StatusBar } from '~components' import { useAuth, useNavigationTheme, useRouterNotifications } from '~hooks' import { Providers } from '~providers' @@ -33,6 +33,7 @@ const Layout = () => { export default function RootLayout() { return ( + ) diff --git a/app/index.tsx b/app/index.tsx index dd6b8465..156571bb 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,13 +1,19 @@ import { Redirect } from 'expo-router' +import { Platform } from 'react-native' import { useAuth } from '~hooks' +import { LandingScreen } from '~screens/LandingScreen' export default function Root() { const { isSignedIn } = useAuth() - if (isSignedIn === false) { - return + if (isSignedIn === true) { + return } - return + if (Platform.OS === 'web') { + return + } + + return } diff --git a/jest.setup.js b/jest.setup.js index e0393482..8e024f1e 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -3,6 +3,7 @@ import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/asy jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage) jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper') +jest.mock('expo-router/entry', () => jest.fn()) jest.mock('react-native-keyboard-aware-scroll-view', () => { const KeyboardAwareScrollView = ({ children }) => children diff --git a/package.json b/package.json index a9cc6573..c0354eb0 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "eslint", "prettier" ], - "main": "expo-router/entry", + "main": "./App", "repository": { "type": "git", "url": "https://github.com/binarapps/baca-react-native-template.git" diff --git a/src/components/LandingHeader.tsx b/src/components/LandingHeader.tsx new file mode 100644 index 00000000..63adf02d --- /dev/null +++ b/src/components/LandingHeader.tsx @@ -0,0 +1,63 @@ +import { useRouter } from 'expo-router' +import { Image, StyleSheet, Platform, View } from 'react-native' +import { useSafeAreaInsets } from 'react-native-safe-area-context' + +import { Box, Button, Icon, Pressable } from '~components' +import { darkLogoFull, lightLogoFull } from '~constants' +import { useColorScheme } from '~contexts' +import { useAuth, useTranslation } from '~hooks' +import { TabColorsStrings } from '~navigation/tabNavigator/config' + +export function LandingHeader() { + const { colorScheme } = useColorScheme() + const { top } = useSafeAreaInsets() + const { t } = useTranslation() + const { push, canGoBack, back } = useRouter() + + const { isSignedIn } = useAuth() + + const navigateToLogin = () => push('/sign-in') + + const height = 60 + top + return ( + + {canGoBack() ? ( + + + + ) : ( + + )} + {!isSignedIn ? ( + + ) : ( + + )} + + ) +} + +const jsStyles = StyleSheet.create({ + appHeader: { + alignItems: 'center', + borderBottomColor: TabColorsStrings.lightGray, + borderBottomWidth: 1, + flexDirection: 'row', + justifyContent: 'space-between', + paddingHorizontal: 16, + width: '100%', + zIndex: 10, + }, + logoWide: { height: 60, width: 150 }, +}) diff --git a/src/components/atoms/Button/Button.test.tsx b/src/components/atoms/Button/Button.test.tsx index 5aacf57c..cdfd3f98 100644 --- a/src/components/atoms/Button/Button.test.tsx +++ b/src/components/atoms/Button/Button.test.tsx @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native' -import { Button } from '.' +import { Button } from './Button' import { theme } from '~constants' import { cleanup, render, fireEvent, act } from '~utils/testUtils' diff --git a/src/components/atoms/Text/Text.test.tsx b/src/components/atoms/Text/Text.test.tsx index d9360f98..8de9a07b 100644 --- a/src/components/atoms/Text/Text.test.tsx +++ b/src/components/atoms/Text/Text.test.tsx @@ -1,4 +1,4 @@ -import { Text } from '.' +import { Text } from './Text' import { theme } from '~constants' import { cleanup, render } from '~utils/testUtils' diff --git a/src/hooks/navigation/useRouterNotifications.ts b/src/hooks/navigation/useRouterNotifications.ts index e7329054..fe2b6c39 100644 --- a/src/hooks/navigation/useRouterNotifications.ts +++ b/src/hooks/navigation/useRouterNotifications.ts @@ -1,8 +1,9 @@ import * as Notifications from 'expo-notifications' import { useRouter } from 'expo-router' import React from 'react' +import { Platform } from 'react-native' -export function useRouterNotifications() { +function useRouterNotificationsNative() { const router = useRouter() React.useEffect(() => { @@ -37,3 +38,6 @@ export function useRouterNotifications() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) } + +export const useRouterNotifications = + Platform.OS !== 'web' ? useRouterNotificationsNative : () => null diff --git a/src/hooks/navigation/useScreenOptions.ts b/src/hooks/navigation/useScreenOptions.ts index 82374a63..927f4ab9 100644 --- a/src/hooks/navigation/useScreenOptions.ts +++ b/src/hooks/navigation/useScreenOptions.ts @@ -4,13 +4,15 @@ import { useLayoutEffect } from 'react' export const useScreenOptions = ({ title, presentation, + headerShown, }: { title?: string presentation?: string + headerShown?: boolean }) => { const navigation = useNavigation() useLayoutEffect(() => { - navigation.setOptions({ title, presentation }) - }, [navigation, presentation, title]) + navigation.setOptions({ title, presentation, headerShown }) + }, [headerShown, navigation, presentation, title]) } diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 5024e7bd..bd59b5d5 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -53,7 +53,9 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography" + "typography": "Typography", + "test_form": "Test form", + "blog": "Blog" } }, "update": { @@ -64,6 +66,11 @@ "examples_component": { "example": "Example" }, + "landing_screen": { + "login_cta": "Login to app", + "go_to_blog": "Open blog", + "go_to_form": "Open full screen form" + }, "application_info_screen": { "navigation_info": "When you will try to go back it will double ask if you really want to leave \n" }, diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index f03692f9..7429dd19 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -53,7 +53,9 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography" + "typography": "Typography", + "test_form": "Formularz testowy", + "blog": "Blog" } }, "update": { @@ -64,6 +66,11 @@ "examples_component": { "example": "Przykład" }, + "landing_screen": { + "login_cta": "Zaloguj się", + "go_to_blog": "Otwórz blog", + "go_to_form": "Otwórz pełno ekranowy formularz full" + }, "application_info_screen": { "navigation_info": "Kiedy będziesz próbował cofnąć to zostaniesz podwójnie zapytany, czy na pewno tego chcesz \n" }, diff --git a/src/screens/ApplicationInfoScreen.tsx b/src/screens/ApplicationInfoScreen.tsx index a440352d..677f10d1 100644 --- a/src/screens/ApplicationInfoScreen.tsx +++ b/src/screens/ApplicationInfoScreen.tsx @@ -3,16 +3,25 @@ import * as Application from 'expo-application' import * as Clipboard from 'expo-clipboard' import Constants from 'expo-constants' import * as Notifications from 'expo-notifications' +import { useRouter } from 'expo-router' import { ScrollView, StyleSheet } from 'react-native' -import { Button, Text } from '~components' +import { Box, Button, Text } from '~components' import { isExpoGo } from '~constants' -import { useCallback, usePreventGoBack, useScreenOptions, useTranslation } from '~hooks' +import { + useCallback, + usePreventGoBack, + useSafeAreaInsets, + useScreenOptions, + useTranslation, +} from '~hooks' const projectId = Constants.expoConfig?.extra?.eas?.projectId export const ApplicationInfoScreen = (): JSX.Element => { const { i18n, t } = useTranslation() + const { bottom } = useSafeAreaInsets() + const { canGoBack, back } = useRouter() useScreenOptions({ title: t('navigation.screen_titles.application_info'), @@ -55,12 +64,22 @@ export const ApplicationInfoScreen = (): JSX.Element => { {Application.nativeApplicationVersion} {Application.nativeBuildVersion} {i18n.languages.join(', ')} + {canGoBack() && ( + <> + + + + + )} ) } const styles = StyleSheet.create({ container: { + flexGrow: 1, padding: 16, }, }) diff --git a/src/screens/BlogScreen.tsx b/src/screens/BlogScreen.tsx new file mode 100644 index 00000000..b9be200b --- /dev/null +++ b/src/screens/BlogScreen.tsx @@ -0,0 +1,13 @@ +import { Center, Text } from '~components' +import { LandingHeader } from '~components/LandingHeader' + +export const BlogScreen = () => { + return ( + <> + +
+ This is blog screen, and is visible by logged in and logged out users +
+ + ) +} diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index c08e12de..36ee9ab7 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -21,6 +21,13 @@ export const HomeScreen = () => { params: { user: 'example@example.com' }, }) }, []) + const navigateToBlog = useCallback(() => { + router.navigate('/blog') + }, []) + + const navigateToBigForm = useCallback(() => { + router.navigate('/big-form') + }, []) return (
@@ -36,6 +43,12 @@ export const HomeScreen = () => { + +
) } diff --git a/src/screens/LandingScreen.tsx b/src/screens/LandingScreen.tsx new file mode 100644 index 00000000..cb2af2b0 --- /dev/null +++ b/src/screens/LandingScreen.tsx @@ -0,0 +1,56 @@ +import { router } from 'expo-router' +import { Image, StyleSheet } from 'react-native' + +import { Button, Center, Text } from '~components' +import { LandingHeader } from '~components/LandingHeader' +import { darkLogo, lightLogo } from '~constants' +import { useColorScheme } from '~contexts' +import { useCallback, useScreenOptions, useTranslation } from '~hooks' + +export const LandingScreen = () => { + const { t } = useTranslation() + + useScreenOptions({ + title: t('navigation.screen_titles.home'), + }) + + const { colorScheme } = useColorScheme() + + const navigateToBlog = useCallback(() => { + router.navigate('/blog') + }, []) + + const navigateToBigForm = useCallback(() => { + router.navigate('/big-form') + }, []) + + return ( + <> + +
+ + {t('hello')} + {t('thanks')} + {t('app_information')} + + +
+ + ) +} + +const styles = StyleSheet.create({ + logo: { + height: 100, + width: '100%', + }, +}) diff --git a/src/screens/TestFormScreen.tsx b/src/screens/TestFormScreen.tsx index f758a37c..ba85f148 100644 --- a/src/screens/TestFormScreen.tsx +++ b/src/screens/TestFormScreen.tsx @@ -27,7 +27,7 @@ export const TestFormScreen = (): JSX.Element => { const { t } = useTranslation() useScreenOptions({ - title: t('navigation.screen_titles.colors'), + title: t('navigation.screen_titles.test_form'), }) const { control, errors, submit, VALIDATION, setFocus } = useTestForm()