control helper and cute tags
This commit is contained in:
parent
87f34a05db
commit
5cec1493f6
22
frontend/package-lock.json
generated
22
frontend/package-lock.json
generated
@ -15,6 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.18.10",
|
||||
"@iconify/vue": "^5.0.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
@ -512,6 +513,27 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify/types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
|
||||
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@iconify/vue": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/vue/-/vue-5.0.0.tgz",
|
||||
"integrity": "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@iconify/types": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/cyberalien"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.18.10",
|
||||
"@iconify/vue": "^5.0.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
|
||||
@ -1 +1 @@
|
||||
0d0407303e68412fce4ec212f727db35
|
||||
063583417fe9e58bc0e2d6b154be7c49
|
||||
@ -25,9 +25,7 @@
|
||||
@selectGame="store.selectGame"
|
||||
class="mb-2"
|
||||
/>
|
||||
<div class="bg-black min-h-10 border-1 border-gray-500">
|
||||
|
||||
</div>
|
||||
<CurrentActionsHelp />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -47,17 +45,16 @@ 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 { fetchGames } from './services/game-service';
|
||||
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();
|
||||
const {
|
||||
selectedTag,
|
||||
selectedGame,
|
||||
tags,
|
||||
games,
|
||||
transitionDirection,
|
||||
qrLink,
|
||||
gameIsStarting,
|
||||
|
||||
51
frontend/src/components/CurrentActionsHelp.vue
Normal file
51
frontend/src/components/CurrentActionsHelp.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div class="bg-black min-h-10 border-1 border-gray-500">
|
||||
<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>
|
||||
<div v-else>
|
||||
<span>Chungus</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import { useAppStore } from "../stores/app-store";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed } from "vue";
|
||||
|
||||
const store = useAppStore();
|
||||
const {
|
||||
currentInputDevice,
|
||||
currentAvailableActions,
|
||||
} = storeToRefs(store);
|
||||
|
||||
const currentActions = computed(() => {
|
||||
const { order, ...rest } = currentAvailableActions.value as any;
|
||||
|
||||
console.log(order, rest);
|
||||
|
||||
if (!order) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const possibleControllers = order.split(",");
|
||||
const index = possibleControllers.findIndex(controller => controller === currentInputDevice.value);
|
||||
const list = [];
|
||||
console.log(index);
|
||||
console.log(rest);
|
||||
for (const [key, value] of Object.entries(rest)) {
|
||||
console.log(key, value);
|
||||
const split = key.split(",");
|
||||
const myKey = split[index];
|
||||
list.push(`${myKey}: ${rest[key]}`);
|
||||
}
|
||||
return list;
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
34
frontend/src/components/CustomCard.vue
Normal file
34
frontend/src/components/CustomCard.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<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>
|
||||
<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"/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-sm">{{ title }}</span>
|
||||
<span>{{ content }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
import { models } from "../../wailsjs/go/models";
|
||||
import Developer = models.Developer;
|
||||
|
||||
defineProps<{
|
||||
title: string,
|
||||
content: string,
|
||||
picture: string,
|
||||
useIcon: boolean,
|
||||
tabbable: boolean,
|
||||
}>();
|
||||
|
||||
defineEmits(['click']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
|
||||
<div class="dev-card flex border-1 rounded p-2 border-gray-300 gap-3" tabindex="0" @click="$emit('qr', dev.link)">
|
||||
<img v-if="dev.picture" :src="dev.picture" class="w-14 rounded-full" />
|
||||
<img v-else src="../assets/images/person.png" class="w-14" />
|
||||
<img v-if="dev.picture" :src="dev.picture" alt="picture" class="w-14 rounded-full" />
|
||||
<Icon v-else icon="fluent:person-circle-24-filled" class="w-14 h-14"/>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span>{{ dev.name }}</span>
|
||||
<span>{{ dev.role }}</span>
|
||||
@ -12,6 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
import { models } from "../../wailsjs/go/models";
|
||||
import Developer = models.Developer;
|
||||
|
||||
|
||||
@ -16,12 +16,12 @@
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div class="flex justify-between w-full space-y-1">
|
||||
<div class="flex justify-between w-full space-y-1 gap-6">
|
||||
<ImageCarousel
|
||||
v-if="game.mediaPaths"
|
||||
:gameId="game.id"
|
||||
:links="game.mediaPaths"
|
||||
class="basis-1/4"
|
||||
class="basis-3/4 h-full"
|
||||
/>
|
||||
<!-- <LocalImage-->
|
||||
<!-- v-for="(img, index) in [game.media_paths[0]]"-->
|
||||
@ -31,50 +31,53 @@
|
||||
<!-- :gameId="game.id"-->
|
||||
<!-- class="rounded-lg border border-gray-600 max-h-48 object-cover basis-1/4"/>-->
|
||||
|
||||
<div class="flex flex-col basis-1/4">
|
||||
<div class="text-md text-white">Players: {{ game.players }}</div>
|
||||
<div class="text-md text-white">Genres: {{ game.genres }}</div>
|
||||
<div class="text-md text-white">Collections: {{ game.collections }}</div>
|
||||
<div class="text-md text-white">Updated: {{ game.modification }}</div>
|
||||
<div class="text-md text-white">Released: {{ game.release }}</div>
|
||||
<div class="text-md text-white">Version: {{ game.version }}</div>
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 w-full flex items-start">
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
v-if="game.executable"
|
||||
id="btn-play"
|
||||
key="play"
|
||||
:style="buttonStyle"
|
||||
@click="store.startSelectedGame()"
|
||||
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
|
||||
>
|
||||
Play
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="game.publicRepositoryLink"
|
||||
key="repo"
|
||||
:style="buttonStyle"
|
||||
@click="$emit('qr', game.publicRepositoryLink)"
|
||||
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
|
||||
>
|
||||
Repo
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="game.itchLink"
|
||||
key="itch"
|
||||
:style="buttonStyle"
|
||||
@click="$emit('qr', game.itchLink)"
|
||||
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
|
||||
>
|
||||
Itch
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-lg w-full wrap min-h-15">{{ game.description }}</div>
|
||||
|
||||
|
||||
<div class="space-y-2 w-full flex items-start">
|
||||
<div class="flex gap-2 mt-2">
|
||||
<button
|
||||
v-if="game.executable"
|
||||
id="btn-play"
|
||||
key="play"
|
||||
:style="buttonStyle"
|
||||
@click="store.startSelectedGame()"
|
||||
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
|
||||
>
|
||||
Play
|
||||
</button>
|
||||
|
||||
<div
|
||||
v-for="(link, name) in {
|
||||
Repo: game?.publicRepositoryLink,
|
||||
Itch: game?.itchLink
|
||||
}">
|
||||
<button
|
||||
v-if="!!link"
|
||||
:key="name"
|
||||
:style="buttonStyle"
|
||||
class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-500 rounded-full text-2xl"
|
||||
@click="$emit('qr', link)"
|
||||
>
|
||||
{{ name }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex w-full items-start">
|
||||
<div class="flex gap-3 flex-wrap max-w-full">
|
||||
<DevCard
|
||||
@ -100,6 +103,8 @@ import { computed } from "vue";
|
||||
import DevCard from "./DevCard.vue";
|
||||
import { useAppStore } from "../stores/app-store";
|
||||
import ImageCarousel from "./ImageCarousel.vue";
|
||||
import CustomCard from "./CustomCard.vue";
|
||||
import { toUpperCamelCase } from "../utils/string-utils";
|
||||
|
||||
const store = useAppStore();
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<LocalImage v-if="imag" :src="imag" :alt="imag" :gameId="gameId" class="rounded-lg border border-gray-600 max-h-52 w-full object-cover" />
|
||||
<LocalImage v-if="imag" :src="imag" :alt="imag" :gameId="gameId" class="rounded-lg border border-gray-600 max-h-124 w-full h-full object-cover" />
|
||||
<div class="flex justify-center">
|
||||
<div class="flex gap-2 relative top-1 points bg-black items-center justify-center px-2 py-1 rounded-full opacity-75">
|
||||
<div
|
||||
|
||||
@ -17,6 +17,8 @@ export const useAppStore = defineStore('app', {
|
||||
optionsOpen: false as boolean,
|
||||
gameIsStarting: false as boolean,
|
||||
showSidebar: false as boolean,
|
||||
currentInputDevice: 'controller' as 'controller' | 'keyboard',
|
||||
currentAvailableActions: {} as object
|
||||
}),
|
||||
getters: {
|
||||
filteredGames(state): Game[] {
|
||||
|
||||
@ -26,12 +26,10 @@ export class CarouselKeyContext extends KeyContext {
|
||||
protected onKeyLeft() {
|
||||
super.onKeyLeft();
|
||||
if (this.store.selectedGameIndex === 0 && this.store.showSidebar) {
|
||||
console.log("fjxhfjkdshjkfd")
|
||||
KeyboardManager.switchContext("sidebar");
|
||||
this.store.selectGame(-1);
|
||||
}
|
||||
else {
|
||||
console.log("assdsds")
|
||||
this.store.moveGameLeft();
|
||||
}
|
||||
}
|
||||
@ -58,4 +56,13 @@ export class CarouselKeyContext extends KeyContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setAvailableActions() {
|
||||
this.store.currentAvailableActions = {
|
||||
"order": "controller,keyboard",
|
||||
"1,Enter": "Start",
|
||||
"2,Space": "Details",
|
||||
"Power,Escape": "See options"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -83,4 +83,12 @@ export class GamePreviewKeyContext extends KeyContext {
|
||||
(document.activeElement as any).blur();
|
||||
KeyboardManager.switchContext("carousel");
|
||||
}
|
||||
|
||||
setAvailableActions() {
|
||||
this.store.currentAvailableActions = {
|
||||
"order": "controller,keyboard",
|
||||
"1,Enter": "Click",
|
||||
"Power,Escape": "Back"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@ export abstract class KeyContext {
|
||||
protected store = useAppStore();
|
||||
|
||||
public handleKey(event: KeyboardEvent): void {
|
||||
this.store.currentInputDevice = "keyboard";
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowRight':
|
||||
this.onKeyRight();
|
||||
@ -31,7 +33,7 @@ export abstract class KeyContext {
|
||||
break;
|
||||
case 'r':
|
||||
console.log("Loading games");
|
||||
this.store.loadGames();
|
||||
this.store.loadGames().then();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -39,6 +41,8 @@ export abstract class KeyContext {
|
||||
}
|
||||
|
||||
public handleState(state: ControllerState) {
|
||||
this.store.currentInputDevice = "controller";
|
||||
|
||||
if (state.joystick.x === 0) {
|
||||
this.onKeyLeft()
|
||||
}
|
||||
@ -94,4 +98,6 @@ export abstract class KeyContext {
|
||||
protected onSpace(): void {
|
||||
console.log('onSpace');
|
||||
}
|
||||
|
||||
public setAvailableActions() {}
|
||||
}
|
||||
@ -28,6 +28,7 @@ export class KeyboardManager {
|
||||
console.log("Unknown context key " + name);
|
||||
break;
|
||||
}
|
||||
this.current?.setAvailableActions();
|
||||
}
|
||||
|
||||
static handle(event: KeyboardEvent) {
|
||||
|
||||
4
frontend/src/utils/string-utils.ts
Normal file
4
frontend/src/utils/string-utils.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export function toUpperCamelCase(str: string): string {
|
||||
const [firstChar, ...otherChars] = str;
|
||||
return firstChar.toUpperCase() + otherChars.join('').toLowerCase();
|
||||
}
|
||||
@ -4,6 +4,12 @@ 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));
|
||||
|
||||
2
frontend/wailsjs/runtime/runtime.d.ts
vendored
2
frontend/wailsjs/runtime/runtime.d.ts
vendored
@ -134,7 +134,7 @@ export function WindowIsFullscreen(): Promise<boolean>;
|
||||
|
||||
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
|
||||
// Sets the width and height of the window.
|
||||
export function WindowSetSize(width: number, height: number): void;
|
||||
export function WindowSetSize(width: number, height: number): Promise<Size>;
|
||||
|
||||
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
|
||||
// Gets the width and height of the window.
|
||||
|
||||
2
go.mod
2
go.mod
@ -6,7 +6,7 @@ toolchain go1.23.5
|
||||
|
||||
require (
|
||||
github.com/karalabe/hid v1.0.0
|
||||
github.com/wailsapp/wails/v2 v2.10.1
|
||||
github.com/wailsapp/wails/v2 v2.9.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
|
||||
4
go.sum
4
go.sum
@ -69,8 +69,8 @@ github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyT
|
||||
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v2 v2.10.1 h1:QWHvWMXII2nI/nXz77gpPG8P3ehl6zKe+u4su5BWIns=
|
||||
github.com/wailsapp/wails/v2 v2.10.1/go.mod h1:zrebnFV6MQf9kx8HI4iAv63vsR5v67oS7GTEZ7Pz1TY=
|
||||
github.com/wailsapp/wails/v2 v2.9.2 h1:Xb5YRTos1w5N7DTMyYegWaGukCP2fIaX9WF21kPPF2k=
|
||||
github.com/wailsapp/wails/v2 v2.9.2/go.mod h1:uehvlCwJSFcBq7rMCGfk4rxca67QQGsbg5Nm4m9UnBs=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user