diff --git a/app/(auth)/(tabs)/(search)/index.tsx b/app/(auth)/(tabs)/(search)/index.tsx index 11a38636..6d1ac344 100644 --- a/app/(auth)/(tabs)/(search)/index.tsx +++ b/app/(auth)/(tabs)/(search)/index.tsx @@ -26,12 +26,14 @@ import React, { useEffect, useLayoutEffect, useMemo, + useRef, useState, } from "react"; import { Platform, ScrollView, TouchableOpacity, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useDebounce } from "use-debounce"; import { useTranslation } from "react-i18next"; +import { eventBus } from "@/utils/eventBus"; type SearchType = "Library" | "Discover"; @@ -120,21 +122,44 @@ export default function search() { [api, searchEngine, settings] ); + type HeaderSearchBarRef = { + focus: () => void; + blur: () => void; + setText: (text: string) => void; + clearText: () => void; + cancelSearch: () => void; + }; + + const searchBarRef = useRef(null); const navigation = useNavigation(); useLayoutEffect(() => { navigation.setOptions({ headerSearchBarOptions: { + ref: searchBarRef, placeholder: t("search.search"), onChangeText: (e: any) => { router.setParams({ q: "" }); setSearch(e.nativeEvent.text); }, hideWhenScrolling: false, - autoFocus: true, + autoFocus: false, }, }); }, [navigation]); + useEffect(() => { + const unsubscribe = eventBus.on("searchTabPressed", () => { + // Screen not actuve + if (!searchBarRef.current) return; + // Screen is active, focus search bar + searchBarRef.current?.focus(); + }); + + return () => { + unsubscribe(); + }; + }, []); + const { data: movies, isFetching: l1 } = useQuery({ queryKey: ["search", "movies", debouncedSearch], queryFn: () => diff --git a/app/(auth)/(tabs)/_layout.tsx b/app/(auth)/(tabs)/_layout.tsx index 1b789c62..6d097240 100644 --- a/app/(auth)/(tabs)/_layout.tsx +++ b/app/(auth)/(tabs)/_layout.tsx @@ -20,6 +20,7 @@ import type { TabNavigationState, } from "@react-navigation/native"; import { SystemBars } from "react-native-edge-to-edge"; +import { eventBus } from "@/utils/eventBus"; export const NativeTabs = withLayoutContext< BottomTabNavigationOptions, @@ -76,6 +77,11 @@ export default function TabLayout() { }} /> ({ + tabPress: (e) => { + eventBus.emit("searchTabPressed"); + }, + })} name="(search)" options={{ title: t("tabs.search"), @@ -137,4 +143,4 @@ export default function TabLayout() { ); -} \ No newline at end of file +} diff --git a/utils/eventBus.ts b/utils/eventBus.ts new file mode 100644 index 00000000..4df6b19f --- /dev/null +++ b/utils/eventBus.ts @@ -0,0 +1,26 @@ +type Listener = (data?: T) => void; + +class EventBus { + private listeners: Record[]> = {}; + + on(event: string, callback: Listener): () => void { + if (!this.listeners[event]) { + this.listeners[event] = []; + } + this.listeners[event].push(callback); + return () => this.off(event, callback); + } + + off(event: string, callback: Listener): void { + if (!this.listeners[event]) return; + this.listeners[event] = this.listeners[event].filter( + (fn) => fn !== callback + ); + } + + emit(event: string, data?: T): void { + this.listeners[event]?.forEach((callback) => callback(data)); + } +} + +export const eventBus = new EventBus();