fix a couple of stuff

This commit is contained in:
Trit0 2025-07-18 19:43:49 -04:00 committed by TristanBrault
parent 0ab4b1f832
commit 09fcc8f76d
24 changed files with 95 additions and 62 deletions

4
app.go
View File

@ -107,6 +107,10 @@ func (a *App) LoadGamesNewModel() []models.Game {
return []models.Game{}
}
func (a *App) Log(message string) {
fmt.Println(message)
}
func (a *App) LoadImage(gameId string, imageSrc string) provider.FileBlob {
blob := provider.LoadImage(gameId, imageSrc)

BIN
build/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -44,10 +44,8 @@ import GameCarousel from './components/GameCarousel.vue';
import OptionsModal from './components/OptionsModal.vue';
import QrModal from './components/QrModal.vue';
import LoadingModal from './components/LoadingModal.vue';
import { useKeyboardNavigation } from './utils/use-keyboard-navigation';
import { useAppStore } from "./stores/app-store";
import { storeToRefs } from "pinia";
import { KeyboardManager } from "./utils/keyboard-manager";
import CurrentActionsHelp from "./components/CurrentActionsHelp.vue";
const store = useAppStore();
@ -77,15 +75,7 @@ const backgroundStyle = computed(() => {
return {
backgroundImage
};
});
if (showSidebar) {
KeyboardManager.switchContext("sidebar")
} else {
KeyboardManager.switchContext("carousel")
}
useKeyboardNavigation();
</script>
<style scoped>

View File

@ -1,5 +1,5 @@
<template>
<div class="bg-black min-h-10 border-1 border-gray-500">
<div class="bg-black min-h-10">
<div v-if="currentActions" class="flex justify-around w-full h-full items-center px-4">
<span v-for="tip in currentActions"> {{ tip }} </span>
</div>

View File

@ -1,6 +1,6 @@
<template>
<div class="dev-card flex border-1 rounded p-2 border-gray-300 gap-3 items-center" :tabindex="!!tabbable ? 1 : -1" @click="$emit('click')">
<div class="dev-card flex border-1 rounded p-2 border-gray-300 gap-3 items-center" :tabindex="!!tabbable ? 10 : -1" @click="$emit('click')">
<div>
<img v-if="!!picture && !useIcon" :src="picture" alt="picture" class="w-14 rounded-full" />
<Icon v-else-if="!!picture" :icon="picture" class="w-10 h-10"/>

View File

@ -1,5 +1,5 @@
<template>
<div class="p-6 h-full w-full overflow-auto flex flex-col items-center">
<div id="preview" class="p-6 h-full w-full overflow-auto flex flex-col items-center">
<div v-if="game" class="space-y-4 flex flex-col items-center w-full max-w-400">
<img v-if="game.logoPath" :src="game.logoPath" :alt="game.title" class="h-72"/>
<h1 v-else class="text-4xl font-bold py-8">{{ game.title }}</h1>
@ -32,12 +32,12 @@
<!-- class="rounded-lg border border-gray-600 max-h-48 object-cover basis-1/4"/>-->
<div class="flex flex-col basis-1/4 gap-2">
<CustomCard title="Number of players" :content="game.players + ' players'" :tabbable=true :use-icon=true picture="fluent:person-24-filled" />
<CustomCard title="Genres" :content="game.genres.split(',').map(s => toUpperCamelCase(s.trim())).join(', ')" :tabbable=true :use-icon=true picture="fluent:apps-list-detail-24-filled" />
<CustomCard title="Collections" :content="game.collections" :tabbable=true :use-icon=true picture="fluent:collections-empty-24-filled" />
<CustomCard title="Updated" :content="game.modification" :tabbable=true :use-icon=true picture="fluent:arrow-upload-24-filled" />
<CustomCard title="Release" :content="game.release" :tabbable=true :use-icon=true picture="fluent:clock-24-filled" />
<CustomCard title="Version" :content="game.version" :tabbable=true :use-icon=true picture="fluent:tag-24-filled" />
<CustomCard title="Number of players" :content="game.players + ' players'" :tabbable=false :use-icon=true picture="fluent:person-24-filled" />
<CustomCard title="Genres" :content="game.genres.split(',').map(s => toUpperCamelCase(s.trim())).join(', ')" :tabbable=false :use-icon=true picture="fluent:apps-list-detail-24-filled" />
<CustomCard title="Collections" :content="game.collections" :tabbable=false :use-icon=true picture="fluent:collections-empty-24-filled" />
<CustomCard title="Updated" :content="game.modification" :tabbable=false :use-icon=true picture="fluent:arrow-upload-24-filled" />
<CustomCard title="Release" :content="game.release" :tabbable=false :use-icon=true picture="fluent:clock-24-filled" />
<CustomCard title="Version" :content="game.version" :tabbable=false :use-icon=true picture="fluent:tag-24-filled" />
</div>
</div>
@ -47,6 +47,7 @@
v-if="game.executable"
id="btn-play"
key="play"
tabindex="0"
:style="buttonStyle"
@click="store.startSelectedGame()"
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
@ -56,7 +57,9 @@
<button
v-if="game.publicRepositoryLink"
id="btn-repo"
key="repo"
tabindex="0"
:style="buttonStyle"
@click="$emit('qr', game.publicRepositoryLink)"
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
@ -66,7 +69,9 @@
<button
v-if="game.itchLink"
id="btn-itch"
key="itch"
tabindex="0"
:style="buttonStyle"
@click="$emit('qr', game.itchLink)"
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"

View File

@ -17,10 +17,8 @@
<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import LocalImage from "./LocalImage.vue";
import { models } from "../../wailsjs/go/models";
import Game = models.Game;
const props = defineProps<{
links: string[],
@ -35,19 +33,28 @@ const imag = computed(() => {
return "";
});
watch(() => [props.gameId], async () => {
index.value = -1;
changeImage();
}, { immediate: true });
function delay(time: number) {
return new Promise(resolve => setTimeout(resolve, time));
}
function changeImage() {
index.value = (index.value + 1) % props.links?.length;
}
function clock() {
delay(3000).then(() => {
index.value = (index.value + 1) % props.links?.length;
changeImage();
clock();
});
}
onMounted(() => {
changeImage();
clock();
})
</script>

View File

@ -11,7 +11,7 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { ImageManager } from "../utils/image-manager";
import { ImageService } from "../services/image-service";
const props = defineProps<{
gameId: string
@ -22,6 +22,6 @@ const props = defineProps<{
const blobUrl = ref<string | null>(null);
watch(() => [props.src, props.gameId], async ([newUrl, key]) => {
blobUrl.value = await ImageManager.getImage(key, newUrl);
blobUrl.value = await ImageService.getImage(key, newUrl);
}, { immediate: true });
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50">
<div class="fixed inset-0 bg-color flex items-center justify-center z-50">
<div class="bg-white text-black p-6 rounded-lg w-full max-w-md">
<h2 class="text-2xl font-bold mb-4">Options</h2>
@ -40,3 +40,9 @@ function save() {
emit('close');
}
</script>
<style scoped>
.bg-color {
background-color: rgba(0, 0, 0, 0.75);
}
</style>

View File

@ -4,10 +4,13 @@ import { KeyContext } from "./key-contexts/key-context";
import { OptionsKeyContext } from "./key-contexts/options-key-context";
import { SidebarKeyContext } from "./key-contexts/sidebar-key-context";
import { GamePreviewKeyContext } from "./key-contexts/game-preview-key-context";
import { EventsOn } from "../../wailsjs/runtime";
import { log } from "../services/logger-service";
export class KeyboardManager {
export class InputManager {
private static current?: KeyContext;
public static loaded = false;
public static loadedCount = 0;
static switchContext(name: 'sidebar' | 'carousel' | 'options' | 'preview') {
console.log("Switching context to " + name);
@ -38,4 +41,16 @@ export class KeyboardManager {
static handleState(controllerState: ControllerState) {
this.current?.handleState(controllerState);
}
static bind() {
console.log("Trying to load inputs")
if (!InputManager.loaded) {
log("Loading inputs");
EventsOn("controller_change", InputManager.handleState.bind(InputManager));
window.addEventListener('keydown', InputManager.handle.bind(InputManager));
InputManager.loaded = true;
InputManager.loadedCount += 1;
log(InputManager.loadedCount);
}
}
}

View File

@ -1,5 +1,5 @@
import { KeyContext } from "./key-context";
import { KeyboardManager } from "../keyboard-manager";
import { InputManager } from "../input-manager";
export class CarouselKeyContext extends KeyContext {
readonly name: string = "CarouselContext";
@ -26,7 +26,7 @@ export class CarouselKeyContext extends KeyContext {
protected onKeyLeft() {
super.onKeyLeft();
if (this.store.selectedGameIndex === 0 && this.store.showSidebar) {
KeyboardManager.switchContext("sidebar");
InputManager.switchContext("sidebar");
this.store.selectGame(-1);
}
else {
@ -37,7 +37,7 @@ export class CarouselKeyContext extends KeyContext {
protected onEscape() {
super.onEscape();
this.store.optionsOpen = true;
KeyboardManager.switchContext("options");
InputManager.switchContext("options");
}
protected onEnter() {
@ -48,12 +48,22 @@ export class CarouselKeyContext extends KeyContext {
protected onSpace() {
super.onSpace();
if (this.store.selectedGameIndex !== -1) {
KeyboardManager.switchContext("preview");
InputManager.switchContext("preview");
const playBtn = document.getElementById("btn-play");
const repoBtn = document.getElementById("btn-repo");
const itchBtn = document.getElementById("btn-itch");
const preview = document.getElementById("preview");
if (playBtn) {
playBtn.focus();
} else if (repoBtn) {
repoBtn.focus();
} else if (itchBtn) {
itchBtn.focus();
} else {
preview.focus();
}
}
}

View File

@ -1,5 +1,5 @@
import { KeyContext } from "./key-context";
import { KeyboardManager } from "../keyboard-manager";
import { InputManager } from "../input-manager";
export class GamePreviewKeyContext extends KeyContext {
readonly name: string = "GamePreviewKeyContext";
@ -81,7 +81,7 @@ export class GamePreviewKeyContext extends KeyContext {
protected onEscape() {
super.onEscape();
(document.activeElement as any).blur();
KeyboardManager.switchContext("carousel");
InputManager.switchContext("carousel");
}
setAvailableActions() {

View File

@ -8,6 +8,7 @@ export abstract class KeyContext {
public handleKey(event: KeyboardEvent): void {
this.store.currentInputDevice = "keyboard";
event.preventDefault();
switch (event.key) {
case 'ArrowRight':

View File

@ -1,4 +1,4 @@
import { KeyboardManager } from "../keyboard-manager";
import { InputManager } from "../input-manager";
import { ModalKeyContext } from "./modal-key-context";
export class OptionsKeyContext extends ModalKeyContext {
@ -8,7 +8,7 @@ export class OptionsKeyContext extends ModalKeyContext {
super.onEscape();
this.store.optionsOpen = false;
this.store.qrLink = "";
KeyboardManager.switchContext('carousel');
InputManager.switchContext('carousel');
}
}

View File

@ -1,5 +1,5 @@
import { KeyContext } from "./key-context";
import { KeyboardManager } from "../keyboard-manager";
import { InputManager } from "../input-manager";
export class SidebarKeyContext extends KeyContext {
readonly name: string = "SidebarContext";
@ -17,13 +17,13 @@ export class SidebarKeyContext extends KeyContext {
protected onKeyRight() {
super.onKeyRight();
this.store.moveGameRight();
KeyboardManager.switchContext("carousel")
InputManager.switchContext("carousel")
}
protected onEnter() {
super.onEnter();
this.store.moveGameRight();
KeyboardManager.switchContext("carousel")
InputManager.switchContext("carousel")
}
protected onEscape() {

View File

@ -2,7 +2,10 @@ import {createApp} from 'vue'
import App from './App.vue'
import './style.css';
import { createPinia } from "pinia";
import { InputManager } from "./inputs/input-manager";
const app = createApp(App);
app.use(createPinia());
app.mount('#app');
InputManager.bind();
InputManager.switchContext("carousel")

View File

@ -1,6 +1,6 @@
import { LoadImage } from "../../wailsjs/go/main/App";
export class ImageManager {
export class ImageService {
static Dictionary: {[key: string]: string} = {}

View File

@ -0,0 +1,6 @@
import { Log } from "../../wailsjs/go/main/App";
export function log(msg: any): void {
console.log(msg)
Log("[Frontend] " + msg.toString()).then();
}

View File

@ -3,7 +3,7 @@ import {models} from "../../wailsjs/go/models";
import Game = models.Game;
import { StartGame } from "../../wailsjs/go/main/App";
import { fetchGames } from '../services/game-service';
import { KeyboardManager } from '../utils/keyboard-manager';
import { InputManager } from '../inputs/input-manager';
export const useAppStore = defineStore('app', {
state: () => ({
@ -67,7 +67,7 @@ export const useAppStore = defineStore('app', {
},
showQr(link: string) {
this.qrLink = link;
KeyboardManager.switchContext("options");
InputManager.switchContext("options");
},
async startSelectedGame() {
if (this.selectedGame && !this.gameIsStarting) {

View File

@ -1,20 +0,0 @@
import { onMounted } from 'vue';
import { KeyboardManager } from "./keyboard-manager";
import { EventsOn } from "../../wailsjs/runtime";
export function useKeyboardNavigation(): void {
onMounted(() => {
if (KeyboardManager.loaded) {
console.log("Unloading inputs");
window.removeEventListener('keydown', KeyboardManager.handle.bind(KeyboardManager));
KeyboardManager.loaded = false;
}
if (!KeyboardManager.loaded) {
console.log("Loading inputs")
EventsOn("controller_change", KeyboardManager.handleState.bind(KeyboardManager));
window.addEventListener('keydown', KeyboardManager.handle.bind(KeyboardManager));
KeyboardManager.loaded = true;
}
});
}

View File

@ -9,4 +9,6 @@ export function LoadGamesNewModel():Promise<Array<models.Game>>;
export function LoadImage(arg1:string,arg2:string):Promise<provider.FileBlob>;
export function Log(arg1:string):Promise<void>;
export function StartGame(arg1:string):Promise<void>;

View File

@ -14,6 +14,10 @@ export function LoadImage(arg1, arg2) {
return window['go']['main']['App']['LoadImage'](arg1, arg2);
}
export function Log(arg1) {
return window['go']['main']['App']['Log'](arg1);
}
export function StartGame(arg1) {
return window['go']['main']['App']['StartGame'](arg1);
}