diff --git a/backend/handler/database/roms_handler.py b/backend/handler/database/roms_handler.py index 9d03392f3..6afd252d8 100644 --- a/backend/handler/database/roms_handler.py +++ b/backend/handler/database/roms_handler.py @@ -424,13 +424,21 @@ class DBRomsHandler(DBBaseHandler): condition = op(RomMetadata.age_ratings, values, session=session) return query.filter(~condition) if match_none else query.filter(condition) - def _filter_by_status(self, query: Query, statuses: Sequence[str]): + def _filter_by_status( + self, + query: Query, + *, + session: Session, + values: Sequence[str], + match_all: bool = False, + match_none: bool = False, + ): """Filter by one or more user statuses using OR logic.""" - if not statuses: + if not values: return query status_filters = [] - for selected_status in statuses: + for selected_status in values: if selected_status == "now_playing": status_filters.append(RomUser.now_playing.is_(True)) elif selected_status == "backlogged": @@ -440,11 +448,17 @@ class DBRomsHandler(DBBaseHandler): else: status_filters.append(RomUser.status == selected_status) - # If hidden is in the list, don't apply the hidden filter at the end - if "hidden" in statuses: - return query.filter(or_(*status_filters)) + comb = and_ if match_all else or_ + condition = comb(*status_filters) - return query.filter(or_(*status_filters), RomUser.hidden.is_(False)) + # Apply negation if match_none, otherwise apply condition + query = query.filter(~condition) if match_none else query.filter(condition) + + # If hidden wasn't explicitly requested, always exclude hidden rows + if "hidden" not in values: + query = query.filter(RomUser.hidden.is_(False)) + + return query def _filter_by_regions( self, @@ -726,6 +740,7 @@ class DBRomsHandler(DBBaseHandler): (regions, regions_logic, self._filter_by_regions), (languages, languages_logic, self._filter_by_languages), (player_counts, player_counts_logic, self._filter_by_player_counts), + (statuses, statuses_logic, self._filter_by_status), ] for values, logic, filter_func in filters_to_apply: @@ -739,9 +754,7 @@ class DBRomsHandler(DBBaseHandler): ) # The RomUser table is already joined if user_id is set - if statuses and user_id: - query = self._filter_by_status(query, statuses) - elif user_id: + if user_id: query = query.filter( or_(RomUser.hidden.is_(False), RomUser.hidden.is_(None)) ) diff --git a/frontend/src/components/common/Collection/Dialog/CreateSmartCollection.vue b/frontend/src/components/common/Collection/Dialog/CreateSmartCollection.vue index 1ce4880d5..23225666b 100644 --- a/frontend/src/components/common/Collection/Dialog/CreateSmartCollection.vue +++ b/frontend/src/components/common/Collection/Dialog/CreateSmartCollection.vue @@ -13,7 +13,6 @@ import storeCollections from "@/stores/collections"; import storeGalleryFilter from "@/stores/galleryFilter"; import storeRoms from "@/stores/roms"; import type { Events } from "@/types/emitter"; -import { getStatusKeyForText } from "@/utils"; const { t } = useI18n(); const galleryFilterStore = storeGalleryFilter(); @@ -172,10 +171,7 @@ async function createSmartCollection() { filterCriteria.age_ratings_logic = ageRatingsLogic.value; } if (selectedStatuses.value && selectedStatuses.value.length > 0) { - const statusKeys = selectedStatuses.value - .filter((s): s is string => s !== null) - .map((s) => getStatusKeyForText(s)) - .filter((key) => key !== null); + const statusKeys = selectedStatuses.value; if (statusKeys.length > 0) { filterCriteria.selected_status = statusKeys; } diff --git a/frontend/src/stores/galleryFilter.ts b/frontend/src/stores/galleryFilter.ts index 90f75bc32..d198c82a3 100644 --- a/frontend/src/stores/galleryFilter.ts +++ b/frontend/src/stores/galleryFilter.ts @@ -29,7 +29,7 @@ const defaultFilterState = { filterRegions: [] as string[], filterLanguages: [] as string[], filterPlayerCounts: [] as string[], - filterStatuses: Object.values(romStatusMap).map((status) => status.text), + filterStatuses: Object.keys(romStatusMap), filterMatched: null as boolean | null, // null = all, true = matched, false = unmatched filterFavorites: null as boolean | null, // null = all, true = favorites, false = not favorites filterDuplicates: null as boolean | null, // null = all, true = duplicates, false = not duplicates diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index bbd45f328..d4d78d9ba 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -710,17 +710,6 @@ export function getI18nKeyForStatus(status: PlayingStatus): string | null { return romStatusMap[status]?.i18nKey ?? null; } -/** - * Get the status key for a given text. - * - * @param text The text to convert. - * @returns The corresponding status key. - */ -export function getStatusKeyForText(text: string | null) { - if (!text) return null; - return inverseRomStatusMap[text]; -} - export function isNintendoDSFile(rom: SimpleRom): boolean { return ["cia", "nds", "3ds", "dsi"].includes(rom.fs_extension.toLowerCase()); }