Library headers, filters and favorites

This commit is contained in:
Simon Caron
2025-01-01 21:57:46 -05:00
parent bb141cad57
commit e23387a384
9 changed files with 81 additions and 30 deletions

View File

@@ -1,8 +1,10 @@
import { nestedTabPageScreenOptions } from "@/components/stacks/NestedTabPageStack";
import { Stack } from "expo-router";
import { Platform } from "react-native";
import { useTranslation } from "react-i18next";
export default function SearchLayout() {
const { t } = useTranslation();
return (
<Stack>
<Stack.Screen
@@ -10,7 +12,7 @@ export default function SearchLayout() {
options={{
headerShown: true,
headerLargeTitle: true,
headerTitle: "Favorites",
headerTitle: t("favorites.favorites_title"),
headerBlurEffect: "prominent",
headerTransparent: Platform.OS === "ios" ? true : false,
headerShadowVisible: false,

View File

@@ -33,6 +33,7 @@ import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { FlatList, View } from "react-native";
import { useTranslation } from "react-i18next";
const page: React.FC = () => {
const searchParams = useLocalSearchParams();
@@ -45,6 +46,8 @@ const page: React.FC = () => {
ScreenOrientation.Orientation.PORTRAIT_UP
);
const { t } = useTranslation();
const [selectedGenres, setSelectedGenres] = useAtom(genreFilterAtom);
const [selectedYears, setSelectedYears] = useAtom(yearFilterAtom);
const [selectedTags, setSelectedTags] = useAtom(tagsFilterAtom);
@@ -244,7 +247,7 @@ const page: React.FC = () => {
}}
set={setSelectedGenres}
values={selectedGenres}
title="Genres"
title={t("library.headers.genres")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -271,7 +274,7 @@ const page: React.FC = () => {
}}
set={setSelectedYears}
values={selectedYears}
title="Years"
title={t("library.headers.years")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) => item.includes(search)}
/>
@@ -296,7 +299,7 @@ const page: React.FC = () => {
}}
set={setSelectedTags}
values={selectedTags}
title="Tags"
title={t("library.headers.tags")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -314,7 +317,7 @@ const page: React.FC = () => {
queryFn={async () => sortOptions.map((s) => s.key)}
set={setSortBy}
values={sortBy}
title="Sort By"
title={t("library.headers.sort_by")}
renderItemLabel={(item) =>
sortOptions.find((i) => i.key === item)?.value || ""
}
@@ -334,7 +337,7 @@ const page: React.FC = () => {
queryFn={async () => sortOrderOptions.map((s) => s.key)}
set={setSortOrder}
values={sortOrder}
title="Sort Order"
title={t("library.headers.sort_order")}
renderItemLabel={(item) =>
sortOrderOptions.find((i) => i.key === item)?.value || ""
}

View File

@@ -302,7 +302,7 @@ const Page = () => {
}}
set={setSelectedGenres}
values={selectedGenres}
title="Genres"
title={t("library.headers.genres")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -329,7 +329,7 @@ const Page = () => {
}}
set={setSelectedYears}
values={selectedYears}
title="Years"
title={t("library.headers.years")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) => item.includes(search)}
/>
@@ -354,7 +354,7 @@ const Page = () => {
}}
set={setSelectedTags}
values={selectedTags}
title="Tags"
title={t("library.headers.tags")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -372,7 +372,7 @@ const Page = () => {
queryFn={async () => sortOptions.map((s) => s.key)}
set={setSortBy}
values={sortBy}
title="Sort By"
title={t("library.headers.sort_by")}
renderItemLabel={(item) =>
sortOptions.find((i) => i.key === item)?.value || ""
}
@@ -392,7 +392,7 @@ const Page = () => {
queryFn={async () => sortOrderOptions.map((s) => s.key)}
set={setSortOrder}
values={sortOrder}
title="Sort Order"
title={t("library.headers.sort_order")}
renderItemLabel={(item) =>
sortOrderOptions.find((i) => i.key === item)?.value || ""
}

View File

@@ -42,11 +42,11 @@ export default function IndexLayout() {
side={"bottom"}
sideOffset={10}
>
<DropdownMenu.Label>Display</DropdownMenu.Label>
<DropdownMenu.Label>{t("library.options.display")}</DropdownMenu.Label>
<DropdownMenu.Group key="display-group">
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger key="image-style-trigger">
Display
{t("library.options.display")}
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent
alignOffset={-10}
@@ -69,7 +69,7 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="display-title-1">
Row
{t("library.options.row")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
@@ -86,14 +86,14 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="display-title-2">
List
{t("library.options.list")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger key="image-style-trigger">
Image style
{t("library.options.image_style")}
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent
alignOffset={-10}
@@ -116,7 +116,7 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="poster-title">
Poster
{t("library.options.poster")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
@@ -133,7 +133,7 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="cover-title">
Cover
{t("library.options.cover")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
</DropdownMenu.SubContent>
@@ -157,7 +157,7 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="show-titles-title">
Show titles
{t("library.options.show_titles")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
@@ -174,7 +174,7 @@ export default function IndexLayout() {
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle key="show-stats-title">
Show stats
{t("library.options.show_stats")}
</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
</DropdownMenu.Group>

View File

@@ -129,7 +129,7 @@ export default function search() {
if (Platform.OS === "ios")
navigation.setOptions({
headerSearchBarOptions: {
placeholder: "Search...",
placeholder: t("search.search"),
onChangeText: (e: any) => {
router.setParams({ q: "" });
setSearch(e.nativeEvent.text);
@@ -308,7 +308,7 @@ export default function search() {
autoCorrect={false}
returnKeyType="done"
keyboardType="web-search"
placeholder={t("search.search_hint")}
placeholder={t("search.search_here")}
value={search}
onChangeText={(text) => setSearch(text)}
/>

View File

@@ -73,7 +73,7 @@ export default function TabLayout() {
<NativeTabs.Screen
name="(favorites)"
options={{
title: "Favorites",
title: t("tabs.favorites"),
tabBarIcon:
Platform.OS == "android"
? ({ color, focused, size }) =>

View File

@@ -19,6 +19,7 @@ import { StyleSheet, TouchableOpacity, View, ViewProps } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { Button } from "../Button";
import { Input } from "../common/Input";
import { useTranslation } from "react-i18next";
interface Props<T> extends ViewProps {
open: boolean;
@@ -76,6 +77,7 @@ export const FilterSheet = <T,>({
}: Props<T>) => {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ["80%"], []);
const { t } = useTranslation();
const [data, setData] = useState<T[]>([]);
const [offset, setOffset] = useState<number>(0);
@@ -156,7 +158,7 @@ export const FilterSheet = <T,>({
<Text className="mb-2 text-neutral-500">{_data?.length} items</Text>
{showSearch && (
<Input
placeholder="Search..."
placeholder={t("search.search")}
className="my-2"
value={search}
onChangeText={(text) => {

View File

@@ -191,14 +191,35 @@
},
"search": {
"search_title": "Search",
"search_hint": "Search here...",
"search_here": "Search here...",
"search": "Search...",
"no_results_found_for": "No results found for"
},
"library": {
"library_title": "Library",
"no_items_found": "No items found",
"no_results": "No results",
"no_libraries_found": "No libraries found"
"no_libraries_found": "No libraries found",
"options": {
"display": "Display",
"row": "Row",
"list": "List",
"image_style": "Image style",
"poster": "Poster",
"cover": "Cover",
"show_titles": "Show titles",
"show_stats": "Show stats"
},
"headers": {
"genres": "Genres",
"years": "Years",
"sort_by": "Sort By",
"sort_order": "Sort Order",
"tags": "Tags"
}
},
"favorites": {
"favorites_title": "Favorites"
},
"player": {
"error": "Error",
@@ -229,6 +250,7 @@
"home": "Home",
"search": "Search",
"library": "Library",
"custom_links": "Custom Links"
"custom_links": "Custom Links",
"favorites": "Favorites"
}
}

View File

@@ -49,19 +49,41 @@
},
"search": {
"search_title": "Recherche",
"search_hint": "Rechercher ici...",
"search_here": "Rechercher ici...",
"search": "Rechercher...",
"no_results_found_for": "Aucun résultat trouvé pour"
},
"library": {
"library_title": "Bibliothèque",
"no_items_found": "Aucun item trouvé",
"no_results": "Aucun résultat",
"no_libraries_found": "Aucune bibliothèque trouvée"
"no_libraries_found": "Aucune bibliothèque trouvée",
"options": {
"display": "Affichage",
"row": "Rangée",
"list": "Liste",
"image_style": "Style d'image",
"poster": "Affiche",
"cover": "Couverture",
"show_titles": "Afficher les titres",
"show_stats": "Afficher les statistiques"
},
"headers": {
"genres": "Genres",
"years": "Années",
"sort_by": "Trier par",
"sort_order": "Ordre de tri",
"tags": "Tags"
}
},
"favorites": {
"favorites_title": "Favoris"
},
"tabs": {
"home": "Accueil",
"search": "Recherche",
"library": "Bibliothèque",
"custom_links": "Liens personalisés"
"custom_links": "Liens personalisés",
"favorites": "Favoris"
}
}