Enhance Search tab behavior with event emitter

Added DeviceEventEmitter to handle search input focus on tab press for Search tab.
This commit is contained in:
AdityasahuX07 2026-01-06 17:08:42 +05:30 committed by GitHub
parent 56df30a4da
commit 066bf6f15d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,7 +2,7 @@ import React, { useEffect, useRef, useMemo, useState } from 'react';
import { NavigationContainer, DefaultTheme as NavigationDefaultTheme, DarkTheme as NavigationDarkTheme, Theme, NavigationProp } from '@react-navigation/native'; import { NavigationContainer, DefaultTheme as NavigationDefaultTheme, DarkTheme as NavigationDarkTheme, Theme, NavigationProp } from '@react-navigation/native';
import { createNativeStackNavigator, NativeStackNavigationOptions, NativeStackNavigationProp } from '@react-navigation/native-stack'; import { createNativeStackNavigator, NativeStackNavigationOptions, NativeStackNavigationProp } from '@react-navigation/native-stack';
import { createBottomTabNavigator, BottomTabNavigationProp } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator, BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
import { useColorScheme, Platform, Animated, StatusBar, TouchableOpacity, View, Text, AppState, Easing, Dimensions } from 'react-native'; import { useColorScheme, Platform, Animated, StatusBar, TouchableOpacity, View, Text, AppState, Easing, Dimensions, DeviceEventEmitter } from 'react-native';
import { mmkvStorage } from '../services/mmkvStorage'; import { mmkvStorage } from '../services/mmkvStorage';
import { PaperProvider, MD3DarkTheme, MD3LightTheme, adaptNavigationTheme } from 'react-native-paper'; import { PaperProvider, MD3DarkTheme, MD3LightTheme, adaptNavigationTheme } from 'react-native-paper';
import type { MD3Theme } from 'react-native-paper'; import type { MD3Theme } from 'react-native-paper';
@ -71,6 +71,7 @@ import BackupScreen from '../screens/BackupScreen';
import ContinueWatchingSettingsScreen from '../screens/ContinueWatchingSettingsScreen'; import ContinueWatchingSettingsScreen from '../screens/ContinueWatchingSettingsScreen';
import ContributorsScreen from '../screens/ContributorsScreen'; import ContributorsScreen from '../screens/ContributorsScreen';
import DebridIntegrationScreen from '../screens/DebridIntegrationScreen'; import DebridIntegrationScreen from '../screens/DebridIntegrationScreen';
import { import {
ContentDiscoverySettingsScreen, ContentDiscoverySettingsScreen,
AppearanceSettingsScreen, AppearanceSettingsScreen,
@ -689,15 +690,32 @@ const MainTabs = () => {
const isFocused = props.state.index === index; const isFocused = props.state.index === index;
const onPress = () => { const onPress = () => {
// Create a synthetic event object we can modify
const syntheticEvent = {
type: 'tabPress',
target: route.key,
canPreventDefault: true,
defaultPrevented: false,
preventDefault: () => {
syntheticEvent.defaultPrevented = true;
}
};
const event = props.navigation.emit({ const event = props.navigation.emit({
type: 'tabPress', type: 'tabPress',
target: route.key, target: route.key,
canPreventDefault: true, canPreventDefault: true,
}); });
if (isFocused) { if (isFocused) {
// Same tab pressed - emit scroll to top if (route.name === 'Search') {
emitScrollToTop(route.name); // Send the signal to SearchScreen.tsx to focus input
} else if (!event.defaultPrevented) { DeviceEventEmitter.emit('FOCUS_SEARCH_INPUT');
syntheticEvent.preventDefault(); // Prevent scroll-to-top
} else {
emitScrollToTop(route.name);
}
} else if (!syntheticEvent.defaultPrevented && !event.defaultPrevented) {
props.navigation.navigate(route.name); props.navigation.navigate(route.name);
} }
}; };
@ -806,6 +824,14 @@ const MainTabs = () => {
const isFocused = props.state.index === index; const isFocused = props.state.index === index;
const onPress = () => { const onPress = () => {
// For Search tab, we need to handle this specially
if (isFocused && route.name === 'Search') {
// Focus search input instead of scrolling to top
DeviceEventEmitter.emit('FOCUS_SEARCH_INPUT');
// Return early to prevent navigation and scroll-to-top
return;
}
const event = props.navigation.emit({ const event = props.navigation.emit({
type: 'tabPress', type: 'tabPress',
target: route.key, target: route.key,
@ -813,7 +839,7 @@ const MainTabs = () => {
}); });
if (isFocused) { if (isFocused) {
// Same tab pressed - emit scroll to top // For other tabs, scroll to top
emitScrollToTop(route.name); emitScrollToTop(route.name);
} else if (!event.defaultPrevented) { } else if (!event.defaultPrevented) {
props.navigation.navigate(route.name); props.navigation.navigate(route.name);
@ -952,7 +978,10 @@ const MainTabs = () => {
listeners={({ navigation }: { navigation: any }) => ({ listeners={({ navigation }: { navigation: any }) => ({
tabPress: (e: any) => { tabPress: (e: any) => {
if (navigation.isFocused()) { if (navigation.isFocused()) {
emitScrollToTop('Search'); // Focus search input instead of scrolling to top
DeviceEventEmitter.emit('FOCUS_SEARCH_INPUT');
// Don't try to access preventDefault on native iOS tabs
// Just emit the event and let SearchScreen handle it
} }
}, },
})} })}
@ -1059,6 +1088,13 @@ const MainTabs = () => {
), ),
freezeOnBlur: true, freezeOnBlur: true,
}} }}
listeners={({ navigation }: any) => ({
tabPress: (e: any) => {
if (navigation.isFocused()) {
emitScrollToTop('Home');
}
},
})}
/> />
<Tab.Screen <Tab.Screen
name="Library" name="Library"
@ -1069,6 +1105,13 @@ const MainTabs = () => {
<MaterialCommunityIcons name={focused ? 'heart' : 'heart-outline'} size={size} color={color} /> <MaterialCommunityIcons name={focused ? 'heart' : 'heart-outline'} size={size} color={color} />
), ),
}} }}
listeners={({ navigation }: any) => ({
tabPress: (e: any) => {
if (navigation.isFocused()) {
emitScrollToTop('Library');
}
},
})}
/> />
<Tab.Screen <Tab.Screen
name="Search" name="Search"
@ -1079,6 +1122,16 @@ const MainTabs = () => {
<MaterialCommunityIcons name={'magnify'} size={size} color={color} /> <MaterialCommunityIcons name={'magnify'} size={size} color={color} />
), ),
}} }}
listeners={({ navigation }: any) => ({
tabPress: (e: any) => {
if (navigation.isFocused()) {
// Focus search input instead of scrolling to top
DeviceEventEmitter.emit('FOCUS_SEARCH_INPUT');
// Simply return to prevent navigation
return;
}
},
})}
/> />
{appSettings?.enableDownloads !== false && ( {appSettings?.enableDownloads !== false && (
<Tab.Screen <Tab.Screen
@ -1090,6 +1143,13 @@ const MainTabs = () => {
<MaterialCommunityIcons name={focused ? 'download' : 'download-outline'} size={size} color={color} /> <MaterialCommunityIcons name={focused ? 'download' : 'download-outline'} size={size} color={color} />
), ),
}} }}
listeners={({ navigation }: any) => ({
tabPress: (e: any) => {
if (navigation.isFocused()) {
emitScrollToTop('Downloads');
}
},
})}
/> />
)} )}
<Tab.Screen <Tab.Screen
@ -1101,6 +1161,13 @@ const MainTabs = () => {
<MaterialCommunityIcons name={focused ? 'cog' : 'cog-outline'} size={size} color={color} /> <MaterialCommunityIcons name={focused ? 'cog' : 'cog-outline'} size={size} color={color} />
), ),
}} }}
listeners={({ navigation }: any) => ({
tabPress: (e: any) => {
if (navigation.isFocused()) {
emitScrollToTop('Settings');
}
},
})}
/> />
</Tab.Navigator> </Tab.Navigator>
</View> </View>
@ -1771,4 +1838,4 @@ const AppNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootStack
</PostHogProvider> </PostHogProvider>
); );
export default AppNavigator; export default AppNavigator;