forked from Ninjalama/streamyfin_mirror
Compare commits
1 Commits
v0.28.0
...
feat/focus
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85ee3ea47d |
@@ -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<HeaderSearchBarRef>(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: () =>
|
||||
|
||||
@@ -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() {
|
||||
}}
|
||||
/>
|
||||
<NativeTabs.Screen
|
||||
listeners={({ navigation }) => ({
|
||||
tabPress: (e) => {
|
||||
eventBus.emit("searchTabPressed");
|
||||
},
|
||||
})}
|
||||
name="(search)"
|
||||
options={{
|
||||
title: t("tabs.search"),
|
||||
@@ -137,4 +143,4 @@ export default function TabLayout() {
|
||||
</NativeTabs>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
26
utils/eventBus.ts
Normal file
26
utils/eventBus.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
type Listener<T = void> = (data?: T) => void;
|
||||
|
||||
class EventBus {
|
||||
private listeners: Record<string, Listener<any>[]> = {};
|
||||
|
||||
on<T = void>(event: string, callback: Listener<T>): () => void {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(callback);
|
||||
return () => this.off(event, callback);
|
||||
}
|
||||
|
||||
off<T = void>(event: string, callback: Listener<T>): void {
|
||||
if (!this.listeners[event]) return;
|
||||
this.listeners[event] = this.listeners[event].filter(
|
||||
(fn) => fn !== callback
|
||||
);
|
||||
}
|
||||
|
||||
emit<T = void>(event: string, data?: T): void {
|
||||
this.listeners[event]?.forEach((callback) => callback(data));
|
||||
}
|
||||
}
|
||||
|
||||
export const eventBus = new EventBus();
|
||||
Reference in New Issue
Block a user