From 850599b9d56a4fa0638acb6d13abe03fc5f662f6 Mon Sep 17 00:00:00 2001 From: Szymon Piwowarczyk Date: Sun, 13 Oct 2024 21:02:14 +0200 Subject: [PATCH] fix(#23, #24): Cameras won't reload when credentials changed --- components/Refresh.tsx | 17 ++++ views/camera-events/CameraEvent.tsx | 6 +- views/camera-events/CameraEvents.tsx | 23 ++++-- views/cameras-list/CamerasList.tsx | 18 ++-- views/logs/Logs.tsx | 22 ++--- views/storage/Storage.tsx | 119 ++++++++++++++------------- views/system/System.tsx | 2 +- 7 files changed, 124 insertions(+), 83 deletions(-) create mode 100644 components/Refresh.tsx diff --git a/components/Refresh.tsx b/components/Refresh.tsx new file mode 100644 index 0000000..f3c598b --- /dev/null +++ b/components/Refresh.tsx @@ -0,0 +1,17 @@ +import {RefreshControl} from 'react-native-gesture-handler'; +import {useTheme} from '../helpers/colors'; +import {FC} from 'react'; +import {RefreshControlProps} from 'react-native'; + +export const Refresh: FC = refreshControlProps => { + const theme = useTheme(); + + return ( + + ); +}; diff --git a/views/camera-events/CameraEvent.tsx b/views/camera-events/CameraEvent.tsx index f1d0906..ce2d69d 100644 --- a/views/camera-events/CameraEvent.tsx +++ b/views/camera-events/CameraEvent.tsx @@ -110,7 +110,7 @@ export const CameraEvent: FC = props => { ); }, }), - [apiUrl, id, intl, onDelete], + [apiUrl, credentials, id, intl, onDelete], ); const retainDrawerItem: DrawerItemProps = useMemo( @@ -146,7 +146,7 @@ export const CameraEvent: FC = props => { }); }, }, - [apiUrl, id, intl, retained], + [apiUrl, credentials, id, intl, retained], ); const shareDrawerItem: DrawerItemProps = useMemo( @@ -158,7 +158,7 @@ export const CameraEvent: FC = props => { onShare(event); }, }), - [apiUrl, id, intl, retained], + [apiUrl, credentials, id, intl, retained], ); return ( diff --git a/views/camera-events/CameraEvents.tsx b/views/camera-events/CameraEvents.tsx index beaf3b8..56e28e1 100644 --- a/views/camera-events/CameraEvents.tsx +++ b/views/camera-events/CameraEvents.tsx @@ -30,6 +30,8 @@ import {Background} from '../../components/Background'; import {useOrientation} from '../../helpers/screen'; import {Share} from './Share'; import {useStyles} from '../../helpers/colors'; +import {Refresh} from '../../components/Refresh'; +import {View} from 'react-native-ui-lib'; export interface ICameraEventsProps { cameraNames?: string[]; @@ -200,7 +202,14 @@ export const CameraEvents: NavigationFunctionComponent = ({ setEvents([...events, ...data]); }); } - }, [apiUrl, endReached, events, eventsQueryParams, watchEndReached]); + }, [ + apiUrl, + credentials, + endReached, + events, + eventsQueryParams, + watchEndReached, + ]); useEffect(() => { refresh(); @@ -263,9 +272,12 @@ export const CameraEvents: NavigationFunctionComponent = ({ return ( {!refreshing && events.length === 0 && ( - - {intl.formatMessage(messages['noEvents'])} - + + + + {intl.formatMessage(messages['noEvents'])} + + )} = ({ )} keyExtractor={data => data.id} initialNumToRender={30} - refreshing={refreshing} - onRefresh={refresh} onEndReached={loadMore} onEndReachedThreshold={0.5} numColumns={numColumns} + refreshControl={} /> setSharedEvent(undefined)} /> diff --git a/views/cameras-list/CamerasList.tsx b/views/cameras-list/CamerasList.tsx index bf7884b..53cc7b8 100644 --- a/views/cameras-list/CamerasList.tsx +++ b/views/cameras-list/CamerasList.tsx @@ -1,6 +1,6 @@ import React, {useCallback, useEffect, useState} from 'react'; import {useIntl} from 'react-intl'; -import {FlatList, StyleSheet, Text} from 'react-native'; +import {FlatList, Text} from 'react-native'; import {Navigation, NavigationFunctionComponent} from 'react-native-navigation'; import {get} from '../../helpers/rest'; import { @@ -22,6 +22,8 @@ import {messages} from './messages'; import {useNoServer} from '../settings/useNoServer'; import {Background} from '../../components/Background'; import {useStyles} from '../../helpers/colors'; +import {View} from 'react-native-ui-lib'; +import {Refresh} from '../../components/Refresh'; interface IConfigResponse { cameras: Record< @@ -95,7 +97,7 @@ export const CamerasList: NavigationFunctionComponent = ({componentId}) => { .finally(() => { setLoading(false); }); - }, [apiUrl, dispatch]); + }, [apiUrl, credentials, dispatch]); useEffect(() => { if (apiUrl !== undefined) { @@ -106,9 +108,12 @@ export const CamerasList: NavigationFunctionComponent = ({componentId}) => { return ( {!loading && cameras.length === 0 && ( - - {intl.formatMessage(messages['noCameras'])} - + + + + {intl.formatMessage(messages['noCameras'])} + + )} { )} keyExtractor={cameraName => cameraName} - refreshing={loading} - onRefresh={refresh} numColumns={numColumns} + refreshControl={} /> ); diff --git a/views/logs/Logs.tsx b/views/logs/Logs.tsx index 2143964..8e9e527 100644 --- a/views/logs/Logs.tsx +++ b/views/logs/Logs.tsx @@ -11,10 +11,14 @@ import { import {messages} from './messages'; import {menuButton, useMenu} from '../menu/menuHelpers'; import {useAppSelector} from '../../store/store'; -import {selectServerApiUrl} from '../../store/settings'; +import { + selectServerApiUrl, + selectServerCredentials, +} from '../../store/settings'; import {Log, LogPreview} from './LogPreview'; import {refreshButton} from '../../helpers/buttonts'; import {useTheme, useStyles} from '../../helpers/colors'; +import {get} from '../../helpers/rest'; const {TabBar, TabPage} = TabController; export const Logs: NavigationFunctionComponent = ({componentId}) => { @@ -31,6 +35,7 @@ export const Logs: NavigationFunctionComponent = ({componentId}) => { const [logs, setLogs] = useState([]); const [loading, setLoading] = useState(true); const apiUrl = useAppSelector(selectServerApiUrl); + const credentials = useAppSelector(selectServerCredentials); const intl = useIntl(); useEffect(() => { @@ -50,14 +55,7 @@ export const Logs: NavigationFunctionComponent = ({componentId}) => { const logsTypes = ['frigate', 'go2rtc', 'nginx']; Promise.allSettled( logsTypes.map(logType => - fetch(`${apiUrl}/logs/${logType}`).then(result => { - const statusGroup = Math.floor(result.status / 100); - if (statusGroup === 2) { - return result.text(); - } else { - throw new Error(`Status: ${result.status}`); - } - }), + get(`${apiUrl}/logs/${logType}`, credentials, undefined, false), ), ).then(logsData => { const updatedLogs: Log[] = logsTypes @@ -91,7 +89,11 @@ export const Logs: NavigationFunctionComponent = ({componentId}) => { ); return loading ? ( - + ) : logs.length > 1 ? ( diff --git a/views/storage/Storage.tsx b/views/storage/Storage.tsx index 2ef9e6d..82c0eb5 100644 --- a/views/storage/Storage.tsx +++ b/views/storage/Storage.tsx @@ -1,21 +1,29 @@ -import { useIntl } from 'react-intl'; -import { Navigation, NavigationFunctionComponent } from 'react-native-navigation'; -import { Carousel, LoaderScreen, PageControlPosition } from 'react-native-ui-lib'; -import { useAppSelector } from '../../store/store'; -import { selectServerApiUrl, selectServerCredentials } from '../../store/settings'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { menuButton, useMenu } from '../menu/menuHelpers'; -import { messages } from './messages'; -import { get } from '../../helpers/rest'; -import { CamerasStorage, Stats, StorageInfo, StorageShortPlace } from '../../helpers/interfaces'; -import { ScrollView } from 'react-native-gesture-handler'; -import { Background } from '../../components/Background'; -import { StorageChart } from './StorageChart'; -import { StorageTable } from './StorageTable'; -import { StyleSheet } from 'react-native'; -import { refreshButton } from '../../helpers/buttonts'; -import { CamerasStorageChart } from './CamerasStorageChart'; -import { CamerasStorageTable } from './CamerasStorageTable'; +import {useIntl} from 'react-intl'; +import {Navigation, NavigationFunctionComponent} from 'react-native-navigation'; +import {Carousel, LoaderScreen, PageControlPosition} from 'react-native-ui-lib'; +import {useAppSelector} from '../../store/store'; +import { + selectServerApiUrl, + selectServerCredentials, +} from '../../store/settings'; +import {useCallback, useEffect, useMemo, useState} from 'react'; +import {menuButton, useMenu} from '../menu/menuHelpers'; +import {messages} from './messages'; +import {get} from '../../helpers/rest'; +import { + CamerasStorage, + Stats, + StorageInfo, + StorageShortPlace, +} from '../../helpers/interfaces'; +import {ScrollView} from 'react-native-gesture-handler'; +import {Background} from '../../components/Background'; +import {StorageChart} from './StorageChart'; +import {StorageTable} from './StorageTable'; +import {StyleSheet} from 'react-native'; +import {refreshButton} from '../../helpers/buttonts'; +import {CamerasStorageChart} from './CamerasStorageChart'; +import {CamerasStorageTable} from './CamerasStorageTable'; const styles = StyleSheet.create({ wrapper: { @@ -25,7 +33,8 @@ const styles = StyleSheet.create({ export const Storage: NavigationFunctionComponent = ({componentId}) => { useMenu(componentId, 'storage'); - const [storage, setStorage] = useState>(); + const [storage, setStorage] = + useState>(); const [camerasStorage, setCamerasStorage] = useState(); const [loading, setLoading] = useState(true); const [page, setPage] = useState(0); @@ -54,43 +63,41 @@ export const Storage: NavigationFunctionComponent = ({componentId}) => { Promise.allSettled([ get(`${apiUrl}/stats`, credentials), get(`${apiUrl}/recordings/storage`, credentials), - ]) - .then(([stats, cameras]) => { - if (stats.status === 'fulfilled') { - const { service} = stats.value; - setStorage({ - clips: service.storage['/media/frigate/clips'], - recordings: service.storage['/media/frigate/recordings'], - cache: service.storage['/tmp/cache'], - shm: service.storage['/dev/shm'], - }); - } - if (cameras.status === 'fulfilled') { - setCamerasStorage(cameras.value); - } - setLoading(false); - }); - }, [apiUrl]); + ]).then(([stats, cameras]) => { + if (stats.status === 'fulfilled') { + const {service} = stats.value; + setStorage({ + clips: service.storage['/media/frigate/clips'], + recordings: service.storage['/media/frigate/recordings'], + cache: service.storage['/tmp/cache'], + shm: service.storage['/dev/shm'], + }); + } + if (cameras.status === 'fulfilled') { + setCamerasStorage(cameras.value); + } + setLoading(false); + }); + }, [apiUrl, credentials]); - return ( - loading || storage === undefined - ? ( - - ) - : ( - - - - - {camerasStorage !== undefined && } - - {page === 0 && } - {camerasStorage && page === 1 && } - - - ) + return loading || storage === undefined ? ( + + ) : ( + + + + + {camerasStorage !== undefined && ( + + )} + + {page === 0 && } + {camerasStorage && page === 1 && ( + + )} + + ); }; diff --git a/views/system/System.tsx b/views/system/System.tsx index dde92e4..de00bea 100644 --- a/views/system/System.tsx +++ b/views/system/System.tsx @@ -94,7 +94,7 @@ export const System: NavigationFunctionComponent = ({componentId}) => { setStats(stats); setLoading(false); }); - }, [apiUrl]); + }, [apiUrl, credentials]); const detectors: DetectorRow[] = useMemo( () =>