diff --git a/backend/handler/database/platforms_handler.py b/backend/handler/database/platforms_handler.py index f2c0aee5f..de3976fa1 100644 --- a/backend/handler/database/platforms_handler.py +++ b/backend/handler/database/platforms_handler.py @@ -1,49 +1,36 @@ -import functools - from decorators.database import begin_session from models.platform import Platform from models.rom import Rom from sqlalchemy import Select, delete, or_, select -from sqlalchemy.orm import Query, Session, selectinload +from sqlalchemy.orm import Session from .base_handler import DBBaseHandler -def with_roms(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - session = kwargs.get("session") - if session is None: - raise ValueError("session is required") - - kwargs["query"] = select(Platform).options( - selectinload(Platform.roms).load_only(Rom.id) - ) - return func(*args, **kwargs) - - return wrapper - - class DBPlatformsHandler(DBBaseHandler): @begin_session - @with_roms def add_platform( - self, platform: Platform, query: Query = None, session: Session = None + self, + platform: Platform, + session: Session, ) -> Platform: platform = session.merge(platform) session.flush() - return session.scalar(query.filter_by(id=platform.id).limit(1)) + new_platform = session.scalar( + select(Platform).filter_by(id=platform.id).limit(1) + ) + if not new_platform: + raise ValueError("Could not find newlyewly created platform") + + return new_platform @begin_session - @with_roms - def get_platform( - self, id: int, *, query: Query = None, session: Session = None - ) -> Platform | None: - return session.scalar(query.filter_by(id=id).limit(1)) + def get_platform(self, id: int, *, session: Session) -> Platform | None: + return session.scalar(select(Platform).filter_by(id=id).limit(1)) @begin_session - def get_platforms(self, *, session: Session = None) -> Select[tuple[Platform]]: + def get_platforms(self, *, session: Session) -> Select[tuple[Platform]]: return ( session.scalars(select(Platform).order_by(Platform.name.asc())) # type: ignore[attr-defined] .unique() @@ -51,28 +38,28 @@ def get_platforms(self, *, session: Session = None) -> Select[tuple[Platform]]: ) @begin_session - @with_roms def get_platform_by_fs_slug( - self, fs_slug: str, query: Query = None, session: Session = None + self, fs_slug: str, session: Session ) -> Platform | None: - return session.scalar(query.filter_by(fs_slug=fs_slug).limit(1)) + return session.scalar(select(Platform).filter_by(fs_slug=fs_slug).limit(1)) @begin_session - def delete_platform(self, id: int, session: Session = None) -> int: + def delete_platform(self, id: int, session: Session) -> None: # Remove all roms from that platforms first session.execute( delete(Rom) .where(Rom.platform_id == id) .execution_options(synchronize_session="evaluate") ) - return session.execute( + + session.execute( delete(Platform) .where(Platform.id == id) .execution_options(synchronize_session="evaluate") ) @begin_session - def purge_platforms(self, fs_platforms: list[str], session: Session = None) -> int: + def purge_platforms(self, fs_platforms: list[str], session: Session) -> int: return session.execute( delete(Platform) .where(or_(Platform.fs_slug.not_in(fs_platforms), Platform.slug.is_(None))) # type: ignore[attr-defined] diff --git a/frontend/src/stores/roms.ts b/frontend/src/stores/roms.ts index 81d9cc3ed..ba20a097e 100644 --- a/frontend/src/stores/roms.ts +++ b/frontend/src/stores/roms.ts @@ -23,8 +23,8 @@ export default defineStore("roms", { currentRom: null as DetailedRom | null, allRoms: [] as SimpleRom[], _grouped: [] as SimpleRom[], - _filteredIDs: [] as number[], - _selectedIDs: [] as number[], + _filteredIDs: new Set(), + _selectedIDs: new Set(), recentRoms: [] as SimpleRom[], lastSelectedIndex: -1, selecting: false, @@ -34,9 +34,9 @@ export default defineStore("roms", { getters: { filteredRoms: (state) => - state._grouped.filter((rom) => state._filteredIDs.includes(rom.id)), + state._grouped.filter((rom) => state._filteredIDs.has(rom.id)), selectedRoms: (state) => - state._grouped.filter((rom) => state._selectedIDs.includes(rom.id)), + state._grouped.filter((rom) => state._selectedIDs.has(rom.id)), }, actions: { @@ -115,22 +115,18 @@ export default defineStore("roms", { return rom.id === value.id; }); }); - this._filteredIDs = this._filteredIDs.filter((value) => { - return !roms.find((rom) => { - return rom.id === value; - }); - }); + roms.forEach((rom) => this._filteredIDs.delete(rom.id)); }, reset() { this.allRoms = []; this._grouped = []; - this._filteredIDs = []; - this._selectedIDs = []; + this._filteredIDs = new Set(); + this._selectedIDs = new Set(); this.lastSelectedIndex = -1; }, // Filter roms by gallery filter store state setFiltered(roms: SimpleRom[], galleryFilter: GalleryFilterStore) { - this._filteredIDs = roms.map((rom) => rom.id); + this._filteredIDs = new Set(roms.map((rom) => rom.id)); if (galleryFilter.filterSearch) { this._filterSearch(galleryFilter.filterSearch); } @@ -157,68 +153,108 @@ export default defineStore("roms", { } }, _filterSearch(searchFilter: string) { - this._filteredIDs = this.filteredRoms - .filter( - (rom) => - rom.name?.toLowerCase().includes(searchFilter.toLowerCase()) || - rom.file_name?.toLowerCase().includes(searchFilter.toLowerCase()), - ) - .map((roms) => roms.id); + const bySearch = new Set( + this.filteredRoms + .filter( + (rom) => + rom.name?.toLowerCase().includes(searchFilter.toLowerCase()) || + rom.file_name?.toLowerCase().includes(searchFilter.toLowerCase()), + ) + .map((roms) => roms.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = bySearch.intersection(this._filteredIDs); }, _filterUnmatched() { - this._filteredIDs = this.filteredRoms - .filter((rom) => !rom.igdb_id && !rom.moby_id) - .map((roms) => roms.id); + const byUnmatched = new Set( + this.filteredRoms + .filter((rom) => !rom.igdb_id && !rom.moby_id) + .map((roms) => roms.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byUnmatched.intersection(this._filteredIDs); }, _filterFavourites() { - this._filteredIDs = this.filteredRoms - .filter((rom) => collectionStore.favCollection?.roms?.includes(rom.id)) - .map((roms) => roms.id); + const byFavourites = new Set( + this.filteredRoms + .filter((rom) => + collectionStore.favCollection?.roms?.includes(rom.id), + ) + .map((roms) => roms.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byFavourites.intersection(this._filteredIDs); }, _filterDuplicates() { - this._filteredIDs = this.filteredRoms - .filter((rom) => rom.sibling_roms?.length) - .map((rom) => rom.id); + const byDuplicates = new Set( + this.filteredRoms + .filter((rom) => rom.sibling_roms?.length) + .map((rom) => rom.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byDuplicates.intersection(this._filteredIDs); }, _filterGenre(genreToFilter: string) { - this._filteredIDs = this.filteredRoms - .filter((rom) => rom.genres.some((genre) => genre === genreToFilter)) - .map((rom) => rom.id); + const byGenre = new Set( + this.filteredRoms + .filter((rom) => rom.genres.some((genre) => genre === genreToFilter)) + .map((rom) => rom.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byGenre.intersection(this._filteredIDs); }, _filterFranchise(franchiseToFilter: string) { - this._filteredIDs = this.filteredRoms - .filter((rom) => - rom.franchises.some((franchise) => franchise === franchiseToFilter), - ) - .map((rom) => rom.id); + const byFranchise = new Set( + this.filteredRoms + .filter((rom) => + rom.franchises.some((franchise) => franchise === franchiseToFilter), + ) + .map((rom) => rom.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byFranchise.intersection(this._filteredIDs); }, _filterCollection(collectionToFilter: string) { - this._filteredIDs = this.filteredRoms - .filter((rom) => - rom.collections.some( - (collection) => collection === collectionToFilter, - ), - ) - .map((rom) => rom.id); + const byCollection = new Set( + this.filteredRoms + .filter((rom) => + rom.collections.some( + (collection) => collection === collectionToFilter, + ), + ) + .map((rom) => rom.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byCollection.intersection(this._filteredIDs); }, _filterCompany(companyToFilter: string) { - this._filteredIDs = this.filteredRoms - .filter((rom) => - rom.companies.some((company) => company === companyToFilter), - ) - .map((rom) => rom.id); + const byCompany = new Set( + this.filteredRoms + .filter((rom) => + rom.companies.some((company) => company === companyToFilter), + ) + .map((rom) => rom.id), + ); + + // @ts-expect-error intersection is recently defined on Set + this._filteredIDs = byCompany.intersection(this._filteredIDs); }, // Selected roms setSelection(roms: SimpleRom[]) { - this._selectedIDs = roms.map((rom) => rom.id); + this._selectedIDs = new Set(roms.map((rom) => rom.id)); }, addToSelection(rom: SimpleRom) { - this._selectedIDs.push(rom.id); + this._selectedIDs.add(rom.id); }, removeFromSelection(rom: SimpleRom) { - this._selectedIDs = this._selectedIDs.filter((id) => { - return id !== rom.id; - }); + this._selectedIDs.delete(rom.id); }, updateLastSelected(index: number) { this.lastSelectedIndex = index; @@ -227,7 +263,7 @@ export default defineStore("roms", { this.selecting = !this.selecting; }, resetSelection() { - this._selectedIDs = []; + this._selectedIDs = new Set(); this.lastSelectedIndex = -1; }, isSimpleRom(rom: SimpleRom | SearchRomSchema): rom is SimpleRom {