From 6f6b0964441024671545b85a7ad7f46d893b8d5b Mon Sep 17 00:00:00 2001 From: Billy Jacoby Date: Sun, 8 Oct 2023 08:03:01 -0400 Subject: [PATCH 1/5] chore: rename navigation --- ios/Podfile.lock | 2 +- src/navigation/CameraTabNavigator.tsx | 45 ++++ src/navigation/RootNavigation.tsx | 95 +++++++++ .../components/LeftHeaderButton.tsx | 31 +++ .../components/RightHeaderButton.tsx | 15 ++ src/navigation/components/TabBarIcon.tsx | 50 +++++ src/navigation/components/index.ts | 2 + src/navigation/index.ts | 2 +- src/navigation/navigationContainer.tsx | 200 ------------------ .../EventsScreen/EventsScreen.tsx | 0 .../EventsScreen/components/CameraEvent.tsx | 0 .../EventsScreen/components/EventDetails.tsx | 0 .../components/EventListFooter.tsx | 0 .../components/SectionDateHeader.tsx | 0 .../EventsScreen/components/index.ts | 0 .../{ => CameraScreens}/EventsScreen/index.ts | 0 .../{ => CameraScreens}/LiveViewScreen.tsx | 0 src/screens/CameraScreens/index.ts | 2 + src/screens/HomeScreen.tsx | 2 +- src/screens/index.ts | 3 +- 20 files changed, 244 insertions(+), 205 deletions(-) create mode 100644 src/navigation/CameraTabNavigator.tsx create mode 100644 src/navigation/RootNavigation.tsx create mode 100644 src/navigation/components/LeftHeaderButton.tsx create mode 100644 src/navigation/components/RightHeaderButton.tsx create mode 100644 src/navigation/components/TabBarIcon.tsx create mode 100644 src/navigation/components/index.ts delete mode 100644 src/navigation/navigationContainer.tsx rename src/screens/{ => CameraScreens}/EventsScreen/EventsScreen.tsx (100%) rename src/screens/{ => CameraScreens}/EventsScreen/components/CameraEvent.tsx (100%) rename src/screens/{ => CameraScreens}/EventsScreen/components/EventDetails.tsx (100%) rename src/screens/{ => CameraScreens}/EventsScreen/components/EventListFooter.tsx (100%) rename src/screens/{ => CameraScreens}/EventsScreen/components/SectionDateHeader.tsx (100%) rename src/screens/{ => CameraScreens}/EventsScreen/components/index.ts (100%) rename src/screens/{ => CameraScreens}/EventsScreen/index.ts (100%) rename src/screens/{ => CameraScreens}/LiveViewScreen.tsx (100%) create mode 100644 src/screens/CameraScreens/index.ts diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 04efaf5..8405143 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -801,4 +801,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: b0e3f0f7f573d264ac8c53b7b631360254dc3679 -COCOAPODS: 1.12.1 +COCOAPODS: 1.13.0 diff --git a/src/navigation/CameraTabNavigator.tsx b/src/navigation/CameraTabNavigator.tsx new file mode 100644 index 0000000..3e45799 --- /dev/null +++ b/src/navigation/CameraTabNavigator.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import {useColorScheme} from 'react-native'; + +import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; + +import {EventsScreen, LiveViewScreen} from '@screens'; +import {hslToHex} from '@utils'; + +import {colors} from '../../themeColors.js'; + +import {TabBarIcon} from './components/TabBarIcon'; + +export type CameraTabsStackParamList = { + Events: undefined; + Live: undefined; + Recordings: undefined; +}; + +const CameraTabStack = createBottomTabNavigator(); + +export const CameraTabNavigator = () => { + const isDarkMode = useColorScheme() === 'dark'; + + return ( + ({ + headerTitle: '', + tabBarIcon: ({color, size}) => + TabBarIcon({color, size, route, isDarkMode}), + tabBarActiveTintColor: isDarkMode ? 'white' : 'black', + tabBarInactiveTintColor: 'gray', + tabBarStyle: { + borderTopWidth: 0, + backgroundColor: isDarkMode + ? hslToHex(colors.dark.background) + : hslToHex(colors.light.background), + }, + header: () => null, + })}> + + + + + ); +}; diff --git a/src/navigation/RootNavigation.tsx b/src/navigation/RootNavigation.tsx new file mode 100644 index 0000000..436856d --- /dev/null +++ b/src/navigation/RootNavigation.tsx @@ -0,0 +1,95 @@ +import {useColorScheme} from 'react-native'; + +import { + NavigationContainer, + NavigatorScreenParams, +} from '@react-navigation/native'; +import {createNativeStackNavigator} from '@react-navigation/native-stack'; + +import { + CameraTabNavigator, + CameraTabsStackParamList, +} from './CameraTabNavigator'; +import {LeftHeaderButton, RightHeaderButton} from './components'; +import { + BirdseyeScreen, + HomeScreen, + OnBoardingScreen, + SettingsScreen, +} from '@screens'; +import {useAppDataStore} from '@stores'; +import {hslToHex} from '@utils'; + +import {colors} from '../../themeColors.js'; + +export type MainStackParamList = { + Home: undefined; + Birdseye: undefined; + CameraTabs: NavigatorScreenParams; + Settings: undefined; + Onboarding: undefined; +}; + +const Stack = createNativeStackNavigator(); + +export const RootNavigation = () => { + const currentCamera = useAppDataStore(state => state.currentCamera); + const isDarkMode = useColorScheme() === 'dark'; + + const tintColor = isDarkMode + ? hslToHex(colors.dark.foreground) + : hslToHex(colors.light.foreground); + + const backgroundColor = isDarkMode + ? hslToHex(colors.dark.background) + : hslToHex(colors.light.background); + + return ( + + + LeftHeaderButton(props as {tintColor: string}), + headerRight: props => + RightHeaderButton(props as {tintColor: string}), + headerTintColor: isDarkMode + ? hslToHex(colors.dark.foreground) + : hslToHex(colors.light.foreground), + }} + /> + + + + + + + ); +}; diff --git a/src/navigation/components/LeftHeaderButton.tsx b/src/navigation/components/LeftHeaderButton.tsx new file mode 100644 index 0000000..5737c7c --- /dev/null +++ b/src/navigation/components/LeftHeaderButton.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import {TouchableOpacity} from 'react-native'; + +import BirdseyeIcon from '@icons/birdseye.svg'; +import {useNavigation} from '@react-navigation/native'; + +import {useConfig} from '@api'; + +export const LeftHeaderButton = ({tintColor}: {tintColor?: string}) => { + const nav = useNavigation(); + const config = useConfig(); + + if (!config.data?.birdseye.enabled) { + return null; + } + + return ( + { + nav.navigate('Birdseye'); + }}> + + + ); +}; diff --git a/src/navigation/components/RightHeaderButton.tsx b/src/navigation/components/RightHeaderButton.tsx new file mode 100644 index 0000000..3ddc2d6 --- /dev/null +++ b/src/navigation/components/RightHeaderButton.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import {TouchableOpacity} from 'react-native'; + +import SettingsIcon from '@icons/settings.svg'; +import {useNavigation} from '@react-navigation/native'; + +export const RightHeaderButton = ({tintColor}: {tintColor?: string}) => { + const navigation = useNavigation(); + + return ( + navigation.navigate('Settings')}> + + + ); +}; diff --git a/src/navigation/components/TabBarIcon.tsx b/src/navigation/components/TabBarIcon.tsx new file mode 100644 index 0000000..55f2f2a --- /dev/null +++ b/src/navigation/components/TabBarIcon.tsx @@ -0,0 +1,50 @@ +import EventIcon from '@icons/event.svg'; +import RecordingIcon from '@icons/recording.svg'; +import VideoIcon from '@icons/video-waveform.svg'; +import {RouteProp} from '@react-navigation/native'; + +import {CameraTabsStackParamList} from '../CameraTabNavigator'; + +export const TabBarIcon = ({ + color, + size, + route, + isDarkMode, +}: { + color: string; + size: number; + isDarkMode: boolean; + route: RouteProp; +}) => { + if (route.name === 'Recordings') { + return ( + + ); + } + if (route.name === 'Events') { + return ( + + ); + } + if (route.name === 'Live') { + return ( + + ); + } + return null; +}; diff --git a/src/navigation/components/index.ts b/src/navigation/components/index.ts new file mode 100644 index 0000000..d21232f --- /dev/null +++ b/src/navigation/components/index.ts @@ -0,0 +1,2 @@ +export * from './LeftHeaderButton'; +export * from './RightHeaderButton'; diff --git a/src/navigation/index.ts b/src/navigation/index.ts index b5551dd..96e9fff 100644 --- a/src/navigation/index.ts +++ b/src/navigation/index.ts @@ -1 +1 @@ -export * from './navigationContainer'; +export * from './RootNavigation'; diff --git a/src/navigation/navigationContainer.tsx b/src/navigation/navigationContainer.tsx deleted file mode 100644 index d57e600..0000000 --- a/src/navigation/navigationContainer.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import {TouchableOpacity, useColorScheme} from 'react-native'; - -import BirdseyeIcon from '@icons/birdseye.svg'; -import EventIcon from '@icons/event.svg'; -import HomeIcon from '@icons/home.svg'; -import SettingsIcon from '@icons/settings.svg'; -import VideoIcon from '@icons/video-waveform.svg'; -import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import { - NavigationContainer, - NavigatorScreenParams, - useNavigation, -} from '@react-navigation/native'; -import {createNativeStackNavigator} from '@react-navigation/native-stack'; - -import {useConfig} from '@api'; -import { - BirdseyeScreen, - EventsScreen, - HomeScreen, - LiveViewScreen, - OnBoardingScreen, - SettingsScreen, -} from '@screens'; -import {useAppDataStore} from '@stores'; -import {hslToHex} from '@utils'; - -import {colors} from '../../themeColors.js'; - -export type MainStackParamList = { - Home: undefined; - Birdseye: undefined; - Tabs: NavigatorScreenParams; - Settings: undefined; - Onboarding: undefined; -}; - -const Stack = createNativeStackNavigator(); - -export type TabsStackParamList = { - Events: undefined; - Live: undefined; - Recordings: undefined; -}; - -const TabStack = createBottomTabNavigator(); - -const TabNavigator = () => { - const isDarkMode = useColorScheme() === 'dark'; - - return ( - ({ - headerTitle: '', - // eslint-disable-next-line react/no-unstable-nested-components - tabBarIcon: ({color, size}) => { - if (route.name === 'Recordings') { - // TODO - return ( - - ); - } - if (route.name === 'Events') { - return ( - - ); - } - if (route.name === 'Live') { - return ( - - ); - } - return null; - }, - tabBarActiveTintColor: isDarkMode ? 'white' : 'black', - tabBarInactiveTintColor: 'gray', - tabBarStyle: { - borderTopWidth: 0, - backgroundColor: isDarkMode - ? hslToHex(colors.dark.background) - : hslToHex(colors.light.background), - }, - header: () => null, - })}> - - - - ); -}; - -const LeftHeaderButton = ({tintColor}: {tintColor?: string}) => { - const nav = useNavigation(); - const config = useConfig(); - - if (!config.data?.birdseye.enabled) { - return null; - } - - return ( - { - nav.navigate('Birdseye'); - }}> - - - ); -}; - -const RightHeaderButton = ({tintColor}: {tintColor?: string}) => { - const navigation = useNavigation(); - - return ( - navigation.navigate('Settings')}> - - - ); -}; - -export const RootNavigation = () => { - const currentCamera = useAppDataStore(state => state.currentCamera); - const isDarkMode = useColorScheme() === 'dark'; - - const tintColor = isDarkMode - ? hslToHex(colors.dark.foreground) - : hslToHex(colors.light.foreground); - - const backgroundColor = isDarkMode - ? hslToHex(colors.dark.background) - : hslToHex(colors.light.background); - - return ( - - - LeftHeaderButton(props as {tintColor: string}), - headerRight: props => - RightHeaderButton(props as {tintColor: string}), - headerTintColor: isDarkMode - ? hslToHex(colors.dark.foreground) - : hslToHex(colors.light.foreground), - }} - /> - - - - - - - ); -}; diff --git a/src/screens/EventsScreen/EventsScreen.tsx b/src/screens/CameraScreens/EventsScreen/EventsScreen.tsx similarity index 100% rename from src/screens/EventsScreen/EventsScreen.tsx rename to src/screens/CameraScreens/EventsScreen/EventsScreen.tsx diff --git a/src/screens/EventsScreen/components/CameraEvent.tsx b/src/screens/CameraScreens/EventsScreen/components/CameraEvent.tsx similarity index 100% rename from src/screens/EventsScreen/components/CameraEvent.tsx rename to src/screens/CameraScreens/EventsScreen/components/CameraEvent.tsx diff --git a/src/screens/EventsScreen/components/EventDetails.tsx b/src/screens/CameraScreens/EventsScreen/components/EventDetails.tsx similarity index 100% rename from src/screens/EventsScreen/components/EventDetails.tsx rename to src/screens/CameraScreens/EventsScreen/components/EventDetails.tsx diff --git a/src/screens/EventsScreen/components/EventListFooter.tsx b/src/screens/CameraScreens/EventsScreen/components/EventListFooter.tsx similarity index 100% rename from src/screens/EventsScreen/components/EventListFooter.tsx rename to src/screens/CameraScreens/EventsScreen/components/EventListFooter.tsx diff --git a/src/screens/EventsScreen/components/SectionDateHeader.tsx b/src/screens/CameraScreens/EventsScreen/components/SectionDateHeader.tsx similarity index 100% rename from src/screens/EventsScreen/components/SectionDateHeader.tsx rename to src/screens/CameraScreens/EventsScreen/components/SectionDateHeader.tsx diff --git a/src/screens/EventsScreen/components/index.ts b/src/screens/CameraScreens/EventsScreen/components/index.ts similarity index 100% rename from src/screens/EventsScreen/components/index.ts rename to src/screens/CameraScreens/EventsScreen/components/index.ts diff --git a/src/screens/EventsScreen/index.ts b/src/screens/CameraScreens/EventsScreen/index.ts similarity index 100% rename from src/screens/EventsScreen/index.ts rename to src/screens/CameraScreens/EventsScreen/index.ts diff --git a/src/screens/LiveViewScreen.tsx b/src/screens/CameraScreens/LiveViewScreen.tsx similarity index 100% rename from src/screens/LiveViewScreen.tsx rename to src/screens/CameraScreens/LiveViewScreen.tsx diff --git a/src/screens/CameraScreens/index.ts b/src/screens/CameraScreens/index.ts new file mode 100644 index 0000000..3e2cef7 --- /dev/null +++ b/src/screens/CameraScreens/index.ts @@ -0,0 +1,2 @@ +export * from './LiveViewScreen'; +export * from './EventsScreen'; diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 040cec1..ec6d239 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -18,7 +18,7 @@ export const HomeScreen = () => { const onCameraPress = (cameraName: string) => { setCurrentCamera(cameraName); - navigation.navigate('Tabs', {screen: 'Events'}); + navigation.navigate('CameraTabs', {screen: 'Events'}); }; if (isLoading) { diff --git a/src/screens/index.ts b/src/screens/index.ts index 4e907bd..69a516c 100644 --- a/src/screens/index.ts +++ b/src/screens/index.ts @@ -1,6 +1,5 @@ export * from './HomeScreen'; -export * from './LiveViewScreen'; -export * from './EventsScreen'; +export * from './CameraScreens'; export * from './SettingsScreen'; // export * from './onboardingScreen'; From d7e3af9d503407c3bf9ed5f0b452a99331004b42 Mon Sep 17 00:00:00 2001 From: Billy Jacoby Date: Fri, 13 Oct 2023 17:32:04 -0400 Subject: [PATCH 2/5] feat: add recording screens --- ios/Podfile.lock | 12 ++ package.json | 2 + src/assets/icons/play-rect.svg | 4 + src/assets/icons/recording.svg | 11 ++ src/components/VideoPlayer.tsx | 7 +- src/components/index.ts | 1 + src/components/loadingView.tsx | 11 ++ src/lib/api/hooks/index.ts | 4 + src/lib/api/hooks/useRecordingSummary.ts | 33 ++++++ src/lib/api/hooks/useRecordings.ts | 34 ++++++ src/lib/api/index.ts | 3 +- src/lib/api/types/recordings.ts | 13 +++ src/navigation/CameraTabNavigator.tsx | 4 +- src/navigation/RootNavigation.tsx | 13 +++ .../EventsScreen/EventsScreen.tsx | 20 +--- .../RecordingsScreen/RecordingsScreen.tsx | 108 ++++++++++++++++++ .../RecordingsScreen/components/index.ts | 0 .../CameraScreens/RecordingsScreen/index.ts | 1 + .../components/SectionDateHeader.tsx | 33 +++--- src/screens/CameraScreens/components/index.ts | 1 + src/screens/CameraScreens/index.ts | 1 + src/screens/FullscreenVideo.tsx | 32 ++++++ src/screens/index.ts | 1 + yarn.lock | 62 +++++++++- 24 files changed, 373 insertions(+), 38 deletions(-) create mode 100644 src/assets/icons/play-rect.svg create mode 100644 src/assets/icons/recording.svg create mode 100644 src/components/loadingView.tsx create mode 100644 src/lib/api/hooks/index.ts create mode 100644 src/lib/api/hooks/useRecordingSummary.ts create mode 100644 src/lib/api/hooks/useRecordings.ts create mode 100644 src/lib/api/types/recordings.ts create mode 100644 src/screens/CameraScreens/RecordingsScreen/RecordingsScreen.tsx create mode 100644 src/screens/CameraScreens/RecordingsScreen/components/index.ts create mode 100644 src/screens/CameraScreens/RecordingsScreen/index.ts rename src/screens/CameraScreens/{EventsScreen => }/components/SectionDateHeader.tsx (50%) create mode 100644 src/screens/CameraScreens/components/index.ts create mode 100644 src/screens/FullscreenVideo.tsx diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8405143..f6da4af 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -502,8 +502,12 @@ PODS: - React-jsi (= 0.72.4) - React-logger (= 0.72.4) - React-perflogger (= 0.72.4) + - RNFlashList (1.6.1): + - React-Core - RNGestureHandler (2.12.1): - React-Core + - RNLocalize (3.0.2): + - React-Core - RNReanimated (3.5.0): - DoubleConversion - FBLazyVector @@ -610,7 +614,9 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNLocalize (from `../node_modules/react-native-localize`) - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) @@ -722,8 +728,12 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/utils" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNFlashList: + :path: "../node_modules/@shopify/flash-list" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" + RNLocalize: + :path: "../node_modules/react-native-localize" RNReanimated: :path: "../node_modules/react-native-reanimated" RNScreens: @@ -791,7 +801,9 @@ SPEC CHECKSUMS: React-runtimescheduler: 4941cc1b3cf08b792fbf666342c9fc95f1969035 React-utils: b79f2411931f9d3ea5781404dcbb2fa8a837e13a ReactCommon: 4b2bdcb50a3543e1c2b2849ad44533686610826d + RNFlashList: 236646d48f224a034f35baa0242e1b77db063b1e RNGestureHandler: c0d04458598fcb26052494ae23dda8f8f5162b13 + RNLocalize: dbea38dcb344bf80ff18a1757b1becf11f70cae4 RNReanimated: fd0dc9a5889bfac6c45a922b26c902dc6185b4dc RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: ed492aaf3af9ca01bc945f7a149d76d62e73ec82 diff --git a/package.json b/package.json index ff2e077..ea220d1 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,14 @@ "@react-navigation/bottom-tabs": "^6.5.8", "@react-navigation/native": "^6.1.7", "@react-navigation/native-stack": "^6.9.13", + "@shopify/flash-list": "^1.6.1", "@types/react-native-video": "^5.0.15", "clsx": "^2.0.0", "nativewind": "^2.0.11", "react": "18.2.0", "react-native": "0.72.4", "react-native-gesture-handler": "^2.12.1", + "react-native-localize": "^3.0.2", "react-native-mmkv": "^2.10.2", "react-native-reanimated": "^3.5.0", "react-native-safe-area-context": "^4.7.1", diff --git a/src/assets/icons/play-rect.svg b/src/assets/icons/play-rect.svg new file mode 100644 index 0000000..cd5ebc8 --- /dev/null +++ b/src/assets/icons/play-rect.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/recording.svg b/src/assets/icons/recording.svg new file mode 100644 index 0000000..6529574 --- /dev/null +++ b/src/assets/icons/recording.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/components/VideoPlayer.tsx b/src/components/VideoPlayer.tsx index d64d7f9..c209c68 100644 --- a/src/components/VideoPlayer.tsx +++ b/src/components/VideoPlayer.tsx @@ -6,23 +6,26 @@ export const VideoPlayer = ({ videoURI, isPaused = true, snapshotURL, + isForcedFullscreen, }: { videoURI: string; isPaused?: boolean; snapshotURL?: string; + isForcedFullscreen?: boolean; }) => { React.useEffect(() => {}, []); return (