Skip to content

Commit

Permalink
feat: initial zustand implementation for settings
Browse files Browse the repository at this point in the history
  • Loading branch information
KestasVenslauskas committed Sep 30, 2024
1 parent c1dd291 commit 88ac3ec
Show file tree
Hide file tree
Showing 18 changed files with 70 additions and 93 deletions.
17 changes: 7 additions & 10 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import Navigation from './app/navigation';

import SettingsProvider from './app/settings/SettingsProvider';
import AppBackground from './app/components/appBackground/AppBackground';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
Expand Down Expand Up @@ -42,15 +41,13 @@ const App: React.FC = () => {

return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<SettingsProvider>
<ThemeProvider>
<AppBackground>
<PlayerProvider>
<Navigation />
</PlayerProvider>
</AppBackground>
</ThemeProvider>
</SettingsProvider>
<ThemeProvider>
<AppBackground>
<PlayerProvider>
<Navigation />
</PlayerProvider>
</AppBackground>
</ThemeProvider>
</SafeAreaProvider>
);
};
Expand Down
6 changes: 0 additions & 6 deletions app/components/appBar/AnimatedAppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,7 @@ const AnimatedAppBar: React.FC<Props> = ({translateY, onBackPress, actions, subH
style={{
flex: 1,
flexDirection: 'row',
// justifyContent: 'space-around',
alignContent: 'space-around',
// backgroundColor: 'rgba(52, 52, 52, 0)',
// backgroundColor: 'red',
width: '100%',
//for animation
height: actionBarHeigh,
}}>
<View
style={{
Expand Down
4 changes: 2 additions & 2 deletions app/components/facebookReactions/FacebookReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import {View, StyleSheet, ViewStyle} from 'react-native';
import {useTheme} from '../../Theme';
import TextComponent from '../text/Text';
import {useSettings} from '../../settings/useSettings';
import {IconFacebook} from '../svg';
import {useSettingsStore} from '../../state/settings';

interface Props {
style?: ViewStyle;
Expand All @@ -12,7 +12,7 @@ interface Props {

const FacebookReactions: React.FC<React.PropsWithChildren<Props>> = ({style, count}) => {
const {colors} = useTheme();
const {textSizeMultiplier} = useSettings();
const textSizeMultiplier = useSettingsStore((state) => state.textSizeMultiplier);

return (
<View style={{...styles.root, ...style}}>
Expand Down
4 changes: 2 additions & 2 deletions app/components/logo/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

import {useSettings} from '../../settings/useSettings';
import {useSelector} from 'react-redux';
import {selectLogo} from '../../redux/selectors';
import {SvgCss} from 'react-native-svg/css';
import {LRTLogo} from '../svg';
import {themeDark, useTheme} from '../../Theme';
import {useSettingsStore} from '../../state/settings';

interface Props {
width?: number;
Expand All @@ -18,7 +18,7 @@ const LogoComponent: React.FC<React.PropsWithChildren<Props>> = ({
height = 32,
useOnlyInternal = false,
}) => {
const {isDarkMode} = useSettings();
const isDarkMode = useSettingsStore((state) => state.isDarkMode);
const {colors} = useTheme();

const logo = useSelector(selectLogo);
Expand Down
4 changes: 2 additions & 2 deletions app/components/photoCount/PhotoCount.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import {View, StyleSheet, ViewStyle} from 'react-native';
import {useSettings} from '../../settings/useSettings';
import {useTheme} from '../../Theme';
import {IconPhotoCamera} from '../svg';
import TextComponent from '../text/Text';
import {useSettingsStore} from '../../state/settings';

interface Props {
style?: ViewStyle;
Expand All @@ -12,7 +12,7 @@ interface Props {

const PhotoCount: React.FC<React.PropsWithChildren<Props>> = ({style, count}) => {
const {colors} = useTheme();
const {textSizeMultiplier} = useSettings();
const textSizeMultiplier = useSettingsStore((state) => state.textSizeMultiplier);

return (
<View style={{...styles.container, backgroundColor: colors.lightGreyBackground, ...style}}>
Expand Down
6 changes: 3 additions & 3 deletions app/components/text/useTextStyle.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {useMemo} from 'react';
import {Falsy, StyleSheet, TextStyle} from 'react-native';
import {useSettings} from '../../settings/useSettings';
import {useTheme} from '../../Theme';
import {TextComponentProps} from './Text';
import {useSettingsStore} from '../../state/settings';
import {useShallow} from 'zustand/react/shallow';

const DEFAULT_FONT_SIZE = 15;

const useTextStyle = (props: TextComponentProps): TextStyle => {
const {colors} = useTheme();
const {textSizeMultiplier} = useSettings();

const textSizeMultiplier = useSettingsStore(useShallow((state) => state.textSizeMultiplier));
const style: TextStyle | Falsy = Array.isArray(props.style)
? StyleSheet.flatten(props.style)
: (props.style as TextStyle);
Expand Down
4 changes: 2 additions & 2 deletions app/components/videoComponent/TheoMediaPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import {useTheme} from '../../Theme';
import usePlayerLanguage from './usePlayerLanguage';
import {EventRegister} from 'react-native-event-listeners';
import FastImage from 'react-native-fast-image';
import {useSettings} from '../../settings/useSettings';
import {VideoTextTrack} from '../../api/Types';
import usePlayerSubtitles from './usePlayerSubtitles';
import Orientation from 'react-native-orientation-locker';
import {useSettingsStore} from '../../state/settings';

export type PlayerAction = 'togglePlay' | 'setFullScreen';

Expand Down Expand Up @@ -128,7 +128,7 @@ const TheoMediaPlayer: React.FC<React.PropsWithChildren<Props>> = ({
const {trackPlay, trackPause, trackBuffer, trackClose, trackComplete, trackSeek} = useMediaTracking();

const {colors} = useTheme();
const {isContinuousPlayEnabled} = useSettings();
const isContinuousPlayEnabled = useSettingsStore((state) => state.isContinuousPlayEnabled);

const {setMediaData, close} = useMediaPlayer();

Expand Down
7 changes: 3 additions & 4 deletions app/navigation/MainStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import {createDrawerNavigator} from '@react-navigation/drawer';
import * as Screens from '../screens';
import {Platform} from 'react-native';
import {Drawer, SearchFilterDrawer} from '../components';
import {useSettings} from '../settings/useSettings';
import {themeDark, themeLight} from '../Theme';
import {ArticlePhotoType, MenuItemPage, SearchFilter} from '../api/Types';
import {NavigatorScreenParams} from '@react-navigation/native';
import SearchContextProvider from '../screens/search/context/SearchContextProvider';
import ChannelContextProvider from '../screens/channel/context/ChannelContextProvider';
import {Article} from '../../Types';
import {useSettingsStore} from '../state/settings';

export type MainStackParamList = {
Home: undefined;
Expand Down Expand Up @@ -112,9 +112,8 @@ const SearchDrawerNavigator: React.FC<React.PropsWithChildren<{}>> = () => {
};

export default () => {
const settings = useSettings();

const theme = settings.isDarkMode ? themeDark : themeLight;
const isDarkMode = useSettingsStore((state) => state.isDarkMode);
const theme = isDarkMode ? themeDark : themeLight;

return (
<Stack.Navigator
Expand Down
15 changes: 4 additions & 11 deletions app/screens/search/SearchScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {DrawerNavigationProp} from '@react-navigation/drawer';
import {Article} from '../../../Types';
import useSearch from './context/useSearch';
import useSearchApi from './useSearchApi';
import {debounce} from 'lodash';
import SearchSuggestions from './SearchSuggestions';
import {defaultSearchFilter} from './context/SearchContext';
import {SearchCategorySuggestion} from '../../api/Types';
Expand All @@ -44,26 +43,20 @@ const SearchScreen: React.FC<React.PropsWithChildren<Props>> = ({navigation, rou
const {loadingState, searchResults, searchSuggestions, callSearchApi} = useSearchApi();
const {colors, strings, dim} = useTheme();

// eslint-disable-next-line react-hooks/exhaustive-deps
const callSearchApiWithDebounce = useCallback(
debounce(callSearchApi, 1000, {
leading: false,
}),
[],
);

useEffect(() => {
const initialQuery = route?.params?.q ?? '';
const initialFilter = route?.params?.filter ?? defaultSearchFilter;

setQuery(initialQuery);
setFilter(initialFilter);

callSearchApi(initialQuery, initialFilter);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
callSearchApiWithDebounce(query, filter);
}, [callSearchApiWithDebounce, filter, query]);
callSearchApi(query, filter);
}, [filter]);

useNavigationAnalytics({
viewId: 'https://www.lrt.lt/paieska',
Expand Down
18 changes: 7 additions & 11 deletions app/screens/settings/SettingsScreenView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,35 @@ import React from 'react';
import {View, StyleSheet} from 'react-native';
import {SettingsToggleButton, Text} from '../../components';
import {SunIcon, MoonIcon} from '../../components/svg';
import {setConfig} from '../../redux/actions';
import {useSelector, useDispatch} from 'react-redux';
import {selectSettings} from '../../redux/selectors';
import {useTheme} from '../../Theme';
import {checkEqual} from '../../util/LodashEqualityCheck';
import SettingsNotifications from './SettingsNotifications';
import {ScrollView} from 'react-native-gesture-handler';
import SettingsSwitch from './SettingsSwitch';
import {SafeAreaView} from 'react-native-safe-area-context';
import {useSettingsStore} from '../../state/settings';

const TEXT_SIZE_NORMAL = 0;
const TEXT_SIZE_LARGE = 2;
const TEXT_SIZE_EXTRA_LARGE = 4;

const SettingsScreenView: React.FC<React.PropsWithChildren<{}>> = () => {
const {strings, colors} = useTheme();
const dispatch = useDispatch();

const config = useSelector(selectSettings, checkEqual);
const settingsStore = useSettingsStore((state) => state);

const handleSetDarkMode = (value: boolean) => {
dispatch(setConfig({...config, isDarkMode: value}));
settingsStore.setIsDarkMode(value);
};

const handleSetContinuousPlayer = (value: boolean) => {
dispatch(setConfig({...config, isContinuousPlayEnabled: value}));
settingsStore.setIsContinuousPlayEnabled(value);
};

const handleSetTextSize = (value: number) => {
dispatch(setConfig({...config, textSizeMultiplier: value}));
settingsStore.setTextSizeMultiplier(value);
};

const {isDarkMode, textSizeMultiplier} = config;
const {isDarkMode, textSizeMultiplier} = settingsStore;

return (
<SafeAreaView style={styles.root} edges={['bottom']}>
Expand Down Expand Up @@ -111,7 +107,7 @@ const SettingsScreenView: React.FC<React.PropsWithChildren<{}>> = () => {
key={'continuous-player'}
title="Nepertraukiamas grotuvas"
onValueChange={handleSetContinuousPlayer}
value={config.isContinuousPlayEnabled}
value={settingsStore.isContinuousPlayEnabled}
cellStyle={{borderBottomWidth: StyleSheet.hairlineWidth}}
/>
</View>
Expand Down
4 changes: 2 additions & 2 deletions app/screens/splash/SplashScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import {View, ActivityIndicator, Button, StyleSheet, StatusBar} from 'react-native';
import {Logo, Text} from '../../components';
import {strings, themeDark, themeLight} from '../../Theme';
import {useSettings} from '../../settings/useSettings';
import useSplashScreenState from './useSplashScreenState';
import {useSettingsStore} from '../../state/settings';

const SplashScreen: React.FC<React.PropsWithChildren<{}>> = () => {
const {isDarkMode} = useSettings();
const isDarkMode = useSettingsStore((state) => state.isDarkMode);
const {colors} = isDarkMode ? themeDark : themeLight;

const state = useSplashScreenState();
Expand Down
4 changes: 2 additions & 2 deletions app/screens/splash/SplashScreenView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import {View, StyleSheet} from 'react-native';

import {themeDark, themeLight} from '../../Theme';
import {useSettings} from '../../settings/useSettings';
import {Logo} from '../../components';
import {useSettingsStore} from '../../state/settings';

const SplashViewComponent: React.FC<React.PropsWithChildren<{}>> = () => {
const {isDarkMode} = useSettings();
const isDarkMode = useSettingsStore((state) => state.isDarkMode);
const colors = isDarkMode ? themeDark.colors : themeLight.colors;

return (
Expand Down
15 changes: 0 additions & 15 deletions app/settings/SettingsContext.ts

This file was deleted.

12 changes: 0 additions & 12 deletions app/settings/SettingsProvider.tsx

This file was deleted.

6 changes: 0 additions & 6 deletions app/settings/useSettings.ts

This file was deleted.

29 changes: 29 additions & 0 deletions app/state/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {create} from 'zustand';
import {persist, createJSONStorage} from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';

export type SettingsStore = {
isDarkMode: boolean;
isContinuousPlayEnabled: boolean;
textSizeMultiplier: number;
setIsDarkMode: (isDarkMode: boolean) => void;
setIsContinuousPlayEnabled: (isContinuousPlayEnabled: boolean) => void;
setTextSizeMultiplier: (textSizeMultiplier: number) => void;
};

export const useSettingsStore = create<SettingsStore>()(
persist(
(set) => ({
isDarkMode: false,
isContinuousPlayEnabled: true,
textSizeMultiplier: 0,
setIsDarkMode: (isDarkMode: boolean) => set({isDarkMode: isDarkMode}),
setIsContinuousPlayEnabled: (isContinuousPlayEnabled: boolean) => set({isContinuousPlayEnabled}),
setTextSizeMultiplier: (textSizeMultiplier: number) => set({textSizeMultiplier}),
}),
{
name: 'settings-store',
storage: createJSONStorage(() => AsyncStorage),
},
),
);
5 changes: 3 additions & 2 deletions app/theme/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, {PropsWithChildren, useMemo} from 'react';
import {AppTheme, themeDark, themeLight} from '../Theme';
import {useSettings} from '../settings/useSettings';
import {ThemeContext} from './ThemeContext';
import {useSettingsStore} from '../state/settings';
import {useShallow} from 'zustand/react/shallow';

type Props = {
forceTheme?: AppTheme;
};

const ThemeProvider: React.FC<PropsWithChildren<Props>> = ({children, forceTheme}) => {
const settings = useSettings();
const settings = useSettingsStore(useShallow((state) => state));
console.log('SETTINGS', settings);
const {isDarkMode} = settings;

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"redux": "^4.2.1",
"redux-devtools-extension": "^2.13.9",
"redux-persist": "^6.0.0",
"redux-saga": "^1.2.3"
"redux-saga": "^1.2.3",
"zustand": "^5.0.0-rc.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down

0 comments on commit 88ac3ec

Please sign in to comment.