From f91d5eaf4852f09951f044ccbaf0f15863d3fa9b Mon Sep 17 00:00:00 2001 From: Pandipipas <62224708+Pandipipas@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:44:19 +0100 Subject: [PATCH] Serve game logos directly from assets HTTP server --- src/dashboard/scoreko-dev/stores/game-assets.ts | 6 ++++++ src/dashboard/scoreko-dev/views/GameAssets.vue | 17 ++++++++--------- src/extension/game-assets.ts | 12 ++++++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/dashboard/scoreko-dev/stores/game-assets.ts b/src/dashboard/scoreko-dev/stores/game-assets.ts index 6d94023..1450ad8 100644 --- a/src/dashboard/scoreko-dev/stores/game-assets.ts +++ b/src/dashboard/scoreko-dev/stores/game-assets.ts @@ -28,6 +28,7 @@ export const useGameAssetsStore = defineStore('game-assets', () => { const loadingByTitle = ref>({}); const removingByTitle = ref>({}); const progressByTitle = ref>({}); + const assetsBaseUrl = ref('http://localhost'); if (!progressListenerAttached) { nodecg.listenFor('scoreko-assets:downloadProgress', (payload: unknown) => { @@ -63,6 +64,10 @@ export const useGameAssetsStore = defineStore('game-assets', () => { const refreshInstalledGames = async () => { const response = await sendNodecgMessage('scoreko-assets:listInstalled'); installedGames.value = Array.isArray(response) ? response : []; + const configResponse = await sendNodecgMessage<{ assetsBaseUrl?: string }>('scoreko-assets:getAssetsBaseUrl'); + assetsBaseUrl.value = typeof configResponse?.assetsBaseUrl === 'string' && configResponse.assetsBaseUrl.trim() + ? configResponse.assetsBaseUrl + : 'http://localhost'; await refreshCharacterNamesByGame(); return installedGames.value; }; @@ -124,6 +129,7 @@ export const useGameAssetsStore = defineStore('game-assets', () => { loadingByTitle, removingByTitle, progressByTitle, + assetsBaseUrl, refreshInstalledGames, refreshCharacterNamesByGame, downloadGame, diff --git a/src/dashboard/scoreko-dev/views/GameAssets.vue b/src/dashboard/scoreko-dev/views/GameAssets.vue index a41ff3d..ba5fbd1 100644 --- a/src/dashboard/scoreko-dev/views/GameAssets.vue +++ b/src/dashboard/scoreko-dev/views/GameAssets.vue @@ -8,13 +8,12 @@ const errorMessage = ref(''); const selectedGameSlug = ref(null); const search = ref(''); -const gameLogoModules = import.meta.glob('/src/shared/game-logos/*.png', { - eager: true, - import: 'default', - query: '?url', -}) as Record; - -const getGameLogoUrl = (logoFile: string) => gameLogoModules[`/src/shared/game-logos/${logoFile}`] ?? ''; +const getGameLogoUrl = (repoFolder: string, logoFile: string) => { + const cleanBaseUrl = gameAssetsStore.assetsBaseUrl.replace(/\/+$/, ''); + const cleanRepoFolder = repoFolder.replace(/^\/+|\/+$/g, ''); + const cleanLogoFile = logoFile.replace(/^\/+/, ''); + return `${cleanBaseUrl}/games/${cleanRepoFolder}/${cleanLogoFile}`; +}; const normalizedSearch = computed(() => search.value.trim().toLowerCase()); const filteredGames = computed(() => { @@ -109,7 +108,7 @@ onMounted(async () => { >
@@ -168,7 +167,7 @@ onMounted(async () => { style="min-width: 360px; max-width: 480px" > { + if (typeof ack !== 'function') { + return; + } + + try { + ack(null, { assetsBaseUrl: getConfiguredAssetsBaseUrl() }); + } catch (error) { + ack((error as Error).message); + } +}); + nodecg.listenFor('scoreko-assets:downloadGame', async (payload: unknown, ack) => { if (typeof ack !== 'function') { return;