fix(performer): tag chips → in-place horizontal filter selector

Follow-up to 1a4bf258 feedback (a627637b + 0264a3ff): the flexWrap chip list ate
too much vertical space and tapping navigated away to TagScenes. Rework: single-row
horizontal scroll of toggle-chips that filter the performer's scenes IN-PLACE
(performer_ids + tags in one listScenes query, no navigation). Selected chip is
highlighted with a ✕ affordance; tap again clears. One line tall instead of N rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jtrzupek 2026-06-09 09:25:02 +02:00
parent 576a424615
commit 7f36865b5a

View file

@ -13,6 +13,7 @@ import {
Alert, Alert,
FlatList, FlatList,
Pressable, Pressable,
ScrollView,
StyleSheet, StyleSheet,
Text, Text,
View, View,
@ -135,11 +136,16 @@ export function PerformerScenesScreen() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [navigation, name, isFavorite, addMutation.isPending, removeMutation.isPending]); }, [navigation, name, isFavorite, addMutation.isPending, removeMutation.isPending]);
// Filtr tagu IN-PLACE (bug-report 0264a3ff: wybór tagu ma filtrować sceny tej
// aktorki w tym widoku, nie nawigować do osobnego ekranu). null = bez filtra.
const [selectedTag, setSelectedTag] = React.useState<{ slug: string; name: string } | null>(null);
const scenesQuery = useQuery({ const scenesQuery = useQuery({
queryKey: ['performer-scenes', id], queryKey: ['performer-scenes', id, selectedTag?.slug ?? null],
queryFn: () => queryFn: () =>
client.listScenes({ client.listScenes({
performer_ids: [id], performer_ids: [id],
tags: selectedTag ? [selectedTag.slug] : undefined,
sort: 'release_date', sort: 'release_date',
per_page: 200, per_page: 200,
// Sceny TPDB/StashDB bez tube-linków nie są usable — zawsze filtrujemy. // Sceny TPDB/StashDB bez tube-linków nie są usable — zawsze filtrujemy.
@ -270,21 +276,31 @@ export function PerformerScenesScreen() {
</Pressable> </Pressable>
</View> </View>
{tab === 'scenes' && !!tagsQuery.data?.items.length && ( {tab === 'scenes' && !!tagsQuery.data?.items.length && (
<View style={styles.tagRow}> <ScrollView
{tagsQuery.data.items.map((t) => ( horizontal
<Pressable showsHorizontalScrollIndicator={false}
key={t.id} contentContainerStyle={styles.tagRow}
style={styles.tagChip} >
onPress={() => {tagsQuery.data.items.map((t) => {
navigation.push('TagScenes', { slug: t.slug, name: t.name }) const active = selectedTag?.slug === t.slug;
} return (
> <Pressable
<Text style={styles.tagChipText} numberOfLines={1}> key={t.id}
{t.name} style={[styles.tagChip, active && styles.tagChipActive]}
</Text> onPress={() =>
</Pressable> setSelectedTag(active ? null : { slug: t.slug, name: t.name })
))} }
</View> >
<Text
style={[styles.tagChipText, active && styles.tagChipTextActive]}
numberOfLines={1}
>
{active ? `${t.name}` : t.name}
</Text>
</Pressable>
);
})}
</ScrollView>
)} )}
</View> </View>
} }
@ -418,10 +434,10 @@ const styles = StyleSheet.create({
actionBtnTextPrimary: { color: theme.accent, fontWeight: '700', fontSize: 12 }, actionBtnTextPrimary: { color: theme.accent, fontWeight: '700', fontSize: 12 },
tagRow: { tagRow: {
flexDirection: 'row', flexDirection: 'row',
flexWrap: 'wrap',
gap: 6, gap: 6,
marginHorizontal: 4, paddingHorizontal: 4,
marginBottom: 10, paddingBottom: 10,
alignItems: 'center',
}, },
tagChip: { tagChip: {
backgroundColor: theme.card, backgroundColor: theme.card,
@ -430,9 +446,11 @@ const styles = StyleSheet.create({
borderRadius: 14, borderRadius: 14,
paddingVertical: 4, paddingVertical: 4,
paddingHorizontal: 10, paddingHorizontal: 10,
maxWidth: 160, maxWidth: 200,
}, },
tagChipActive: { backgroundColor: theme.accent, borderColor: theme.accent },
tagChipText: { color: theme.muted, fontSize: 12, fontWeight: '600' }, tagChipText: { color: theme.muted, fontSize: 12, fontWeight: '600' },
tagChipTextActive: { color: theme.fg, fontWeight: '700' },
tabRow: { flexDirection: 'row', gap: 8, marginBottom: 8 }, tabRow: { flexDirection: 'row', gap: 8, marginBottom: 8 },
tabBtn: { tabBtn: {
flex: 1, flex: 1,