diff --git a/src/core/classes/rom.ts b/src/core/classes/rom.ts index 64f7458..e691c9c 100644 --- a/src/core/classes/rom.ts +++ b/src/core/classes/rom.ts @@ -42,9 +42,13 @@ export class Rom { return this.goodCode.rom } - get cover() { + get covers() { if (this.standardizedName) { - return getCover({ system: this.system, name: this.standardizedName }) + return [ + getCover({ system: this.system, name: this.standardizedName, type: 'boxart' }), + getCover({ system: this.system, name: this.standardizedName, type: 'title' }), + getCover({ system: this.system, name: this.standardizedName, type: 'snap' }), + ] } return '' } diff --git a/src/core/helpers/misc.ts b/src/core/helpers/misc.ts index 41efaaa..7b1423b 100644 --- a/src/core/helpers/misc.ts +++ b/src/core/helpers/misc.ts @@ -7,7 +7,7 @@ function encodeRFC3986URIComponent(str) { return encodeURIComponent(str).replaceAll(/[!'()*]/g, (c) => `%${c.codePointAt(0)?.toString(16).toUpperCase()}`) } -export function getCover({ system, name, type = system === 'gw' ? 'snap' : 'boxart' }) { +export function getCover({ system, name, type = 'boxart' }) { if (!name || !system) { return '' } diff --git a/src/views/components/home-screen/game-entries-grid/game-entry-content.tsx b/src/views/components/home-screen/game-entries-grid/game-entry-content.tsx index f43ee35..a2c43ca 100644 --- a/src/views/components/home-screen/game-entries-grid/game-entry-content.tsx +++ b/src/views/components/home-screen/game-entries-grid/game-entry-content.tsx @@ -22,11 +22,16 @@ export function GameEntryContent({ rom }: { rom: Rom }) { throw new Error('skip load cover') } await rom.ready() - const { cover } = rom + const { covers } = rom const abortController = new AbortController() abortControllerRef.current = abortController - await loadImageWithLimit(cover, abortController.signal) - return cover + for (const cover of covers) { + try { + await loadImageWithLimit(cover, abortController.signal) + return cover + } catch {} + } + throw new Error('invalid cover') }, [rom]) useEffect(() => { diff --git a/src/views/components/home-screen/game-entries-grid/game-entry.tsx b/src/views/components/home-screen/game-entries-grid/game-entry.tsx index 8dbc155..2f16c51 100644 --- a/src/views/components/home-screen/game-entries-grid/game-entry.tsx +++ b/src/views/components/home-screen/game-entries-grid/game-entry.tsx @@ -7,7 +7,7 @@ import { GameEntryButton } from './game-entry-button' import { GameEntryContent } from './game-entry-content' import { GameTitle } from './game-title' -function onFocus(e: FocusEvent) { +function scrollAsNeeded(e: FocusEvent) { const $focusedElement = $(e.currentTarget) const $outer = $focusedElement.offsetParent() const outerScrollTop = $outer.scrollTop() @@ -54,7 +54,7 @@ export function GameEntry({ isLastColumn={isLastColumn} isLastRow={isLastRow} onClick={onClickGameEntryButton} - onFocus={onFocus} + onFocus={scrollAsNeeded} style={style} >
diff --git a/src/views/components/home-screen/game-entries-grid/utils.ts b/src/views/components/home-screen/game-entries-grid/utils.ts index 22be1ca..1278ed0 100644 --- a/src/views/components/home-screen/game-entries-grid/utils.ts +++ b/src/views/components/home-screen/game-entries-grid/utils.ts @@ -1,10 +1,14 @@ import ky from 'ky' import PQueue from 'p-queue' +import store2 from 'store2' const queue = new PQueue({ concurrency: 5 }) -const validImages = {} -const invalidImages = {} +const cacheKey = 'image-load-status-record' + +const record = store2.session.get(cacheKey) || {} +const validImages = record?.validImages || {} +const invalidImages = record?.invalidImages || {} async function loadImage(src: string, signal: AbortSignal) { if (src in validImages) { return @@ -18,6 +22,7 @@ async function loadImage(src: string, signal: AbortSignal) { } catch (error: any) { if (typeof error?.response?.status === 'number') { invalidImages[src] = true + store2.session.set(cacheKey, { ...record, invalidImages }) } throw error } @@ -27,6 +32,7 @@ async function loadImage(src: string, signal: AbortSignal) { return await new Promise((resolve, reject) => { img.addEventListener('load', () => { validImages[src] = true + store2.session.set(cacheKey, { ...record, validImages }) resolve() }) img.addEventListener('error', (error) => {