mirror of
https://github.com/rommapp/romm.git
synced 2026-06-28 14:56:01 +00:00
Merge pull request #2904 from rommapp/roms-filter-endpoint
ROMs filter endpoint + refactor
This commit is contained in:
@@ -444,3 +444,16 @@ class DetailedRomSchema(RomSchema):
|
||||
@field_validator("user_screenshots")
|
||||
def sort_user_screenshots(cls, v: list[ScreenshotSchema]) -> list[ScreenshotSchema]:
|
||||
return sorted(v, key=lambda x: x.created_at, reverse=True)
|
||||
|
||||
|
||||
class RomFiltersDict(TypedDict):
|
||||
genres: list[str]
|
||||
franchises: list[str]
|
||||
collections: list[str]
|
||||
companies: list[str]
|
||||
game_modes: list[str]
|
||||
age_ratings: list[str]
|
||||
player_counts: list[str]
|
||||
regions: list[str]
|
||||
languages: list[str]
|
||||
platforms: list[int]
|
||||
|
||||
@@ -43,6 +43,7 @@ from endpoints.responses import BulkOperationResponse
|
||||
from endpoints.responses.rom import (
|
||||
DetailedRomSchema,
|
||||
RomFileSchema,
|
||||
RomFiltersDict,
|
||||
RomUserSchema,
|
||||
SimpleRomSchema,
|
||||
UserNoteSchema,
|
||||
@@ -186,6 +187,7 @@ class CustomLimitOffsetParams(LimitOffsetParams):
|
||||
class CustomLimitOffsetPage[T: BaseModel](LimitOffsetPage[T]):
|
||||
char_index: dict[str, int]
|
||||
rom_id_index: list[int]
|
||||
filter_values: RomFiltersDict
|
||||
__params_type__ = CustomLimitOffsetParams
|
||||
|
||||
|
||||
@@ -196,6 +198,9 @@ def get_roms(
|
||||
bool,
|
||||
Query(description="Whether to get the char index."),
|
||||
] = True,
|
||||
with_filter_values: Annotated[
|
||||
bool, Query(description="Whether to return filter values.")
|
||||
] = True,
|
||||
search_term: Annotated[
|
||||
str | None,
|
||||
Query(description="Search term to filter roms."),
|
||||
@@ -413,7 +418,7 @@ def get_roms(
|
||||
] = None,
|
||||
) -> CustomLimitOffsetPage[SimpleRomSchema]:
|
||||
"""Retrieve roms."""
|
||||
query, order_by_attr = db_rom_handler.get_roms_query(
|
||||
unfiltered_query, order_by_attr = db_rom_handler.get_roms_query(
|
||||
user_id=request.user.id,
|
||||
order_by=order_by.lower(),
|
||||
order_dir=order_dir.lower(),
|
||||
@@ -421,7 +426,7 @@ def get_roms(
|
||||
|
||||
# Filter down the query
|
||||
query = db_rom_handler.filter_roms(
|
||||
query=query,
|
||||
query=unfiltered_query,
|
||||
user_id=request.user.id,
|
||||
platform_ids=platform_ids,
|
||||
collection_id=collection_id,
|
||||
@@ -467,6 +472,33 @@ def get_roms(
|
||||
)
|
||||
char_index_dict = {char: index for (char, index) in char_index}
|
||||
|
||||
filter_values = RomFiltersDict(
|
||||
genres=[],
|
||||
franchises=[],
|
||||
collections=[],
|
||||
companies=[],
|
||||
game_modes=[],
|
||||
age_ratings=[],
|
||||
player_counts=[],
|
||||
regions=[],
|
||||
languages=[],
|
||||
platforms=[],
|
||||
)
|
||||
if with_filter_values:
|
||||
# We use the unfiltered query so applied filters don't affect the list
|
||||
filter_query = db_rom_handler.filter_roms(
|
||||
query=unfiltered_query,
|
||||
user_id=request.user.id,
|
||||
platform_ids=platform_ids,
|
||||
collection_id=collection_id,
|
||||
virtual_collection_id=virtual_collection_id,
|
||||
smart_collection_id=smart_collection_id,
|
||||
search_term=search_term,
|
||||
)
|
||||
query_filters = db_rom_handler.with_filter_values(query=filter_query)
|
||||
# trunk-ignore(mypy/typeddict-item)
|
||||
filter_values = RomFiltersDict(**query_filters)
|
||||
|
||||
# Get all ROM IDs in order for the additional data
|
||||
with sync_session.begin() as session:
|
||||
rom_id_index = session.scalars(query.with_only_columns(Rom.id)).all() # type: ignore
|
||||
@@ -480,6 +512,7 @@ def get_roms(
|
||||
additional_data={
|
||||
"char_index": char_index_dict,
|
||||
"rom_id_index": rom_id_index,
|
||||
"filter_values": filter_values,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -678,6 +711,15 @@ def get_rom_by_hash(
|
||||
return DetailedRomSchema.from_orm_with_request(rom, request)
|
||||
|
||||
|
||||
@protected_route(router.get, "/filters", [Scope.ROMS_READ])
|
||||
async def get_rom_filters(request: Request) -> RomFiltersDict:
|
||||
from handler.database import db_rom_handler
|
||||
|
||||
filters = db_rom_handler.get_rom_filters()
|
||||
# trunk-ignore(mypy/typeddict-item)
|
||||
return RomFiltersDict(**filters)
|
||||
|
||||
|
||||
@protected_route(
|
||||
router.get,
|
||||
"/{id}",
|
||||
@@ -1509,7 +1551,7 @@ async def update_rom_user(
|
||||
|
||||
@protected_route(
|
||||
router.get,
|
||||
"files/{id}",
|
||||
"/files/{id}",
|
||||
[Scope.ROMS_READ],
|
||||
responses={status.HTTP_404_NOT_FOUND: {}},
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ from sqlalchemy import (
|
||||
)
|
||||
from sqlalchemy.orm import Query, Session, joinedload, noload, selectinload
|
||||
from sqlalchemy.sql.elements import KeyedColumnElement
|
||||
from sqlalchemy.sql.selectable import Select
|
||||
|
||||
from config import ROMM_DB_DRIVER
|
||||
from decorators.database import begin_session
|
||||
@@ -207,12 +208,12 @@ class DBRomsHandler(DBBaseHandler):
|
||||
def filter_by_platform_id(self, query: Query, platform_id: int):
|
||||
return query.filter(Rom.platform_id == platform_id)
|
||||
|
||||
def filter_by_platform_ids(
|
||||
def _filter_by_platform_ids(
|
||||
self, query: Query, platform_ids: Sequence[int]
|
||||
) -> Query:
|
||||
return query.filter(Rom.platform_id.in_(platform_ids))
|
||||
|
||||
def filter_by_collection_id(
|
||||
def _filter_by_collection_id(
|
||||
self, query: Query, session: Session, collection_id: int
|
||||
):
|
||||
from . import db_collection_handler
|
||||
@@ -223,7 +224,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
return query.filter(Rom.id.in_(collection.rom_ids))
|
||||
return query
|
||||
|
||||
def filter_by_virtual_collection_id(
|
||||
def _filter_by_virtual_collection_id(
|
||||
self, query: Query, session: Session, virtual_collection_id: str
|
||||
):
|
||||
from . import db_collection_handler
|
||||
@@ -236,7 +237,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
return query.filter(Rom.id.in_(v_collection.rom_ids))
|
||||
return query
|
||||
|
||||
def filter_by_smart_collection_id(
|
||||
def _filter_by_smart_collection_id(
|
||||
self, query: Query, session: Session, smart_collection_id: int, user_id: int
|
||||
):
|
||||
from . import db_collection_handler
|
||||
@@ -251,7 +252,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
return query.filter(Rom.id.in_(smart_collection.rom_ids))
|
||||
return query
|
||||
|
||||
def filter_by_search_term(self, query: Query, search_term: str):
|
||||
def _filter_by_search_term(self, query: Query, search_term: str):
|
||||
return query.filter(
|
||||
or_(
|
||||
Rom.fs_name.ilike(f"%{search_term}%"),
|
||||
@@ -259,7 +260,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
)
|
||||
)
|
||||
|
||||
def filter_by_matched(self, query: Query, value: bool) -> Query:
|
||||
def _filter_by_matched(self, query: Query, value: bool) -> Query:
|
||||
"""Filter based on whether the rom is matched to a metadata provider.
|
||||
|
||||
Args:
|
||||
@@ -279,7 +280,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
predicate = not_(predicate)
|
||||
return query.filter(predicate)
|
||||
|
||||
def filter_by_favorite(
|
||||
def _filter_by_favorite(
|
||||
self, query: Query, session: Session, value: bool, user_id: int | None
|
||||
) -> Query:
|
||||
"""Filter based on whether the rom is in the user's favorites collection."""
|
||||
@@ -301,21 +302,21 @@ class DBRomsHandler(DBBaseHandler):
|
||||
return query
|
||||
return query.filter(false())
|
||||
|
||||
def filter_by_duplicate(self, query: Query, value: bool) -> Query:
|
||||
def _filter_by_duplicate(self, query: Query, value: bool) -> Query:
|
||||
"""Filter based on whether the rom has duplicates."""
|
||||
predicate = Rom.sibling_roms.any()
|
||||
if not value:
|
||||
predicate = not_(predicate)
|
||||
return query.filter(predicate)
|
||||
|
||||
def filter_by_playable(self, query: Query, value: bool) -> Query:
|
||||
def _filter_by_playable(self, query: Query, value: bool) -> Query:
|
||||
"""Filter based on whether the rom is playable on supported platforms."""
|
||||
predicate = Platform.slug.in_(EJS_SUPPORTED_PLATFORMS)
|
||||
if not value:
|
||||
predicate = not_(predicate)
|
||||
return query.join(Platform).filter(predicate)
|
||||
|
||||
def filter_by_last_played(
|
||||
def _filter_by_last_played(
|
||||
self, query: Query, value: bool, user_id: int | None = None
|
||||
) -> Query:
|
||||
"""Filter based on whether the rom has a last played value for the user."""
|
||||
@@ -329,19 +330,19 @@ class DBRomsHandler(DBBaseHandler):
|
||||
)
|
||||
return query.filter(has_last_played)
|
||||
|
||||
def filter_by_has_ra(self, query: Query, value: bool) -> Query:
|
||||
def _filter_by_has_ra(self, query: Query, value: bool) -> Query:
|
||||
predicate = Rom.ra_id.isnot(None)
|
||||
if not value:
|
||||
predicate = not_(predicate)
|
||||
return query.filter(predicate)
|
||||
|
||||
def filter_by_missing_from_fs(self, query: Query, value: bool) -> Query:
|
||||
def _filter_by_missing_from_fs(self, query: Query, value: bool) -> Query:
|
||||
predicate = Rom.missing_from_fs.isnot(False)
|
||||
if not value:
|
||||
predicate = not_(predicate)
|
||||
return query.filter(predicate)
|
||||
|
||||
def filter_by_verified(self, query: Query):
|
||||
def _filter_by_verified(self, query: Query):
|
||||
keys_to_check = [
|
||||
"tosec_match",
|
||||
"mame_arcade_match",
|
||||
@@ -364,7 +365,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
or_(*(Rom.hasheous_metadata[key].as_boolean() for key in keys_to_check))
|
||||
)
|
||||
|
||||
def filter_by_genres(
|
||||
def _filter_by_genres(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -375,7 +376,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(RomMetadata.genres, values, session=session))
|
||||
|
||||
def filter_by_franchises(
|
||||
def _filter_by_franchises(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -386,7 +387,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(RomMetadata.franchises, values, session=session))
|
||||
|
||||
def filter_by_collections(
|
||||
def _filter_by_collections(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -397,7 +398,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(RomMetadata.collections, values, session=session))
|
||||
|
||||
def filter_by_companies(
|
||||
def _filter_by_companies(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -408,7 +409,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(RomMetadata.companies, values, session=session))
|
||||
|
||||
def filter_by_age_ratings(
|
||||
def _filter_by_age_ratings(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -419,7 +420,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(RomMetadata.age_ratings, values, session=session))
|
||||
|
||||
def filter_by_status(self, query: Query, statuses: Sequence[str]):
|
||||
def _filter_by_status(self, query: Query, statuses: Sequence[str]):
|
||||
"""Filter by one or more user statuses using OR logic."""
|
||||
if not statuses:
|
||||
return query
|
||||
@@ -441,7 +442,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
|
||||
return query.filter(or_(*status_filters), RomUser.hidden.is_(False))
|
||||
|
||||
def filter_by_regions(
|
||||
def _filter_by_regions(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -452,7 +453,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(Rom.regions, values, session=session))
|
||||
|
||||
def filter_by_languages(
|
||||
def _filter_by_languages(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -463,7 +464,7 @@ class DBRomsHandler(DBBaseHandler):
|
||||
op = json_array_contains_all if match_all else json_array_contains_any
|
||||
return query.filter(op(Rom.languages, values, session=session))
|
||||
|
||||
def filter_by_player_counts(
|
||||
def _filter_by_player_counts(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
@@ -518,52 +519,52 @@ class DBRomsHandler(DBBaseHandler):
|
||||
|
||||
# Handle platform filtering - platform filtering always uses OR logic since ROMs belong to only one platform
|
||||
if platform_ids:
|
||||
query = self.filter_by_platform_ids(query, platform_ids)
|
||||
query = self._filter_by_platform_ids(query, platform_ids)
|
||||
|
||||
if collection_id:
|
||||
query = self.filter_by_collection_id(query, session, collection_id)
|
||||
query = self._filter_by_collection_id(query, session, collection_id)
|
||||
|
||||
if virtual_collection_id:
|
||||
query = self.filter_by_virtual_collection_id(
|
||||
query = self._filter_by_virtual_collection_id(
|
||||
query, session, virtual_collection_id
|
||||
)
|
||||
|
||||
if smart_collection_id and user_id:
|
||||
query = self.filter_by_smart_collection_id(
|
||||
query = self._filter_by_smart_collection_id(
|
||||
query, session, smart_collection_id, user_id
|
||||
)
|
||||
|
||||
if search_term:
|
||||
query = self.filter_by_search_term(query, search_term)
|
||||
query = self._filter_by_search_term(query, search_term)
|
||||
|
||||
if matched is not None:
|
||||
query = self.filter_by_matched(query, value=matched)
|
||||
query = self._filter_by_matched(query, value=matched)
|
||||
|
||||
if favorite is not None:
|
||||
query = self.filter_by_favorite(
|
||||
query = self._filter_by_favorite(
|
||||
query, session=session, value=favorite, user_id=user_id
|
||||
)
|
||||
|
||||
if duplicate is not None:
|
||||
query = self.filter_by_duplicate(query, value=duplicate)
|
||||
query = self._filter_by_duplicate(query, value=duplicate)
|
||||
|
||||
if last_played is not None:
|
||||
query = self.filter_by_last_played(
|
||||
query = self._filter_by_last_played(
|
||||
query, value=last_played, user_id=user_id
|
||||
)
|
||||
|
||||
if playable is not None:
|
||||
query = self.filter_by_playable(query, value=playable)
|
||||
query = self._filter_by_playable(query, value=playable)
|
||||
|
||||
if has_ra is not None:
|
||||
query = self.filter_by_has_ra(query, value=has_ra)
|
||||
query = self._filter_by_has_ra(query, value=has_ra)
|
||||
|
||||
if missing is not None:
|
||||
query = self.filter_by_missing_from_fs(query, value=missing)
|
||||
query = self._filter_by_missing_from_fs(query, value=missing)
|
||||
|
||||
# TODO: Correctly support true/false values.
|
||||
if verified:
|
||||
query = self.filter_by_verified(query)
|
||||
query = self._filter_by_verified(query)
|
||||
|
||||
if updated_after:
|
||||
query = query.filter(Rom.updated_at > updated_after)
|
||||
@@ -681,14 +682,14 @@ class DBRomsHandler(DBBaseHandler):
|
||||
|
||||
# Apply metadata and rom-level filters efficiently
|
||||
filters_to_apply = [
|
||||
(genres, genres_logic, self.filter_by_genres),
|
||||
(franchises, franchises_logic, self.filter_by_franchises),
|
||||
(collections, collections_logic, self.filter_by_collections),
|
||||
(companies, companies_logic, self.filter_by_companies),
|
||||
(age_ratings, age_ratings_logic, self.filter_by_age_ratings),
|
||||
(regions, regions_logic, self.filter_by_regions),
|
||||
(languages, languages_logic, self.filter_by_languages),
|
||||
(player_counts, player_counts_logic, self.filter_by_player_counts),
|
||||
(genres, genres_logic, self._filter_by_genres),
|
||||
(franchises, franchises_logic, self._filter_by_franchises),
|
||||
(collections, collections_logic, self._filter_by_collections),
|
||||
(companies, companies_logic, self._filter_by_companies),
|
||||
(age_ratings, age_ratings_logic, self._filter_by_age_ratings),
|
||||
(regions, regions_logic, self._filter_by_regions),
|
||||
(languages, languages_logic, self._filter_by_languages),
|
||||
(player_counts, player_counts_logic, self._filter_by_player_counts),
|
||||
]
|
||||
|
||||
for values, logic, filter_func in filters_to_apply:
|
||||
@@ -699,7 +700,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)
|
||||
query = self._filter_by_status(query, statuses)
|
||||
elif user_id:
|
||||
query = query.filter(
|
||||
or_(RomUser.hidden.is_(False), RomUser.hidden.is_(None))
|
||||
@@ -1232,3 +1233,108 @@ class DBRomsHandler(DBBaseHandler):
|
||||
|
||||
# Return the first ROM matching any of the provided hash values
|
||||
return session.scalar(query.outerjoin(Rom.files).filter(or_(*filters)).limit(1))
|
||||
|
||||
def _collect_filter_values(
|
||||
self,
|
||||
session: Session,
|
||||
statement: Select,
|
||||
) -> dict:
|
||||
genres = set()
|
||||
franchises = set()
|
||||
collections = set()
|
||||
companies = set()
|
||||
game_modes = set()
|
||||
age_ratings = set()
|
||||
player_counts = set()
|
||||
regions = set()
|
||||
languages = set()
|
||||
platforms = set()
|
||||
|
||||
for row in session.execute(statement):
|
||||
g, f, cl, co, gm, ar, pc, rg, lg, pid = row
|
||||
if g:
|
||||
genres.update(g)
|
||||
if f:
|
||||
franchises.update(f)
|
||||
if cl:
|
||||
collections.update(cl)
|
||||
if co:
|
||||
companies.update(co)
|
||||
if gm:
|
||||
game_modes.update(gm)
|
||||
if ar:
|
||||
age_ratings.update(ar)
|
||||
if pc:
|
||||
player_counts.add(pc)
|
||||
if rg:
|
||||
regions.update(rg)
|
||||
if lg:
|
||||
languages.update(lg)
|
||||
platforms.add(pid)
|
||||
|
||||
return {
|
||||
"genres": sorted(genres),
|
||||
"franchises": sorted(franchises),
|
||||
"collections": sorted(collections),
|
||||
"companies": sorted(companies),
|
||||
"game_modes": sorted(game_modes),
|
||||
"age_ratings": sorted(age_ratings),
|
||||
"player_counts": sorted(player_counts),
|
||||
"regions": sorted(regions),
|
||||
"languages": sorted(languages),
|
||||
"platforms": sorted(platforms),
|
||||
}
|
||||
|
||||
@begin_session
|
||||
def with_filter_values(
|
||||
self,
|
||||
query: Query,
|
||||
session: Session = None, # type: ignore
|
||||
) -> dict:
|
||||
"""
|
||||
Returns the list of filters given the current subset of ROMs in the query
|
||||
"""
|
||||
ids_subq = query.with_only_columns(Rom.id).scalar_subquery() # type: ignore
|
||||
|
||||
statement = (
|
||||
select(
|
||||
RomMetadata.genres,
|
||||
RomMetadata.franchises,
|
||||
RomMetadata.collections,
|
||||
RomMetadata.companies,
|
||||
RomMetadata.game_modes,
|
||||
RomMetadata.age_ratings,
|
||||
RomMetadata.player_count,
|
||||
Rom.regions,
|
||||
Rom.languages,
|
||||
Rom.platform_id,
|
||||
)
|
||||
.select_from(Rom)
|
||||
.join(RomMetadata, Rom.id == RomMetadata.rom_id)
|
||||
.where(Rom.id.in_(ids_subq))
|
||||
)
|
||||
|
||||
return self._collect_filter_values(session, statement)
|
||||
|
||||
@begin_session
|
||||
def get_rom_filters(
|
||||
self,
|
||||
session: Session = None, # type: ignore
|
||||
) -> dict:
|
||||
"""
|
||||
Returns all filter values across all ROM metadata
|
||||
"""
|
||||
statement = select(
|
||||
RomMetadata.genres,
|
||||
RomMetadata.franchises,
|
||||
RomMetadata.collections,
|
||||
RomMetadata.companies,
|
||||
RomMetadata.game_modes,
|
||||
RomMetadata.age_ratings,
|
||||
RomMetadata.player_count,
|
||||
Rom.regions,
|
||||
Rom.languages,
|
||||
Rom.platform_id,
|
||||
)
|
||||
|
||||
return self._collect_filter_values(session, statement)
|
||||
|
||||
1
frontend/src/__generated__/index.ts
generated
1
frontend/src/__generated__/index.ts
generated
@@ -62,6 +62,7 @@ export type { RAUserGameProgression } from './models/RAUserGameProgression';
|
||||
export type { Role } from './models/Role';
|
||||
export type { RomFileCategory } from './models/RomFileCategory';
|
||||
export type { RomFileSchema } from './models/RomFileSchema';
|
||||
export type { RomFiltersDict } from './models/RomFiltersDict';
|
||||
export type { RomFlashpointMetadata } from './models/RomFlashpointMetadata';
|
||||
export type { RomGamelistMetadata } from './models/RomGamelistMetadata';
|
||||
export type { RomHasheousMetadata } from './models/RomHasheousMetadata';
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { RomFiltersDict } from './RomFiltersDict';
|
||||
import type { SimpleRomSchema } from './SimpleRomSchema';
|
||||
export type CustomLimitOffsetPage_SimpleRomSchema_ = {
|
||||
items: Array<SimpleRomSchema>;
|
||||
@@ -10,5 +11,6 @@ export type CustomLimitOffsetPage_SimpleRomSchema_ = {
|
||||
offset: number;
|
||||
char_index: Record<string, number>;
|
||||
rom_id_index: Array<number>;
|
||||
filter_values: RomFiltersDict;
|
||||
};
|
||||
|
||||
|
||||
17
frontend/src/__generated__/models/RomFiltersDict.ts
generated
Normal file
17
frontend/src/__generated__/models/RomFiltersDict.ts
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export type RomFiltersDict = {
|
||||
genres: Array<string>;
|
||||
franchises: Array<string>;
|
||||
collections: Array<string>;
|
||||
companies: Array<string>;
|
||||
game_modes: Array<string>;
|
||||
age_ratings: Array<string>;
|
||||
player_counts: Array<string>;
|
||||
regions: Array<string>;
|
||||
languages: Array<string>;
|
||||
platforms: Array<number>;
|
||||
};
|
||||
|
||||
@@ -5,11 +5,13 @@ import { inject, watch, computed } from "vue";
|
||||
import { useDisplay } from "vuetify";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
|
||||
const { smAndDown } = useDisplay();
|
||||
const romsStore = storeRoms();
|
||||
const platformsStore = storePlatforms();
|
||||
const galleryFilterStore = storeGalleryFilter();
|
||||
const galleryViewStore = storeGalleryView();
|
||||
const { selectedRoms } = storeToRefs(romsStore);
|
||||
@@ -29,7 +31,11 @@ async function fetchRoms() {
|
||||
});
|
||||
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore, concat: false })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
concat: false,
|
||||
})
|
||||
.then(() => {
|
||||
emitter?.emit("showLoadingDialog", {
|
||||
loading: false,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { debounce } from "lodash";
|
||||
import type { Emitter } from "mitt";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { inject, nextTick, onMounted, ref, watch } from "vue";
|
||||
import { inject, nextTick, onMounted } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useDisplay } from "vuetify";
|
||||
@@ -15,10 +15,9 @@ import FilterPlatformBtn from "@/components/Gallery/AppBar/common/FilterDrawer/F
|
||||
import FilterPlayablesBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterPlayablesBtn.vue";
|
||||
import FilterRaBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterRaBtn.vue";
|
||||
import FilterVerifiedBtn from "@/components/Gallery/AppBar/common/FilterDrawer/FilterVerifiedBtn.vue";
|
||||
import cachedApiService from "@/services/cache/api";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
|
||||
withDefaults(
|
||||
@@ -79,13 +78,16 @@ const {
|
||||
selectedPlayerCounts,
|
||||
playerCountsLogic,
|
||||
} = storeToRefs(galleryFilterStore);
|
||||
const { allPlatforms } = storeToRefs(platformsStore);
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
|
||||
const onFilterChange = debounce(
|
||||
() => {
|
||||
romsStore.resetPagination();
|
||||
romsStore.fetchRoms({ galleryFilter: galleryFilterStore, concat: false });
|
||||
romsStore.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
concat: false,
|
||||
});
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
// Update URL with filters
|
||||
@@ -174,16 +176,6 @@ const onFilterChange = debounce(
|
||||
{ leading: false, trailing: true },
|
||||
);
|
||||
|
||||
// Separate debounced function for search term changes
|
||||
const onSearchChange = debounce(
|
||||
async () => {
|
||||
await fetchSearchFilteredRoms();
|
||||
setFilters();
|
||||
},
|
||||
500,
|
||||
{ leading: false, trailing: true },
|
||||
);
|
||||
|
||||
emitter?.on("filterRoms", onFilterChange);
|
||||
|
||||
const filters = [
|
||||
@@ -264,111 +256,10 @@ const filters = [
|
||||
function resetFilters() {
|
||||
galleryFilterStore.resetFilters();
|
||||
nextTick(async () => {
|
||||
await fetchSearchFilteredRoms();
|
||||
setFilters();
|
||||
emitter?.emit("filterRoms", null);
|
||||
});
|
||||
}
|
||||
|
||||
// Store search-filtered ROMs for populating filter options
|
||||
let searchFilteredRoms = ref<SimpleRom[]>([]);
|
||||
|
||||
async function fetchSearchFilteredRoms() {
|
||||
try {
|
||||
const params = {
|
||||
searchTerm: searchTerm.value,
|
||||
platformIds: romsStore.currentPlatform
|
||||
? [romsStore.currentPlatform.id]
|
||||
: null,
|
||||
collectionId: romsStore.currentCollection?.id ?? null,
|
||||
virtualCollectionId: romsStore.currentVirtualCollection?.id ?? null,
|
||||
smartCollectionId: romsStore.currentSmartCollection?.id ?? null,
|
||||
limit: 10000, // Get enough ROMs to populate filters
|
||||
offset: 0,
|
||||
orderBy: romsStore.orderBy,
|
||||
orderDir: romsStore.orderDir,
|
||||
// Exclude all other filters to get comprehensive filter options
|
||||
filterMatched: null,
|
||||
filterFavorites: null,
|
||||
filterDuplicates: null,
|
||||
filterPlayables: null,
|
||||
filterRA: null,
|
||||
filterMissing: null,
|
||||
filterVerified: null,
|
||||
// Exclude all multi-value filters to get all possible options
|
||||
selectedGenres: null,
|
||||
selectedFranchises: null,
|
||||
selectedCollections: null,
|
||||
selectedCompanies: null,
|
||||
selectedAgeRatings: null,
|
||||
selectedRegions: null,
|
||||
selectedLanguages: null,
|
||||
selectedStatuses: null,
|
||||
};
|
||||
|
||||
// Fetch ROMs with only search term applied (and current platform/collection context)
|
||||
const response = await cachedApiService.getRoms(params, () => {}); // No background update callback needed
|
||||
|
||||
searchFilteredRoms.value = response.data.items;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch search-filtered ROMs:", error);
|
||||
// Fall back to current filtered ROMs if search-only fetch fails
|
||||
searchFilteredRoms.value = romsStore.filteredRoms;
|
||||
}
|
||||
}
|
||||
|
||||
function setFilters() {
|
||||
const romsForFilters =
|
||||
searchFilteredRoms.value.length > 0
|
||||
? searchFilteredRoms.value
|
||||
: romsStore.filteredRoms;
|
||||
|
||||
galleryFilterStore.setFilterPlatforms([
|
||||
...new Set(
|
||||
romsForFilters
|
||||
.flatMap((rom) => platformsStore.get(rom.platform_id))
|
||||
.filter((platform) => !!platform)
|
||||
.sort(),
|
||||
),
|
||||
]);
|
||||
galleryFilterStore.setFilterGenres([
|
||||
...new Set(romsForFilters.flatMap((rom) => rom.metadatum.genres).sort()),
|
||||
]);
|
||||
galleryFilterStore.setFilterFranchises([
|
||||
...new Set(
|
||||
romsForFilters.flatMap((rom) => rom.metadatum.franchises).sort(),
|
||||
),
|
||||
]);
|
||||
galleryFilterStore.setFilterCompanies([
|
||||
...new Set(romsForFilters.flatMap((rom) => rom.metadatum.companies).sort()),
|
||||
]);
|
||||
galleryFilterStore.setFilterCollections([
|
||||
...new Set(
|
||||
romsForFilters.flatMap((rom) => rom.metadatum.collections).sort(),
|
||||
),
|
||||
]);
|
||||
galleryFilterStore.setFilterAgeRatings([
|
||||
...new Set(
|
||||
romsForFilters.flatMap((rom) => rom.metadatum.age_ratings).sort(),
|
||||
),
|
||||
]);
|
||||
galleryFilterStore.setFilterRegions([
|
||||
...new Set(romsForFilters.flatMap((rom) => rom.regions).sort()),
|
||||
]);
|
||||
galleryFilterStore.setFilterLanguages([
|
||||
...new Set(romsForFilters.flatMap((rom) => rom.languages).sort()),
|
||||
]);
|
||||
galleryFilterStore.setFilterPlayerCounts([
|
||||
...new Set(
|
||||
romsForFilters
|
||||
.map((rom) => rom.metadatum.player_count)
|
||||
.filter((playerCount): playerCount is string => !!playerCount)
|
||||
.sort(),
|
||||
),
|
||||
]);
|
||||
// Note: filterStatuses is static and doesn't need to be set dynamically
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const {
|
||||
search: urlSearch,
|
||||
@@ -581,33 +472,10 @@ onMounted(async () => {
|
||||
romsStore.resetPagination();
|
||||
}
|
||||
|
||||
// Initial fetch of search-filtered ROMs for filter options
|
||||
await fetchSearchFilteredRoms();
|
||||
setFilters();
|
||||
|
||||
// Fire off search if URL state prepopulated
|
||||
if (freshSearch || galleryFilterStore.isFiltered()) {
|
||||
emitter?.emit("filterRoms", null);
|
||||
}
|
||||
|
||||
// Watch for search term changes to update filter options
|
||||
watch(
|
||||
() => searchTerm.value,
|
||||
async () => {
|
||||
await onSearchChange();
|
||||
},
|
||||
{ immediate: false },
|
||||
);
|
||||
|
||||
// Watch for platform changes to update filter options
|
||||
watch(
|
||||
() => allPlatforms.value,
|
||||
async () => {
|
||||
await fetchSearchFilteredRoms();
|
||||
setFilters();
|
||||
},
|
||||
{ immediate: false },
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import PlatformIcon from "@/components/common/Platform/PlatformIcon.vue";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms, { MAX_FETCH_LIMIT } from "@/stores/roms";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
|
||||
const { t } = useI18n();
|
||||
@@ -45,6 +45,7 @@ const onFilterChange = debounce(
|
||||
galleryFilterStore.setFilterMissing(true);
|
||||
romsStore.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
concat: false,
|
||||
});
|
||||
|
||||
@@ -74,7 +75,10 @@ async function fetchRoms() {
|
||||
|
||||
galleryFilterStore.setFilterMissing(true);
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching missing games:", error);
|
||||
emitter?.emit("snackbarShow", {
|
||||
@@ -91,10 +95,13 @@ async function fetchRoms() {
|
||||
}
|
||||
|
||||
function cleanupAll() {
|
||||
romsStore.setLimit(MAX_FETCH_LIMIT);
|
||||
romsStore.setLimit(10000);
|
||||
galleryFilterStore.setFilterMissing(true);
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
})
|
||||
.then(() => {
|
||||
emitter?.emit("showLoadingDialog", {
|
||||
loading: false,
|
||||
|
||||
@@ -16,6 +16,7 @@ import storeAuth from "@/stores/auth";
|
||||
import storeCollections from "@/stores/collections";
|
||||
import storeDownload from "@/stores/download";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import {
|
||||
@@ -44,6 +45,7 @@ const { filteredRoms, selectedRoms, fetchingRoms, fetchTotalRoms } =
|
||||
const auth = storeAuth();
|
||||
const galleryFilterStore = storeGalleryFilter();
|
||||
const collectionsStore = storeCollections();
|
||||
const platformsStore = storePlatforms();
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
|
||||
const HEADERS = [
|
||||
@@ -134,7 +136,10 @@ function updateOptions({ sortBy }: { sortBy: SortBy }) {
|
||||
romsStore.resetPagination();
|
||||
romsStore.setOrderBy(key);
|
||||
romsStore.setOrderDir(order);
|
||||
romsStore.fetchRoms({ galleryFilter: galleryFilterStore });
|
||||
romsStore.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -320,6 +320,7 @@ async function fetchRoms() {
|
||||
|
||||
const fetchedRoms = await romsStore.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
concat: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
ManualMetadata,
|
||||
RomUserSchema,
|
||||
UserNoteSchema,
|
||||
RomFiltersDict,
|
||||
} from "@/__generated__";
|
||||
import { type CustomLimitOffsetPage_SimpleRomSchema_ as GetRomsResponse } from "@/__generated__/models/CustomLimitOffsetPage_SimpleRomSchema_";
|
||||
import api from "@/services/api";
|
||||
@@ -246,6 +247,7 @@ async function getRecentRoms(): Promise<{ data: GetRomsResponse }> {
|
||||
order_dir: "desc",
|
||||
limit: RECENT_ROMS_LIMIT,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -257,6 +259,7 @@ async function getRecentPlayedRoms(): Promise<{ data: GetRomsResponse }> {
|
||||
order_dir: "desc",
|
||||
limit: RECENT_PLAYED_ROMS_LIMIT,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
last_played: true,
|
||||
},
|
||||
});
|
||||
@@ -582,6 +585,10 @@ async function getRomNotes({
|
||||
});
|
||||
}
|
||||
|
||||
async function getRomFilters(): Promise<{ data: RomFiltersDict }> {
|
||||
return api.get("/roms/filters");
|
||||
}
|
||||
|
||||
export default {
|
||||
uploadRoms,
|
||||
getRoms,
|
||||
@@ -601,4 +608,5 @@ export default {
|
||||
updateRomNote,
|
||||
deleteRomNote,
|
||||
getRomNotes,
|
||||
getRomFilters,
|
||||
};
|
||||
|
||||
4
frontend/src/services/cache/api.ts
vendored
4
frontend/src/services/cache/api.ts
vendored
@@ -147,6 +147,7 @@ class CachedApiService {
|
||||
order_dir: "desc",
|
||||
limit: 15,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
});
|
||||
|
||||
return cacheService.request<GetRomsResponse>(config, onBackgroundUpdate);
|
||||
@@ -160,6 +161,7 @@ class CachedApiService {
|
||||
order_dir: "desc",
|
||||
limit: 15,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
last_played: true,
|
||||
});
|
||||
|
||||
@@ -177,6 +179,7 @@ class CachedApiService {
|
||||
order_dir: "desc",
|
||||
limit: 15,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -186,6 +189,7 @@ class CachedApiService {
|
||||
order_dir: "desc",
|
||||
limit: 15,
|
||||
with_char_index: false,
|
||||
with_filter_values: false,
|
||||
last_played: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,15 +14,16 @@ import {
|
||||
type SmartCollection,
|
||||
} from "@/stores/collections";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import { type Platform } from "@/stores/platforms";
|
||||
import type { ExtractPiniaStoreType } from "@/types";
|
||||
|
||||
type GalleryFilterStore = ExtractPiniaStoreType<typeof storeGalleryFilter>;
|
||||
type PlatformsStore = ExtractPiniaStoreType<typeof storePlatforms>;
|
||||
|
||||
export type SimpleRom = SimpleRomSchema;
|
||||
export type SearchRom = SearchRomSchema;
|
||||
export type DetailedRom = DetailedRomSchema;
|
||||
export const MAX_FETCH_LIMIT = 10000;
|
||||
|
||||
const orderByStorage = useLocalStorage("roms.orderBy", "name");
|
||||
const orderDirStorage = useLocalStorage("roms.orderDir", "asc");
|
||||
@@ -150,8 +151,14 @@ export default defineStore("roms", {
|
||||
};
|
||||
return params;
|
||||
},
|
||||
_postFetchRoms(response: GetRomsResponse, concat: boolean) {
|
||||
const { items, offset, total, char_index, rom_id_index } = response;
|
||||
_postFetchRoms(
|
||||
response: GetRomsResponse,
|
||||
galleryFilter: GalleryFilterStore,
|
||||
platformsStore: PlatformsStore,
|
||||
concat: boolean,
|
||||
) {
|
||||
const { items, offset, total, char_index, rom_id_index, filter_values } =
|
||||
response;
|
||||
if (!concat || this.fetchOffset === 0) {
|
||||
this._allRoms = items;
|
||||
} else {
|
||||
@@ -165,12 +172,34 @@ export default defineStore("roms", {
|
||||
// Set the character index for the current platform
|
||||
this.characterIndex = char_index;
|
||||
this.romIdIndex = rom_id_index;
|
||||
|
||||
// Only set the list of platforms on first fetch
|
||||
if (galleryFilter.filterPlatforms.length === 0) {
|
||||
galleryFilter.setFilterPlatforms(
|
||||
platformsStore.allPlatforms.filter((p) =>
|
||||
filter_values.platforms.includes(p.id),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (filter_values) {
|
||||
galleryFilter.setFilterCollections(filter_values.collections);
|
||||
galleryFilter.setFilterGenres(filter_values.genres);
|
||||
galleryFilter.setFilterFranchises(filter_values.franchises);
|
||||
galleryFilter.setFilterCompanies(filter_values.companies);
|
||||
galleryFilter.setFilterAgeRatings(filter_values.age_ratings);
|
||||
galleryFilter.setFilterRegions(filter_values.regions);
|
||||
galleryFilter.setFilterLanguages(filter_values.languages);
|
||||
galleryFilter.setFilterPlayerCounts(filter_values.player_counts);
|
||||
}
|
||||
},
|
||||
async fetchRoms({
|
||||
galleryFilter,
|
||||
platformsStore,
|
||||
concat = true,
|
||||
}: {
|
||||
galleryFilter: GalleryFilterStore;
|
||||
platformsStore: PlatformsStore;
|
||||
concat?: boolean;
|
||||
}): Promise<SimpleRom[]> {
|
||||
if (this.fetchingRoms) return Promise.resolve([]);
|
||||
@@ -190,10 +219,20 @@ export default defineStore("roms", {
|
||||
JSON.stringify(currentParams) !==
|
||||
JSON.stringify(currentRequestParams);
|
||||
if (paramsChanged) return;
|
||||
this._postFetchRoms(response, concat);
|
||||
this._postFetchRoms(
|
||||
response,
|
||||
galleryFilter,
|
||||
platformsStore,
|
||||
concat,
|
||||
);
|
||||
})
|
||||
.then((response) => {
|
||||
this._postFetchRoms(response.data, concat);
|
||||
this._postFetchRoms(
|
||||
response.data,
|
||||
galleryFilter,
|
||||
platformsStore,
|
||||
concat,
|
||||
);
|
||||
resolve(response.data.items);
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -15,6 +15,7 @@ import GameTable from "@/components/common/Game/VirtualTable.vue";
|
||||
import { type CollectionType } from "@/stores/collections";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import { views } from "@/utils";
|
||||
@@ -29,6 +30,7 @@ const galleryViewStore = storeGalleryView();
|
||||
const galleryFilterStore = storeGalleryFilter();
|
||||
const { scrolledToTop, currentView } = storeToRefs(galleryViewStore);
|
||||
const romsStore = storeRoms();
|
||||
const platformsStore = storePlatforms();
|
||||
const {
|
||||
filteredRoms,
|
||||
selectedRoms,
|
||||
@@ -53,7 +55,10 @@ async function fetchRoms() {
|
||||
});
|
||||
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
})
|
||||
.then(() => {
|
||||
emitter?.emit("showLoadingDialog", {
|
||||
loading: false,
|
||||
|
||||
@@ -48,7 +48,10 @@ async function fetchRoms() {
|
||||
});
|
||||
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
})
|
||||
.then(() => {
|
||||
emitter?.emit("showLoadingDialog", {
|
||||
loading: false,
|
||||
|
||||
@@ -13,6 +13,7 @@ import GameCard from "@/components/common/Game/Card/Base.vue";
|
||||
import GameTable from "@/components/common/Game/VirtualTable.vue";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import { views } from "@/utils";
|
||||
@@ -22,6 +23,7 @@ const { scrolledToTop, currentView } = storeToRefs(galleryViewStore);
|
||||
const galleryFilterStore = storeGalleryFilter();
|
||||
const { searchTerm } = storeToRefs(galleryFilterStore);
|
||||
const romsStore = storeRoms();
|
||||
const platformsStore = storePlatforms();
|
||||
const {
|
||||
filteredRoms,
|
||||
selectedRoms,
|
||||
@@ -100,7 +102,10 @@ function onGameTouchEnd() {
|
||||
|
||||
function fetchRoms() {
|
||||
romsStore
|
||||
.fetchRoms({ galleryFilter: galleryFilterStore })
|
||||
.fetchRoms({
|
||||
galleryFilter: galleryFilterStore,
|
||||
platformsStore: platformsStore,
|
||||
})
|
||||
.catch((error) => {
|
||||
emitter?.emit("snackbarShow", {
|
||||
msg: `Couldn't fetch roms: ${error}`,
|
||||
@@ -108,9 +113,6 @@ function fetchRoms() {
|
||||
color: "red",
|
||||
timeout: 4000,
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
galleryFilterStore.activeFilterDrawer = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user