From b85ca7c3cf8de7f8f4b2952d3af767efd824a064 Mon Sep 17 00:00:00 2001 From: Trit0 Date: Mon, 15 Sep 2025 20:43:45 -0400 Subject: [PATCH] show case data --- app.go | 9 +- frontend/src/App.vue | 4 +- frontend/src/components/OptionsModal.vue | 22 +++- .../key-contexts/game-preview-key-context.ts | 3 +- .../key-contexts/options-key-context.ts | 105 ++++++++++++++++++ frontend/src/services/game-service.ts | 8 +- frontend/src/stores/app-store.ts | 11 +- frontend/wailsjs/go/main/App.d.ts | 2 +- frontend/wailsjs/go/main/App.js | 4 +- lib/config/config.go | 1 + lib/provider/provider.go | 22 ++-- 11 files changed, 170 insertions(+), 21 deletions(-) diff --git a/app.go b/app.go index d21ea79..91f039f 100644 --- a/app.go +++ b/app.go @@ -98,8 +98,15 @@ func (a *App) StartGame(id string) { fmt.Println() } -func (a *App) LoadGames() []models.Metadata { +func (a *App) LoadGames(mode string) []models.Metadata { games = provider.GetConjureGameInfo() + + if mode == "remote-showcase" { + games = provider.Filter(games, func(game models.Metadata) bool { + return game.Game == "Soul Shaper" || game.Game == "One Pixel Remaning" || game.Game == "Pong" + }) + } + return games } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 7e27ab5..156a89a 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -30,8 +30,8 @@ - - + + diff --git a/frontend/src/components/OptionsModal.vue b/frontend/src/components/OptionsModal.vue index 36a9581..654afab 100644 --- a/frontend/src/components/OptionsModal.vue +++ b/frontend/src/components/OptionsModal.vue @@ -9,6 +9,7 @@ @@ -28,15 +29,34 @@ diff --git a/frontend/src/inputs/key-contexts/game-preview-key-context.ts b/frontend/src/inputs/key-contexts/game-preview-key-context.ts index 39accdb..10eb868 100644 --- a/frontend/src/inputs/key-contexts/game-preview-key-context.ts +++ b/frontend/src/inputs/key-contexts/game-preview-key-context.ts @@ -1,5 +1,6 @@ import { KeyContext } from "./key-context"; import { InputManager } from "../input-manager"; +import { mod } from "../../stores/app-store"; export class GamePreviewKeyContext extends KeyContext { readonly name: string = "GamePreviewKeyContext"; @@ -58,7 +59,7 @@ export class GamePreviewKeyContext extends KeyContext { .filter(el => (el as any).offsetParent !== null); // filter out hidden elements const currentIndex = focusableElements.indexOf(document.activeElement); - const nextIndex = (currentIndex - 1) % focusableElements.length; + const nextIndex = mod((currentIndex - 1), focusableElements.length); (focusableElements[nextIndex] as any).focus(); } diff --git a/frontend/src/inputs/key-contexts/options-key-context.ts b/frontend/src/inputs/key-contexts/options-key-context.ts index 5993573..14887e1 100644 --- a/frontend/src/inputs/key-contexts/options-key-context.ts +++ b/frontend/src/inputs/key-contexts/options-key-context.ts @@ -1,5 +1,7 @@ import { InputManager } from "../input-manager"; import { ModalKeyContext } from "./modal-key-context"; +import { log } from "../../services/logger-service"; +import { mod } from "../../stores/app-store"; export class OptionsKeyContext extends ModalKeyContext { public name: string = "OptionsKeyContext"; @@ -8,7 +10,110 @@ export class OptionsKeyContext extends ModalKeyContext { super.onEscape(); this.store.optionsOpen = false; this.store.qrLink = ""; + (document.activeElement as any).blur(); InputManager.switchContext('carousel'); } + protected onKeyUp() { + super.onKeyUp(); + this.focusLastElement() + } + + protected onKeyDown() { + super.onKeyDown(); + this.focusNextElement(); + } + + private focusNextElement() { + const focusableSelectors = [ + 'a[href]', + 'button:not([disabled])', + 'input:not([disabled]):not([type="hidden"])', + 'select:not([disabled])', + 'textarea:not([disabled])', + '[tabindex]:not([tabindex="-1"])' + ]; + + const focusableElements = Array.from(document.querySelectorAll(focusableSelectors.join(','))) + .filter(el => (el as any).offsetParent !== null); // filter out hidden elements + + const currentIndex = focusableElements.indexOf(document.activeElement); + const nextIndex = (currentIndex + 1) % focusableElements.length; + + (focusableElements[nextIndex] as any).focus(); + } + + protected onEnter() { + super.onEnter(); + const activeElement = document.activeElement; + console.log(activeElement); + (document.activeElement as any).click(); + } + + private focusLastElement() { + const focusableSelectors = [ + 'a[href]', + 'button:not([disabled])', + 'input:not([disabled]):not([type="hidden"])', + 'select:not([disabled])', + 'textarea:not([disabled])', + '[tabindex]:not([tabindex="-1"])' + ]; + + const focusableElements = Array.from(document.querySelectorAll(focusableSelectors.join(','))) + .filter(el => (el as any).offsetParent !== null); // filter out hidden elements + + const currentIndex = focusableElements.indexOf(document.activeElement); + const nextIndex = mod((currentIndex - 1), focusableElements.length); + + (focusableElements[nextIndex] as any).focus(); + } + + protected onKeyRight() { + super.onKeyRight(); + + const activeElement = document.activeElement; + if (activeElement.tagName.toLowerCase() === 'select') { + const mySelect = document.activeElement as HTMLSelectElement; + const currentIndex = mySelect.selectedIndex; + mySelect.selectedIndex = (currentIndex + 1) % mySelect.options.length; + } + else if (activeElement && activeElement.tagName.toLowerCase() === 'input' && (activeElement as HTMLInputElement).type === 'range') { + // Get the current value, convert to number, add 10, and set the new value + const range = (activeElement as HTMLInputElement); + let currentValue = parseInt(range.value); + range.value = (currentValue + 10).toString(); + } + else { + this.focusNextElement(); + } + } + + protected onKeyLeft() { + super.onKeyLeft(); + const activeElement = document.activeElement; + if (activeElement.tagName.toLowerCase() === 'select') { + const mySelect = document.activeElement as HTMLSelectElement; + const currentIndex = mySelect.selectedIndex; + mySelect.selectedIndex = mod((currentIndex - 1), mySelect.options.length); + } + else if (activeElement && activeElement.tagName.toLowerCase() === 'input' && (activeElement as HTMLInputElement).type === 'range') { + // Get the current value, convert to number, add 10, and set the new value + const range = (activeElement as HTMLInputElement); + let currentValue = parseInt(range.value); + range.value = (currentValue - 10).toString(); + } + else { + this.focusLastElement(); + } + } + + setAvailableActions() { + this.store.currentAvailableActions = { + "order": "controller,keyboard", + "1,Enter": "Click", + "Power,Escape": "Back" + }; + } + } \ No newline at end of file diff --git a/frontend/src/services/game-service.ts b/frontend/src/services/game-service.ts index 660518c..5882d53 100644 --- a/frontend/src/services/game-service.ts +++ b/frontend/src/services/game-service.ts @@ -4,7 +4,7 @@ import Metadata = models.Metadata; import Game = models.Game; import Developer = models.Developer; -const localGames: Game[] = [ +const mockGames: Game[] = [ new Game({ id: "ddf1ab0c-d86e-442f-8fd8-cfe8a0dc0a52", title: "Soul Shaper", @@ -98,13 +98,13 @@ const localGames: Game[] = [ export async function fetchGames(): Promise { const source = localStorage.getItem('dataSource') || 'local'; - if (source === 'local') return localGames; + if (source === 'local') return mockGames; - const games = await LoadGames(); + const games = (await LoadGames(source)) ?? []; for (const game of games) { console.log(game) } - return [...games.map(convertToNewFormat), ...localGames]; + return [...games.map(convertToNewFormat)]; } function convertToNewFormat(metadata: Metadata): Game { diff --git a/frontend/src/stores/app-store.ts b/frontend/src/stores/app-store.ts index 1eefc5b..aa60a37 100644 --- a/frontend/src/stores/app-store.ts +++ b/frontend/src/stores/app-store.ts @@ -34,8 +34,10 @@ export const useAppStore = defineStore('app', { console.log(this.games); this.tags = [...new Set(this.games.flatMap(game => game.genres.split(",")))]; if (this.tags.length > 0) { - this.selectTag(this.tags[0]) + this.selectTag(this.tags[0]); } + + this.selectGame(0); }, moveGameRight() { this.selectGame(this.selectedGameIndex + 1); @@ -69,6 +71,11 @@ export const useAppStore = defineStore('app', { this.qrLink = link; InputManager.switchContext("options"); }, + closeModal() { + this.qrLink = ""; + this.optionsOpen = false; + InputManager.switchContext("carousel"); + }, async startSelectedGame() { if (this.selectedGame && !this.gameIsStarting) { this.gameIsStarting = true; @@ -82,6 +89,6 @@ export const useAppStore = defineStore('app', { } }); -function mod(n, m) { +export function mod(n, m) { return ((n % m) + m) % m; } \ No newline at end of file diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 2f9f48b..9ef1b79 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -3,7 +3,7 @@ import {models} from '../models'; import {provider} from '../models'; -export function LoadGames():Promise>; +export function LoadGames(arg1:string):Promise>; export function LoadGamesNewModel():Promise>; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 6d199b0..43b9641 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,8 +2,8 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -export function LoadGames() { - return window['go']['main']['App']['LoadGames'](); +export function LoadGames(arg1) { + return window['go']['main']['App']['LoadGames'](arg1); } export function LoadGamesNewModel() { diff --git a/lib/config/config.go b/lib/config/config.go index 22e5bed..a3a11c3 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -31,6 +31,7 @@ func GetDefaultConjureOsDirectory() string { case "windows": return filepath.Join(cacheDir, conjureDirectoryName, conjureOsDirectoryName) case "darwin": + return filepath.Join(configDir, conjureDirectoryName, conjureOsDirectoryName) case "linux": return filepath.Join(configDir, conjureDirectoryName, conjureOsDirectoryName) default: diff --git a/lib/provider/provider.go b/lib/provider/provider.go index c9cb432..70883c6 100644 --- a/lib/provider/provider.go +++ b/lib/provider/provider.go @@ -182,16 +182,14 @@ func ExtractGame(game models.Metadata) string { func GetConjureGameInfo() []models.Metadata { gamePath := config.GetDefaultConjureGamesDirectory() - fmt.Println("Loading games....") - fmt.Println(gamePath) + fmt.Println("Loading games from path " + gamePath + "....") + var games []models.Metadata entries, err := os.ReadDir(gamePath) if err != nil { - log.Fatal(err) + return games } - var games []models.Metadata - for _, e := range entries { if e.IsDir() { continue @@ -228,13 +226,23 @@ func GetConjureGameInfo() []models.Metadata { } if len(games) > 0 { - fmt.Println("Found Conjure Games:", len(games)) + fmt.Println("Found Conjure Games: ", len(games)) } else { - fmt.Println("No Conjure games Found") + fmt.Println("No Conjure games found") } return games } +func Filter[T any](s []T, predicate func(T) bool) []T { + result := make([]T, 0, len(s)) // Pre-allocate for efficiency + for _, v := range s { + if predicate(v) { + result = append(result, v) + } + } + return result +} + // Function to escape backslashes in the YAML string func escapeBackslashes(input string) string { // Replace every single backslash with double backslashes