From 6cd10d0b3726704cb07810732a5a3223c0005604 Mon Sep 17 00:00:00 2001 From: zurdi Date: Thu, 18 Dec 2025 16:48:57 +0000 Subject: [PATCH] refactor: update existing platforms structure to include rom counts and simplify related logic in Setup.vue and API --- backend/endpoints/heartbeat.py | 31 ++++--- .../components/Setup/PlatformGroupList.vue | 1 - frontend/src/services/api/setup.ts | 8 +- frontend/src/views/Auth/Setup.vue | 87 +++++++++++-------- 4 files changed, 72 insertions(+), 55 deletions(-) diff --git a/backend/endpoints/heartbeat.py b/backend/endpoints/heartbeat.py index bd52ffb66..9bcfe54af 100644 --- a/backend/endpoints/heartbeat.py +++ b/backend/endpoints/heartbeat.py @@ -171,8 +171,7 @@ async def get_setup_library_info(): Returns: - detected_structure: "A" (roms/{platform}), "B" ({platform}/roms), or None - - existing_platforms: list of platform fs_slugs already in filesystem - - platform_game_counts: dict mapping platform fs_slug to game count + - existing_platforms: list of objects with fs_slug and rom_count - supported_platforms: list of all supported platforms with metadata """ @@ -187,15 +186,16 @@ async def get_setup_library_info(): # Get existing platforms from filesystem try: - existing_platforms = await fs_platform_handler.get_platforms() + existing_platform_slugs = await fs_platform_handler.get_platforms() except Exception: - existing_platforms = [] + existing_platform_slugs = [] - # Count games for each existing platform - platform_game_counts = {} - if detected_structure and existing_platforms: + # Build existing platforms with rom counts + existing_platforms = [] + if detected_structure and existing_platform_slugs: cnfg = cm.get_config() - for fs_slug in existing_platforms: + for fs_slug in existing_platform_slugs: + rom_count = 0 try: # Determine the roms directory based on structure if detected_structure == "A": @@ -211,7 +211,7 @@ async def get_setup_library_info(): if os.path.exists(roms_path): items = os.listdir(roms_path) # Filter out hidden files and system files - game_count = len( + rom_count = len( [ item for item in items @@ -219,11 +219,15 @@ async def get_setup_library_info(): and item not in ["_resources", "_cache"] ] ) - platform_game_counts[fs_slug] = game_count - else: - platform_game_counts[fs_slug] = 0 except Exception: - platform_game_counts[fs_slug] = 0 + pass + + existing_platforms.append( + { + "fs_slug": fs_slug, + "rom_count": rom_count, + } + ) # Get all supported platforms with metadata supported_platforms = get_supported_platforms() @@ -231,7 +235,6 @@ async def get_setup_library_info(): return { "detected_structure": detected_structure, "existing_platforms": existing_platforms, - "platform_game_counts": platform_game_counts, "supported_platforms": supported_platforms, } diff --git a/frontend/src/components/Setup/PlatformGroupList.vue b/frontend/src/components/Setup/PlatformGroupList.vue index c91b33608..9d0f1fed2 100644 --- a/frontend/src/components/Setup/PlatformGroupList.vue +++ b/frontend/src/components/Setup/PlatformGroupList.vue @@ -11,7 +11,6 @@ const props = defineProps<{ baseIndex?: number; onToggleGroup?: (platforms: Platform[], checked: boolean) => void; isGroupFullySelected?: (platforms: Platform[]) => boolean; - platformGameCounts?: Record; }>(); const emit = defineEmits<{ diff --git a/frontend/src/services/api/setup.ts b/frontend/src/services/api/setup.ts index 9f1268ef7..d057b543c 100644 --- a/frontend/src/services/api/setup.ts +++ b/frontend/src/services/api/setup.ts @@ -3,10 +3,14 @@ import type { Platform } from "@/stores/platforms"; export type LibraryStructure = "A" | "B" | null; +export interface ExistingPlatform { + fs_slug: string; + rom_count: number; +} + export interface SetupLibraryInfo { detected_structure: LibraryStructure; - existing_platforms: string[]; - platform_game_counts: Record; + existing_platforms: ExistingPlatform[]; supported_platforms: Platform[]; } diff --git a/frontend/src/views/Auth/Setup.vue b/frontend/src/views/Auth/Setup.vue index a2e64e7e7..cc0160a17 100644 --- a/frontend/src/views/Auth/Setup.vue +++ b/frontend/src/views/Auth/Setup.vue @@ -158,27 +158,37 @@ const groupedExistingPlatforms = computed(() => { libraryInfo.value.supported_platforms.map((p) => p.fs_slug), ); + // Get existing platform slugs + const existingSlugs = libraryInfo.value.existing_platforms.map( + (p) => p.fs_slug, + ); + + // Create a lookup map for rom counts + const romCountMap = new Map( + libraryInfo.value.existing_platforms.map((p) => [p.fs_slug, p.rom_count]), + ); + // Get identified platforms (existing and in supported list) const identified = libraryInfo.value.supported_platforms - .filter((p) => libraryInfo.value?.existing_platforms.includes(p.fs_slug)) + .filter((p) => existingSlugs.includes(p.fs_slug)) .map((p) => ({ ...p, - rom_count: libraryInfo.value?.platform_game_counts?.[p.fs_slug] || 0, + rom_count: romCountMap.get(p.fs_slug) || 0, })); // Get unidentified platforms (existing but not in supported list) // Create Platform objects for them with family_name="Other" const unidentified = libraryInfo.value.existing_platforms - .filter((slug) => !supportedSlugs.has(slug)) + .filter((ep) => !supportedSlugs.has(ep.fs_slug)) .map( - (slug) => + (ep) => ({ - fs_slug: slug, - slug: slug, - name: slug, + fs_slug: ep.fs_slug, + slug: ep.fs_slug, + name: ep.fs_slug, family_name: "Other", generation: 999, - rom_count: libraryInfo.value?.platform_game_counts?.[slug] || 0, + rom_count: ep.rom_count, }) as Platform, ); @@ -189,11 +199,14 @@ const groupedExistingPlatforms = computed(() => { // Group available platforms (not existing) const groupedAvailablePlatforms = computed(() => { if (!libraryInfo.value) return []; + const existingSlugs = libraryInfo.value.existing_platforms.map( + (p) => p.fs_slug, + ); const available = libraryInfo.value.supported_platforms - .filter((p) => !libraryInfo.value?.existing_platforms.includes(p.fs_slug)) + .filter((p) => !existingSlugs.includes(p.fs_slug)) .map((p) => ({ ...p, - rom_count: libraryInfo.value?.platform_game_counts?.[p.fs_slug] || 0, + rom_count: 0, })); return groupPlatformsByManufacturer(available); }); @@ -207,7 +220,10 @@ const hasExistingPlatforms = computed(() => { // Check if platform already exists const isPlatformExisting = (fsSlug: string) => { - return libraryInfo.value?.existing_platforms.includes(fsSlug) ?? false; + return ( + libraryInfo.value?.existing_platforms.some((p) => p.fs_slug === fsSlug) ?? + false + ); }; // Watch grouped existing and available platforms to open all panels @@ -226,18 +242,19 @@ watch( watch(selectAll, (newValue) => { if (!libraryInfo.value) return; + const existingSlugs = libraryInfo.value.existing_platforms.map( + (p) => p.fs_slug, + ); + if (newValue) { // Select all available platforms (exclude existing ones) const allAvailable = libraryInfo.value.supported_platforms - .filter((p) => !isPlatformExisting(p.fs_slug)) + .filter((p) => !existingSlugs.includes(p.fs_slug)) .map((p) => p.fs_slug); - selectedPlatforms.value = [ - ...libraryInfo.value.existing_platforms, - ...allAvailable, - ]; + selectedPlatforms.value = [...existingSlugs, ...allAvailable]; } else { // Keep only existing platforms selected - selectedPlatforms.value = [...libraryInfo.value.existing_platforms]; + selectedPlatforms.value = [...existingSlugs]; } }); @@ -265,17 +282,17 @@ function isGroupFullySelected(platforms: Platform[]) { // Compute the count of selected available platforms (excluding existing ones) const selectedAvailableCount = computed(() => { - const existingPlatforms = libraryInfo.value?.existing_platforms || []; - return selectedPlatforms.value.filter( - (slug) => !existingPlatforms.includes(slug), - ).length; + const existingSlugs = + libraryInfo.value?.existing_platforms.map((p) => p.fs_slug) || []; + return selectedPlatforms.value.filter((slug) => !existingSlugs.includes(slug)) + .length; }); // Compute the total game count for detected platforms const totalDetectedGames = computed(() => { - if (!libraryInfo.value?.platform_game_counts) return 0; - return Object.values(libraryInfo.value.platform_game_counts).reduce( - (total, count) => total + count, + if (!libraryInfo.value?.existing_platforms) return 0; + return libraryInfo.value.existing_platforms.reduce( + (total, p) => total + p.rom_count, 0, ); }); @@ -312,11 +329,12 @@ function handleNext(nextCallback: () => void) { } // Case 3: Structure is detected and user selected at least one platform to create - if (hasStructure && platformsToCreate.length > 0) { - const structureType = hasStructure === "A" ? "A" : "B"; + if (hasStructure && platformsToCreate.length > 0 && libraryInfo.value) { const structurePattern = - hasStructure === "A" ? "roms/{platform}" : "{platform}/roms"; - confirmDialogMessage.value = `RomM will create Structure ${structureType} (${structurePattern}) with ${ + libraryInfo.value.detected_structure === "A" + ? "roms/{platform}" + : "{platform}/roms"; + confirmDialogMessage.value = `RomM will create Structure ${libraryInfo.value.detected_structure} (${structurePattern}) with ${ platformsToCreate.length } platform${platformsToCreate.length > 1 ? "s" : ""}. Continue?`; confirmDialogAction.value = nextCallback; @@ -343,7 +361,9 @@ async function loadLibraryInfo() { libraryInfo.value = response.data; // Pre-check existing platforms - selectedPlatforms.value = [...(libraryInfo.value.existing_platforms || [])]; + selectedPlatforms.value = [ + ...(libraryInfo.value.existing_platforms.map((p) => p.fs_slug) || []), + ]; } catch (error: any) { emitter?.emit("snackbarShow", { msg: `Failed to load library info: ${ @@ -541,9 +561,6 @@ onMounted(() => {
@@ -624,9 +641,6 @@ onMounted(() => { @@ -805,9 +819,6 @@ onMounted(() => { width="500" @close="showConfirmDialog = false" > -