Fix combobox select not changing (#1354)

This commit is contained in:
Zoe Roux 2026-03-11 22:21:22 +01:00 committed by GitHub
commit 5d69791021
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 28 deletions

View File

@ -158,6 +158,7 @@ export const ComboBox = <Data,>({
</View>
<LegendList
data={data}
extraData={selectedKeys}
estimatedItemSize={48}
keyExtractor={(item: Data | null, index: number) =>
item ? getKey(item) : `placeholder-${index}`

View File

@ -4,7 +4,7 @@ import ExpandMore from "@material-symbols/svg-400/rounded/keyboard_arrow_down-fi
import SearchIcon from "@material-symbols/svg-400/rounded/search-fill.svg";
import * as Popover from "@radix-ui/react-popover";
import { useMemo, useRef, useState } from "react";
import { Platform, View } from "react-native";
import { Platform, Pressable, View } from "react-native";
import { useInfiniteFetch } from "~/query/query";
import { cn } from "~/utils";
import type { ComboBoxProps } from "./combobox";
@ -117,6 +117,7 @@ export const ComboBox = <Data,>({
</div>
<LegendList
data={data}
extraData={selectedKeys}
estimatedItemSize={40}
keyExtractor={(item: Data | null, index: number) =>
item ? getKey(item) : `placeholder-${index}`
@ -168,14 +169,11 @@ const ComboBoxItem = ({
onSelect: () => void;
}) => {
return (
<button
type="button"
onClick={onSelect}
<Pressable
onPress={onSelect}
className={cn(
"flex w-full select-none items-center rounded py-2 pr-6 pl-8 outline-0",
"font-sans text-slate-600 dark:text-slate-400",
"hover:bg-accent hover:text-slate-200",
"group",
"flex w-full select-none rounded py-2 pr-6 pl-8 outline-0",
"group focus-within:bg-accent hover:bg-accent",
)}
>
{selected && (
@ -187,8 +185,10 @@ const ComboBoxItem = ({
)}
/>
)}
<span className="text-left group-hover:text-slate-200">{label}</span>
</button>
<P className="group-focus-within:text-slate-200 group-hover:text-slate-200">
{label}
</P>
</Pressable>
);
};

View File

@ -25,17 +25,15 @@ export const useEditLinks = (
compute: ({
video,
entries,
guess = false,
}: {
video: string;
entries: Omit<Entry, "href" | "progress" | "videos">[];
guess?: boolean;
}) => ({
body: [
{
id: video,
for: entries.map((x) =>
guess && x.kind === "episode"
x.kind === "episode" && !x.slug
? {
serie: slug,
// @ts-expect-error: idk why it couldn't match x as an episode
@ -93,7 +91,11 @@ export const VideosModal = () => {
layout={{ layout: "vertical", gap: 8, numColumns: 1, size: 48 }}
Render={({ item }) => (
<PathItem
item={item}
id={item.id}
path={item.path}
entries={item.entries as Entry[]}
guessTitle={item.guess.title}
guesses={item.guess.episodes}
serieSlug={slug}
addTitle={addTitle}
editLinks={editLinks}

View File

@ -1,31 +1,39 @@
import { useRecyclingState } from "@legendapp/list";
import Check from "@material-symbols/svg-400/rounded/check-fill.svg";
import Close from "@material-symbols/svg-400/rounded/close-fill.svg";
import Question from "@material-symbols/svg-400/rounded/question_mark-fill.svg";
import { useTranslation } from "react-i18next";
import { View } from "react-native";
import { entryDisplayNumber } from "~/components/entries";
import { Entry, type FullVideo } from "~/models";
import { Entry } from "~/models";
import { ComboBox, IconButton, P, Skeleton, tooltip } from "~/primitives";
import { uniqBy } from "~/utils";
import type { useEditLinks } from ".";
export const PathItem = ({
item,
id,
path,
entries,
guessTitle,
guesses,
serieSlug,
addTitle,
editLinks,
}: {
item: FullVideo;
id: string;
guessTitle: string;
path: string;
entries: Entry[];
guesses: { season: number | null; episode: number }[];
serieSlug: string;
addTitle: (title: string) => void;
editLinks: ReturnType<typeof useEditLinks>;
}) => {
const { t } = useTranslation();
const saved = item.entries.length;
const [saved] = useRecyclingState(entries.length);
const guess = !saved
? uniqBy(
item.guess.episodes.map(
guesses.map(
(x) =>
({
kind: "episode",
@ -47,8 +55,8 @@ export const PathItem = ({
<IconButton
icon={Close}
onPress={async () => {
addTitle(item.guess.title);
await editLinks({ video: item.id, entries: [] });
addTitle(guessTitle);
await editLinks({ video: id, entries: [] });
}}
{...tooltip(t("videos-map.delete"))}
/>
@ -57,9 +65,8 @@ export const PathItem = ({
icon={Check}
onPress={async () => {
await editLinks({
video: item.id,
video: id,
entries: guess,
guess: true,
});
}}
{...tooltip(t("videos-map.validate"))}
@ -71,13 +78,13 @@ export const PathItem = ({
{...tooltip(t("videos-map.no-guess"))}
/>
)}
<P className="flex-1 flex-wrap">{item.path}</P>
<P className="flex-1 flex-wrap">{path}</P>
</View>
<ComboBox
multiple
label={t("videos-map.none")}
searchPlaceholder={t("navbar.search")}
values={saved ? item.entries : guess}
values={saved ? entries : guess}
query={(q) => ({
parser: Entry,
path: ["api", "series", serieSlug, "entries"],
@ -97,9 +104,9 @@ export const PathItem = ({
getLabel={(x) => `${entryDisplayNumber(x)} - ${x.name}`}
getSmallLabel={entryDisplayNumber}
onValueChange={async (entries) => {
if (!entries.length) addTitle(item.guess.title);
if (!entries.length) addTitle(guessTitle);
await editLinks({
video: item.id,
video: id,
entries,
});
}}