import { FontAwesome, Ionicons } from "@expo/vector-icons"; import type { BottomSheetModal } from "@gorhom/bottom-sheet"; import { useQuery } from "@tanstack/react-query"; import { useCallback, useRef, useState } from "react"; import { TouchableOpacity, View, type ViewProps } from "react-native"; import { Text } from "@/components/common/Text"; import { FilterSheet } from "./FilterSheet"; import { useFilterSheet } from "./FilterSheetProvider"; interface FilterButtonProps extends ViewProps { id: string; disableSearch?: boolean; queryKey: string; values: T[]; title: string; set: (value: T[]) => void; queryFn: (params: any) => Promise; searchFilter?: (item: T, query: string) => boolean; renderItemLabel: (item: T) => React.ReactNode; multiple?: boolean; icon?: "filter" | "sort"; } export const FilterButton = ({ id, queryFn, queryKey, set, values, // selected values title, renderItemLabel, searchFilter, disableSearch = false, multiple = false, icon = "filter", ...props }: FilterButtonProps) => { // When a FilterSheetProvider is present (library / collections), all buttons // share one sheet so two can never stack. Outside a provider (e.g. logs, // discover), fall back to this button's own standalone sheet. const shared = useFilterSheet(); const { data: filters, isLoading } = useQuery({ queryKey: ["filters", title, queryKey, id], queryFn, staleTime: 0, enabled: !!id && !!queryFn && !!queryKey, }); // Standalone-mode state (unused in shared mode). const [open, setOpen] = useState(false); const sheetModalRef = useRef(null); const onButtonPress = useCallback(() => { if (shared) { shared.openFilter({ key: `${id}:${queryKey}`, id, queryKey, queryFn, title, values: values as unknown[], set: set as (value: unknown[]) => void, renderItemLabel: renderItemLabel as (item: unknown) => React.ReactNode, searchFilter: searchFilter as | ((item: unknown, query: string) => boolean) | undefined, disableSearch, multiple, }); return; } // present() must run from the press handler: from an effect after a state // update it silently no-ops on the new architecture and the sheet never // appears. setOpen(true); sheetModalRef.current?.present(); }, [ shared, id, queryKey, queryFn, title, values, set, renderItemLabel, searchFilter, disableSearch, multiple, ]); return ( <> 0 ? "bg-purple-600 border border-purple-700" : "bg-neutral-900 border border-neutral-900" } ${filters?.length === 0 && "opacity-50"} `} {...props} > 0 ? "text-purple-100" : "text-neutral-100"} text-xs font-semibold`} > {title} {icon === "filter" ? ( ) : ( )} {!shared && ( title={title} open={open} setOpen={setOpen} modalRef={sheetModalRef} loading={isLoading} data={filters} values={values} set={set} renderItemLabel={renderItemLabel} searchFilter={searchFilter} disableSearch={disableSearch} multiple={multiple} /> )} ); };