From 697476845740a421948a22c322bd878605951969 Mon Sep 17 00:00:00 2001 From: Saif Shaikh Date: Fri, 9 Jan 2026 23:46:31 -0800 Subject: [PATCH] patch: bottom sheet back button behavior, SettingsScreen.tsx refactor --- .../home/ContinueWatchingSection.tsx | 4 + .../search/DiscoverBottomSheets.tsx | 11 +- src/constants/locales.ts | 9 + src/hooks/useBottomSheetBackHandler.ts | 41 ++++ src/screens/SettingsScreen.tsx | 218 +++--------------- 5 files changed, 97 insertions(+), 186 deletions(-) create mode 100644 src/constants/locales.ts create mode 100644 src/hooks/useBottomSheetBackHandler.ts diff --git a/src/components/home/ContinueWatchingSection.tsx b/src/components/home/ContinueWatchingSection.tsx index 60cdc66..4328c26 100644 --- a/src/components/home/ContinueWatchingSection.tsx +++ b/src/components/home/ContinueWatchingSection.tsx @@ -31,6 +31,7 @@ import { TraktService } from '../../services/traktService'; import { stremioService } from '../../services/stremioService'; import { streamCacheService } from '../../services/streamCacheService'; import { useSettings } from '../../hooks/useSettings'; +import { useBottomSheetBackHandler } from '../../hooks/useBottomSheetBackHandler'; // Define interface for continue watching items @@ -122,6 +123,7 @@ const ContinueWatchingSection = React.forwardRef((props, re // Bottom sheet for item actions const actionSheetRef = useRef(null); + const { onChange, onDismiss } = useBottomSheetBackHandler(); const [selectedItem, setSelectedItem] = useState(null); // Enhanced responsive sizing for tablets and TV screens @@ -1620,7 +1622,9 @@ const ContinueWatchingSection = React.forwardRef((props, re }} onDismiss={() => { setSelectedItem(null); + onDismiss(actionSheetRef); }} + onChange={onChange(actionSheetRef)} > {selectedItem && ( diff --git a/src/components/search/DiscoverBottomSheets.tsx b/src/components/search/DiscoverBottomSheets.tsx index 8809976..87d17d0 100644 --- a/src/components/search/DiscoverBottomSheets.tsx +++ b/src/components/search/DiscoverBottomSheets.tsx @@ -1,10 +1,11 @@ -import React, { useMemo, useCallback, forwardRef, RefObject } from 'react'; +import React, { useMemo, useCallback, forwardRef, RefObject, useState } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import { useTranslation } from 'react-i18next'; import { MaterialIcons } from '@expo/vector-icons'; import { BottomSheetModal, BottomSheetScrollView, BottomSheetBackdrop } from '@gorhom/bottom-sheet'; import { DiscoverCatalog } from './searchUtils'; import { searchStyles as styles } from './searchStyles'; +import { useBottomSheetBackHandler } from '../../hooks/useBottomSheetBackHandler'; interface DiscoverBottomSheetsProps { typeSheetRef: RefObject; @@ -40,6 +41,8 @@ export const DiscoverBottomSheets = ({ const typeSnapPoints = useMemo(() => ['25%'], []); const catalogSnapPoints = useMemo(() => ['50%'], []); const genreSnapPoints = useMemo(() => ['50%'], []); + const [activeBottomSheetRef, setActiveBottomSheetRef] = useState(null); + const {onDismiss, onChange} = useBottomSheetBackHandler(); const renderBackdrop = useCallback( (props: any) => ( @@ -71,6 +74,8 @@ export const DiscoverBottomSheets = ({ handleIndicatorStyle={{ backgroundColor: currentTheme.colors.mediumGray, }} + onDismiss={onDismiss(catalogSheetRef)} + onChange={onChange(catalogSheetRef)} > @@ -130,6 +135,8 @@ export const DiscoverBottomSheets = ({ handleIndicatorStyle={{ backgroundColor: currentTheme.colors.mediumGray, }} + onDismiss={onDismiss(genreSheetRef)} + onChange={onChange(genreSheetRef)} > @@ -203,6 +210,8 @@ export const DiscoverBottomSheets = ({ handleIndicatorStyle={{ backgroundColor: currentTheme.colors.mediumGray, }} + onDismiss={onDismiss(typeSheetRef)} + onChange={onChange(typeSheetRef)} > diff --git a/src/constants/locales.ts b/src/constants/locales.ts new file mode 100644 index 0000000..ca0e5b5 --- /dev/null +++ b/src/constants/locales.ts @@ -0,0 +1,9 @@ +export const LOCALES = [ + { code: 'en', key: 'english' }, + { code: 'pt-BR', key: 'portuguese_br' }, + { code: 'pt-PT', key: 'portuguese_pt' }, + { code: 'de', key: 'german' }, + { code: 'ar', key: 'arabic' }, + { code: 'fr', key: 'french' }, + { code: 'it', key: 'italian' } +]; \ No newline at end of file diff --git a/src/hooks/useBottomSheetBackHandler.ts b/src/hooks/useBottomSheetBackHandler.ts new file mode 100644 index 0000000..48ecf1e --- /dev/null +++ b/src/hooks/useBottomSheetBackHandler.ts @@ -0,0 +1,41 @@ +import { useEffect, useRef } from 'react'; + +import { BackHandler } from 'react-native'; +import { BottomSheetModal } from '@gorhom/bottom-sheet'; + +export function useBottomSheetBackHandler() { + const activeSheetRef = + useRef | null>(null); + + useEffect(() => { + const sub = BackHandler.addEventListener( + 'hardwareBackPress', + () => { + if (activeSheetRef.current?.current) { + activeSheetRef.current.current.dismiss(); + return true; + } + return false; + } + ); + + return () => sub.remove(); + }, []); + + const onChange = + (ref: React.RefObject) => + (index: number) => { + if (index >= 0) { + activeSheetRef.current = ref; + } + }; + + const onDismiss = + (ref: React.RefObject) => () => { + if (activeSheetRef.current === ref) { + activeSheetRef.current = null; + } + }; + + return { onChange, onDismiss }; +} \ No newline at end of file diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 6cebc70..1a491b1 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -45,6 +45,8 @@ import { AppearanceSettingsContent } from './settings/AppearanceSettingsScreen'; import { IntegrationsSettingsContent } from './settings/IntegrationsSettingsScreen'; import { AboutSettingsContent, AboutFooter } from './settings/AboutSettingsScreen'; import { SettingsCard, SettingItem, ChevronRight, CustomSwitch } from './settings/SettingsComponents'; +import { useBottomSheetBackHandler } from '../hooks/useBottomSheetBackHandler'; +import { LOCALES } from '../constants/locales'; const { width } = Dimensions.get('window'); const isTablet = width >= 768; @@ -151,6 +153,7 @@ const SettingsScreen: React.FC = () => { const { settings, updateSetting } = useSettings(); const [hasUpdateBadge, setHasUpdateBadge] = useState(false); const languageSheetRef = useRef(null); + const { onChange, onDismiss } = useBottomSheetBackHandler(); const insets = useSafeAreaInsets(); // Render backdrop for bottom sheet @@ -626,15 +629,7 @@ const SettingsScreen: React.FC = () => { l.code === i18n.language)?.key}`) } icon="globe" renderControl={() => } @@ -870,12 +865,14 @@ const SettingsScreen: React.FC = () => { backgroundColor: currentTheme.colors.mediumGray, width: 40, }} + onChange={onChange(languageSheetRef)} + onDismiss={onDismiss(languageSheetRef)} > {t('settings.select_language')} - languageSheetRef.current?.close()}> + languageSheetRef.current?.dismiss()}> @@ -883,181 +880,32 @@ const SettingsScreen: React.FC = () => { style={{ backgroundColor: currentTheme.colors.darkGray || '#0A0C0C' }} contentContainerStyle={[styles.bottomSheetContent, { paddingBottom: insets.bottom + 16 }]} > - { - i18n.changeLanguage('en'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.english')} - - {i18n.language === 'en' && ( - - )} - - - { - i18n.changeLanguage('pt-BR'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.portuguese_br')} - - {i18n.language === 'pt-BR' && ( - - )} - - - { - i18n.changeLanguage('pt-PT'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.portuguese_pt')} - - {i18n.language === 'pt-PT' && ( - - )} - - - { - i18n.changeLanguage('de'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.german')} - - {i18n.language === 'de' && ( - - )} - - - { - i18n.changeLanguage('ar'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.arabic')} - - {i18n.language === 'ar' && ( - - )} - - - { - i18n.changeLanguage('es'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.spanish')} - - {i18n.language === 'es' && ( - - )} - - - { - i18n.changeLanguage('fr'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.french')} - - {i18n.language === 'fr' && ( - - )} - - - { - i18n.changeLanguage('it'); - languageSheetRef.current?.close(); - }} - > - - {t('settings.italian')} - - {i18n.language === 'it' && ( - - )} - + { + LOCALES.sort((a,b) => a.key.localeCompare(b.key)).map(l => + { + i18n.changeLanguage(l.code); + languageSheetRef.current?.dismiss(); + }} + > + + {t(`settings.${l.key}`)} + + {i18n.language === l.code && ( + + )} + + ) + }