feat(filters): the any/all switch sits on the panel above its picker
ui/MatchToggle replaces the Combobox popover footer (Feed tags, topics, languages; Plex collections) and PlexSidebar's own toggle (genres, actors): shown from two picks, one wording. A closed picker had hidden that "all" was on.
This commit is contained in:
@@ -17,6 +17,7 @@ import ChannelPicker from "./ChannelPicker";
|
||||
import DateFilterSelect from "./DateFilterSelect";
|
||||
import YearFilter from "./YearFilter";
|
||||
import Combobox, { type ComboboxOption } from "./ui/Combobox";
|
||||
import MatchToggle from "./ui/MatchToggle";
|
||||
import { useFeedFilters, useFeedFiltersActions } from "./feedFiltersContext";
|
||||
import { useChannelsActions } from "./channelsContext";
|
||||
import { useMe } from "../lib/useMe";
|
||||
@@ -101,7 +102,8 @@ export default function Sidebar({
|
||||
tags: [...filters.tags.filter((id) => !inList.has(id)), ...next.map(Number)],
|
||||
});
|
||||
}
|
||||
// Each tag category (language/topic/other) has its OWN any/all match, set from its combobox footer.
|
||||
// Each tag category (language/topic/other) has its OWN any/all match, set from the switch above its
|
||||
// picker (ui/MatchToggle); the store keeps the older or/and words.
|
||||
const setTagMode = (category: TagCategory, mode: "or" | "and") =>
|
||||
setFilters({ ...filters, tagModes: { ...filters.tagModes, [category]: mode } });
|
||||
|
||||
@@ -125,18 +127,23 @@ export default function Sidebar({
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Combobox
|
||||
label={t("sidebar.widget.tags")}
|
||||
options={[
|
||||
{ value: NO_TAG_SENTINEL, label: t("sidebar.noTagOption") },
|
||||
...visibleChips(userTags).map(tagOption),
|
||||
]}
|
||||
selected={noneOn ? [NO_TAG_SENTINEL] : selectedIn(userTags)}
|
||||
onChange={onChange}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
matchMode={filters.tagModes.other}
|
||||
onMatchModeChange={(m) => setTagMode("other", m)}
|
||||
/>
|
||||
<>
|
||||
<MatchToggle
|
||||
picked={selectedIn(userTags).length}
|
||||
value={filters.tagModes.other === "and" ? "all" : "any"}
|
||||
onChange={(m) => setTagMode("other", m === "all" ? "and" : "or")}
|
||||
/>
|
||||
<Combobox
|
||||
label={t("sidebar.widget.tags")}
|
||||
options={[
|
||||
{ value: NO_TAG_SENTINEL, label: t("sidebar.noTagOption") },
|
||||
...visibleChips(userTags).map(tagOption),
|
||||
]}
|
||||
selected={noneOn ? [NO_TAG_SENTINEL] : selectedIn(userTags)}
|
||||
onChange={onChange}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -165,27 +172,37 @@ export default function Sidebar({
|
||||
return <YearFilter filters={filters} setFilters={setFilters} />;
|
||||
case "language":
|
||||
return (
|
||||
<Combobox
|
||||
label={t("sidebar.widget.language")}
|
||||
options={visibleChips(languages).map(tagOption)}
|
||||
selected={selectedIn(languages)}
|
||||
onChange={(next) => setTagSelection(languages, next)}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
matchMode={filters.tagModes.language}
|
||||
onMatchModeChange={(m) => setTagMode("language", m)}
|
||||
/>
|
||||
<>
|
||||
<MatchToggle
|
||||
picked={selectedIn(languages).length}
|
||||
value={filters.tagModes.language === "and" ? "all" : "any"}
|
||||
onChange={(m) => setTagMode("language", m === "all" ? "and" : "or")}
|
||||
/>
|
||||
<Combobox
|
||||
label={t("sidebar.widget.language")}
|
||||
options={visibleChips(languages).map(tagOption)}
|
||||
selected={selectedIn(languages)}
|
||||
onChange={(next) => setTagSelection(languages, next)}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case "topic":
|
||||
return (
|
||||
<Combobox
|
||||
label={t("sidebar.widget.topic")}
|
||||
options={visibleChips(topics).map(tagOption)}
|
||||
selected={selectedIn(topics)}
|
||||
onChange={(next) => setTagSelection(topics, next)}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
matchMode={filters.tagModes.topic}
|
||||
onMatchModeChange={(m) => setTagMode("topic", m)}
|
||||
/>
|
||||
<>
|
||||
<MatchToggle
|
||||
picked={selectedIn(topics).length}
|
||||
value={filters.tagModes.topic === "and" ? "all" : "any"}
|
||||
onChange={(m) => setTagMode("topic", m === "all" ? "and" : "or")}
|
||||
/>
|
||||
<Combobox
|
||||
label={t("sidebar.widget.topic")}
|
||||
options={visibleChips(topics).map(tagOption)}
|
||||
selected={selectedIn(topics)}
|
||||
onChange={(next) => setTagSelection(topics, next)}
|
||||
emptyText={t("sidebar.noMatchingTags")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case "tags":
|
||||
// The widget's own "Manage" trigger is its title (see the PanelItem onTitleClick below), so the
|
||||
|
||||
Reference in New Issue
Block a user