set filter platforms on platforms fetch

This commit is contained in:
Georges-Antoine Assi
2026-01-15 12:10:13 -05:00
parent 81b9eff8c7
commit b0cf2e9338
9 changed files with 89 additions and 109 deletions

View File

@@ -449,6 +449,7 @@ class DetailedRomSchema(RomSchema):
class RomFiltersDict(TypedDict):
genres: list[str]
franchises: list[str]
collections: list[str]
companies: list[str]
game_modes: list[str]
age_ratings: list[str]

View File

@@ -468,6 +468,7 @@ def get_roms(
filter_values = RomFiltersDict(
genres=[],
franchises=[],
collections=[],
companies=[],
game_modes=[],
age_ratings=[],
@@ -480,6 +481,7 @@ def get_roms(
filter_values = RomFiltersDict(
genres=query_filters["genres"],
franchises=query_filters["franchises"],
collections=query_filters["collections"],
companies=query_filters["companies"],
game_modes=query_filters["game_modes"],
age_ratings=query_filters["age_ratings"],
@@ -709,6 +711,7 @@ async def get_rom_filters(request: Request) -> RomFiltersDict:
return RomFiltersDict(
genres=filters["genres"],
franchises=filters["franchises"],
collections=filters["collections"],
companies=filters["companies"],
game_modes=filters["game_modes"],
age_ratings=filters["age_ratings"],

View File

@@ -835,6 +835,65 @@ class DBRomsHandler(DBBaseHandler):
.all()
)
@begin_session
def with_filter_values(
self,
query: Query,
session: Session = None, # type: ignore
) -> dict:
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,
)
.select_from(Rom)
.join(RomMetadata, Rom.id == RomMetadata.rom_id)
.where(Rom.id.in_(ids_subq))
)
genres = set()
franchises = set()
collections = set()
companies = set()
game_modes = set()
age_ratings = set()
player_counts = set()
regions = set()
languages = set()
for row in session.execute(statement):
g, f, cl, co, gm, ar, pc, rg, lg = row
genres.update(g)
franchises.update(f)
collections.update(cl)
companies.update(co)
game_modes.update(gm)
age_ratings.update(ar)
player_counts.update(pc)
regions.update(rg)
languages.update(lg)
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),
}
@begin_session
@with_details
def get_roms_by_fs_name(
@@ -1236,6 +1295,7 @@ class DBRomsHandler(DBBaseHandler):
statement = select(
RomMetadata.genres,
RomMetadata.franchises,
RomMetadata.collections,
RomMetadata.companies,
RomMetadata.game_modes,
RomMetadata.age_ratings,
@@ -1243,8 +1303,10 @@ class DBRomsHandler(DBBaseHandler):
Rom.regions,
Rom.languages,
)
genres = set()
franchises = set()
collections = set()
companies = set()
game_modes = set()
age_ratings = set()
@@ -1253,65 +1315,11 @@ class DBRomsHandler(DBBaseHandler):
languages = set()
for row in session.execute(statement):
g, f, c, gm, ar, pc, rg, lg = row
g, f, cl, co, gm, ar, pc, rg, lg = row
genres.update(g)
franchises.update(f)
companies.update(c)
game_modes.update(gm)
age_ratings.update(ar)
player_counts.update(pc)
regions.update(rg)
languages.update(lg)
return {
"genres": sorted(genres),
"franchises": sorted(franchises),
"companies": sorted(companies),
"game_modes": sorted(game_modes),
"age_ratings": sorted(age_ratings),
"player_counts": sorted(player_counts),
"regions": sorted(regions),
"languages": sorted(languages),
}
@begin_session
def with_filter_values(
self,
query: Query,
session: Session = None, # type: ignore
) -> dict:
ids_subq = query.with_only_columns(Rom.id).scalar_subquery() # type: ignore
statement = (
select(
RomMetadata.genres,
RomMetadata.franchises,
RomMetadata.companies,
RomMetadata.game_modes,
RomMetadata.age_ratings,
RomMetadata.player_count,
Rom.regions,
Rom.languages,
)
.select_from(Rom)
.join(RomMetadata, Rom.id == RomMetadata.rom_id)
.where(Rom.id.in_(ids_subq))
)
genres = set()
franchises = set()
companies = set()
game_modes = set()
age_ratings = set()
player_counts = set()
regions = set()
languages = set()
for row in session.execute(statement):
g, f, c, gm, ar, pc, rg, lg = row
genres.update(g)
franchises.update(f)
companies.update(c)
collections.update(cl)
companies.update(co)
game_modes.update(gm)
age_ratings.update(ar)
player_counts.update(pc)
@@ -1321,6 +1329,7 @@ class DBRomsHandler(DBBaseHandler):
return {
"genres": sorted(genres),
"franchises": sorted(franchises),
"collections": sorted(collections),
"companies": sorted(companies),
"game_modes": sorted(game_modes),
"age_ratings": sorted(age_ratings),

View File

@@ -5,6 +5,7 @@
export type RomFiltersDict = {
genres: Array<string>;
franchises: Array<string>;
collections: Array<string>;
companies: Array<string>;
game_modes: Array<string>;
age_ratings: Array<string>;

View File

@@ -2,7 +2,7 @@
import { debounce } from "lodash";
import type { Emitter } from "mitt";
import { storeToRefs } from "pinia";
import { inject, nextTick, onMounted, watch } from "vue";
import { inject, nextTick, onMounted } from "vue";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import { useDisplay } from "vuetify";
@@ -15,7 +15,6 @@ 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 romApi from "@/services/api/rom";
import storeGalleryFilter from "@/stores/galleryFilter";
import storePlatforms from "@/stores/platforms";
import storeRoms from "@/stores/roms";
@@ -79,7 +78,6 @@ const {
selectedPlayerCounts,
playerCountsLogic,
} = storeToRefs(galleryFilterStore);
const { allPlatforms } = storeToRefs(platformsStore);
const emitter = inject<Emitter<Events>>("emitter");
const onFilterChange = debounce(
@@ -174,15 +172,6 @@ const onFilterChange = debounce(
{ leading: false, trailing: true },
);
// Separate debounced function for search term changes
const onSearchChange = debounce(
async () => {
await fetchSearchFilters();
},
500,
{ leading: false, trailing: true },
);
emitter?.on("filterRoms", onFilterChange);
const filters = [
@@ -267,19 +256,6 @@ function resetFilters() {
});
}
async function fetchSearchFilters() {
// const { data } = await romApi.getRomFilters();
// galleryFilterStore.setFilterPlatforms([]);
// galleryFilterStore.setFilterGenres(data.genres);
// galleryFilterStore.setFilterFranchises(data.franchises);
// galleryFilterStore.setFilterCompanies(data.companies);
// galleryFilterStore.setFilterCollections([]);
// galleryFilterStore.setFilterAgeRatings(data.age_ratings);
// galleryFilterStore.setFilterRegions(data.regions);
// galleryFilterStore.setFilterLanguages(data.languages);
// galleryFilterStore.setFilterPlayerCounts(data.player_counts);
}
onMounted(async () => {
const {
search: urlSearch,
@@ -492,31 +468,10 @@ onMounted(async () => {
romsStore.resetPagination();
}
// Initial fetch of search-filtered ROMs for filter options
await fetchSearchFilters();
// 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 fetchSearchFilters();
},
{ immediate: false },
);
});
</script>

View File

@@ -9,6 +9,7 @@ import { attachGamepad } from "@/console/input/gamepad";
import { attachKeyboard } from "@/console/input/keyboard";
import { ROUTES } from "@/plugins/router";
import storeCollections from "@/stores/collections";
import storeGalleryFilter from "@/stores/galleryFilter";
import storeNavigation from "@/stores/navigation";
import storePlatforms from "@/stores/platforms";
@@ -20,6 +21,7 @@ provide(InputBusSymbol, bus);
const navigationStore = storeNavigation();
const platformsStore = storePlatforms();
const collectionsStore = storeCollections();
const galleryFilterStore = storeGalleryFilter();
const showVirtualCollections = useLocalStorage(
"settings.showVirtualCollections",
@@ -70,7 +72,7 @@ let detachKeyboard: (() => void) | null = null;
let detachGamepad: (() => void) | null = null;
onBeforeMount(() => {
platformsStore.fetchPlatforms();
platformsStore.fetchPlatforms({ galleryFilter: galleryFilterStore });
collectionsStore.fetchCollections();
collectionsStore.fetchSmartCollections();
if (showVirtualCollections) {

View File

@@ -23,6 +23,7 @@ import NewVersionDialog from "@/components/common/NewVersionDialog.vue";
import Notification from "@/components/common/Notifications/Notification.vue";
import UploadProgress from "@/components/common/Notifications/UploadProgress.vue";
import storeCollections from "@/stores/collections";
import storeGalleryFilter from "@/stores/galleryFilter";
import storeNavigation from "@/stores/navigation";
import storePlatforms from "@/stores/platforms";
import type { Events } from "@/types/emitter";
@@ -30,10 +31,11 @@ import type { Events } from "@/types/emitter";
const navigationStore = storeNavigation();
const platformsStore = storePlatforms();
const collectionsStore = storeCollections();
const galleryFilterStore = storeGalleryFilter();
const emitter = inject<Emitter<Events>>("emitter");
emitter?.on("refreshDrawer", async () => {
platformsStore.fetchPlatforms();
platformsStore.fetchPlatforms({ galleryFilter: galleryFilterStore });
});
const showVirtualCollections = useLocalStorage(
@@ -56,7 +58,7 @@ function unhackNavbar() {
onBeforeMount(async () => {
document.addEventListener("network-quiesced", unhackNavbar);
platformsStore.fetchPlatforms();
platformsStore.fetchPlatforms({ galleryFilter: galleryFilterStore });
collectionsStore.fetchCollections();
collectionsStore.fetchSmartCollections();
if (showVirtualCollections) {

View File

@@ -2,8 +2,11 @@ import { uniqBy } from "lodash";
import { defineStore } from "pinia";
import type { PlatformSchema } from "@/__generated__";
import platformApi from "@/services/api/platform";
import storeGalleryFilter from "@/stores/galleryFilter";
import type { ExtractPiniaStoreType } from "@/types";
export type Platform = PlatformSchema;
type GalleryFilterStore = ExtractPiniaStoreType<typeof storeGalleryFilter>;
export default defineStore("platforms", {
state: () => ({
@@ -35,7 +38,11 @@ export default defineStore("platforms", {
return a.name.localeCompare(b.name);
});
},
fetchPlatforms(): Promise<Platform[]> {
fetchPlatforms({
galleryFilter,
}: {
galleryFilter: GalleryFilterStore;
}): Promise<Platform[]> {
if (this.fetchingPlatforms) return Promise.resolve([]);
this.fetchingPlatforms = true;
@@ -44,6 +51,7 @@ export default defineStore("platforms", {
.getPlatforms()
.then(({ data: platforms }) => {
this.allPlatforms = platforms;
galleryFilter.setFilterPlatforms(platforms);
resolve(platforms);
})
.catch((error) => {

View File

@@ -171,8 +171,7 @@ export default defineStore("roms", {
this.romIdIndex = rom_id_index;
if (filter_values) {
galleryFilter.setFilterPlatforms([]);
galleryFilter.setFilterCollections([]);
galleryFilter.setFilterCollections(filter_values.collections);
galleryFilter.setFilterGenres(filter_values.genres);
galleryFilter.setFilterFranchises(filter_values.franchises);
galleryFilter.setFilterCompanies(filter_values.companies);