From edf1351b82b1607630ed12b3fef8e9e8f8a7a4ec Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Tue, 25 Mar 2025 19:59:09 -0400 Subject: [PATCH 01/33] Revert to old system to storing and loading saves --- .../src/views/Player/EmulatorJS/Player.vue | 83 ++++++++----------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/frontend/src/views/Player/EmulatorJS/Player.vue b/frontend/src/views/Player/EmulatorJS/Player.vue index 343500257..f3c926501 100644 --- a/frontend/src/views/Player/EmulatorJS/Player.vue +++ b/frontend/src/views/Player/EmulatorJS/Player.vue @@ -186,6 +186,40 @@ async function fetchSave(): Promise { return new Uint8Array(await file.arrayBuffer()); } +window.EJS_onSaveSave = async function ({ save }) { + if (saveRef.value) { + saveApi + .updateSave({ + save: saveRef.value, + file: new File([save], saveRef.value.file_name, { + type: "application/octet-stream", + }), + }) + .then(({ data }) => { + saveRef.value = data; + }); + } else { + saveApi + .uploadSaves({ + rom: romRef.value, + emulator: window.EJS_core, + saves: [ + new File([save], buildSaveName(), { + type: "application/octet-stream", + }), + ], + }) + .then(({ data }) => { + const allSaves = data.saves.sort( + (a: SaveSchema, b: SaveSchema) => a.id - b.id, + ); + if (romRef.value) romRef.value.user_saves = allSaves; + saveRef.value = allSaves.pop() ?? null; + }) + .catch(); + } +}; + window.EJS_onLoadSave = async function () { const sav = await fetchSave(); const FS = window.EJS_emulator.gameManager.FS; @@ -242,10 +276,6 @@ window.EJS_onGameStart = async () => { }; }, 10); - const savesMonitor = await createIndexedDBDiffMonitor({ - dbName: "/data/saves", - intervalMs: 2000, - }); const statesMonitor = await createIndexedDBDiffMonitor({ dbName: "EmulatorJS-states", storeName: "states", @@ -253,53 +283,8 @@ window.EJS_onGameStart = async () => { }); // Start monitoring - savesMonitor.start(); statesMonitor.start(); - savesMonitor.on("change", (changes: Change[]) => { - console.log("Save changes detected:", changes); - - changes.forEach((change) => { - if (!change.key.includes(window.EJS_gameName)) return; - - if (saveRef.value) { - saveApi - .updateSave({ - save: saveRef.value, - file: new File( - [change.newValue.contents], - saveRef.value.file_name, - { - type: "application/octet-stream", - }, - ), - }) - .then(({ data }) => { - saveRef.value = data; - }); - } else { - saveApi - .uploadSaves({ - rom: romRef.value, - emulator: window.EJS_core, - saves: [ - new File([change.newValue.contents], buildSaveName(), { - type: "application/octet-stream", - }), - ], - }) - .then(({ data }) => { - const allSaves = data.saves.sort( - (a: SaveSchema, b: SaveSchema) => a.id - b.id, - ); - if (romRef.value) romRef.value.user_saves = allSaves; - saveRef.value = allSaves.pop() ?? null; - }) - .catch(); - } - }); - }); - statesMonitor.on("change", (changes: Change[]) => { console.log("State changes detected:", changes); From 51cd16634c77a0a8684ce69cac1177ba9308c408 Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Wed, 26 Mar 2025 10:56:48 -0400 Subject: [PATCH 02/33] add dedicated emulatorjs save quick button --- backend/endpoints/platform.py | 1 + backend/endpoints/responses/platform.py | 2 +- backend/models/platform.py | 2 +- .../__generated__/models/PlatformSchema.ts | 2 +- .../AppBar/Platform/PlatformInfoDrawer.vue | 2 +- frontend/src/locales/de_DE/play.json | 2 +- frontend/src/locales/en_GB/play.json | 4 +- frontend/src/locales/en_US/play.json | 4 +- frontend/src/locales/es_ES/play.json | 2 +- frontend/src/locales/fr_FR/play.json | 2 +- frontend/src/locales/ja_JP/play.json | 2 +- frontend/src/locales/ko_KR/play.json | 2 +- frontend/src/locales/pt_BR/play.json | 2 +- frontend/src/locales/ro_RO/play.json | 2 +- frontend/src/locales/ru_RU/play.json | 4 +- frontend/src/locales/zh_CN/play.json | 2 +- frontend/src/utils/indexdb-monitor.ts | 2 +- frontend/src/views/Player/EmulatorJS/Base.vue | 71 +++++----- .../src/views/Player/EmulatorJS/Player.vue | 134 +++++------------- frontend/src/views/Player/EmulatorJS/utils.ts | 104 ++++++++++++++ frontend/src/views/Player/RuffleRS/Base.vue | 32 +---- 21 files changed, 196 insertions(+), 184 deletions(-) create mode 100644 frontend/src/views/Player/EmulatorJS/utils.ts diff --git a/backend/endpoints/platform.py b/backend/endpoints/platform.py index dacbe7a99..a6ed6986c 100644 --- a/backend/endpoints/platform.py +++ b/backend/endpoints/platform.py @@ -87,6 +87,7 @@ def get_supported_platforms(request: Request) -> list[PlatformSchema]: "rom_count": 0, "created_at": now, "updated_at": now, + "fs_size_bytes": 0, } if platform["name"] in db_platforms_map: diff --git a/backend/endpoints/responses/platform.py b/backend/endpoints/responses/platform.py index cae9a9a22..9e0068912 100644 --- a/backend/endpoints/responses/platform.py +++ b/backend/endpoints/responses/platform.py @@ -29,7 +29,7 @@ class PlatformSchema(BaseModel): aspect_ratio: str = DEFAULT_COVER_ASPECT_RATIO created_at: datetime updated_at: datetime - filesystem_size_bytes: int + fs_size_bytes: int class Config: from_attributes = True diff --git a/backend/models/platform.py b/backend/models/platform.py index 7e4de74df..e3b02cdb1 100644 --- a/backend/models/platform.py +++ b/backend/models/platform.py @@ -53,7 +53,7 @@ class Platform(BaseModel): return self.name @cached_property - def filesystem_size_bytes(self) -> int: + def fs_size_bytes(self) -> int: from handler.database import db_stats_handler return db_stats_handler.get_platform_filesize(self.id) diff --git a/frontend/src/__generated__/models/PlatformSchema.ts b/frontend/src/__generated__/models/PlatformSchema.ts index 4b6e820d1..8a4d180bb 100644 --- a/frontend/src/__generated__/models/PlatformSchema.ts +++ b/frontend/src/__generated__/models/PlatformSchema.ts @@ -25,7 +25,7 @@ export type PlatformSchema = { aspect_ratio?: string; created_at: string; updated_at: string; - filesystem_size_bytes: number; + fs_size_bytes: number; readonly display_name: string; }; diff --git a/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue b/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue index 22be49b0f..80aa59495 100644 --- a/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue +++ b/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue @@ -69,7 +69,7 @@ const PLATFORM_INFO_FIELDS: { { key: "generation", label: t("platform.generation"), format: identity }, { key: "family_name", label: t("platform.family"), format: identity }, { - key: "filesystem_size_bytes", + key: "fs_size_bytes", label: t("common.size-on-disk"), format: (fs: number) => formatBytes(fs, 2), }, diff --git a/frontend/src/locales/de_DE/play.json b/frontend/src/locales/de_DE/play.json index 1a7e66622..90ddecc42 100644 --- a/frontend/src/locales/de_DE/play.json +++ b/frontend/src/locales/de_DE/play.json @@ -1,7 +1,7 @@ { "full-screen": "Vollbild", "play": "Spielen", - "reset-session": "Session zurücksetzen", + "save-and-quit": "Speichern und beenden", "back-to-game-details": "Zurück zu den Spieldetails", "back-to-gallery": "Zurück zur Plattformübersicht" } diff --git a/frontend/src/locales/en_GB/play.json b/frontend/src/locales/en_GB/play.json index 8f028ccdc..954e573a6 100644 --- a/frontend/src/locales/en_GB/play.json +++ b/frontend/src/locales/en_GB/play.json @@ -1,7 +1,7 @@ { - "full-screen": "Full Screen", + "full-screen": "Full screen", "play": "Play", - "reset-session": "Reset Session", + "save-and-quit": "Save and quit", "back-to-game-details": "Back to game details", "back-to-gallery": "Back to gallery" } diff --git a/frontend/src/locales/en_US/play.json b/frontend/src/locales/en_US/play.json index 8f028ccdc..954e573a6 100644 --- a/frontend/src/locales/en_US/play.json +++ b/frontend/src/locales/en_US/play.json @@ -1,7 +1,7 @@ { - "full-screen": "Full Screen", + "full-screen": "Full screen", "play": "Play", - "reset-session": "Reset Session", + "save-and-quit": "Save and quit", "back-to-game-details": "Back to game details", "back-to-gallery": "Back to gallery" } diff --git a/frontend/src/locales/es_ES/play.json b/frontend/src/locales/es_ES/play.json index 4bb90c966..c4cc22e53 100644 --- a/frontend/src/locales/es_ES/play.json +++ b/frontend/src/locales/es_ES/play.json @@ -1,7 +1,7 @@ { "full-screen": "Pantalla completa", "play": "Jugar", - "reset-session": "Restablecer sesión", + "save-and-quit": "Guardar y salir", "back-to-game-details": "Volver a detalles", "back-to-gallery": "Volver a galería" } diff --git a/frontend/src/locales/fr_FR/play.json b/frontend/src/locales/fr_FR/play.json index ff0c24a26..59d6222ba 100644 --- a/frontend/src/locales/fr_FR/play.json +++ b/frontend/src/locales/fr_FR/play.json @@ -1,7 +1,7 @@ { "full-screen": "Plein écran", "play": "Jouer", - "reset-session": "Réinitialiser la session", + "save-and-quit": "Sauvegarder et quitter", "back-to-game-details": "Retour aux détails du jeu", "back-to-gallery": "Retour à la galerie" } diff --git a/frontend/src/locales/ja_JP/play.json b/frontend/src/locales/ja_JP/play.json index b359b4ef7..bd0c154c8 100644 --- a/frontend/src/locales/ja_JP/play.json +++ b/frontend/src/locales/ja_JP/play.json @@ -1,7 +1,7 @@ { "full-screen": "全画面", "play": "プレイ", - "reset-session": "セッションをリセット", + "save-and-quit": "保存して終了", "back-to-game-details": "ゲーム詳細へ戻る", "back-to-gallery": "ギャラリーへ戻る" } diff --git a/frontend/src/locales/ko_KR/play.json b/frontend/src/locales/ko_KR/play.json index 2366d40a9..cd409b306 100644 --- a/frontend/src/locales/ko_KR/play.json +++ b/frontend/src/locales/ko_KR/play.json @@ -1,7 +1,7 @@ { "full-screen": "전체 화면", "play": "실행", - "reset-session": "세션 초기화", + "save-and-quit": "저장하고 종료", "back-to-game-details": "게임 설명으로 가기", "back-to-gallery": "갤러리로 가기" } diff --git a/frontend/src/locales/pt_BR/play.json b/frontend/src/locales/pt_BR/play.json index 9c5b70bba..8f4411b05 100644 --- a/frontend/src/locales/pt_BR/play.json +++ b/frontend/src/locales/pt_BR/play.json @@ -1,7 +1,7 @@ { "full-screen": "Tela cheia", "play": "Jogar", - "reset-session": "Redefinir sessão", + "save-and-quit": "Salvar e sair", "back-to-game-details": "Voltar aos detalhes do jogo", "back-to-gallery": "Voltar à galeria" } diff --git a/frontend/src/locales/ro_RO/play.json b/frontend/src/locales/ro_RO/play.json index cd7cd8437..36c14647f 100644 --- a/frontend/src/locales/ro_RO/play.json +++ b/frontend/src/locales/ro_RO/play.json @@ -1,7 +1,7 @@ { "full-screen": "Ecran complet", "play": "Joacă", - "reset-session": "Resetează sesiunea", + "save-and-quit": "Salvează și ieși", "back-to-game-details": "Înapoi la detaliile jocului", "back-to-gallery": "Înapoi la galerie" } diff --git a/frontend/src/locales/ru_RU/play.json b/frontend/src/locales/ru_RU/play.json index 8f028ccdc..954e573a6 100644 --- a/frontend/src/locales/ru_RU/play.json +++ b/frontend/src/locales/ru_RU/play.json @@ -1,7 +1,7 @@ { - "full-screen": "Full Screen", + "full-screen": "Full screen", "play": "Play", - "reset-session": "Reset Session", + "save-and-quit": "Save and quit", "back-to-game-details": "Back to game details", "back-to-gallery": "Back to gallery" } diff --git a/frontend/src/locales/zh_CN/play.json b/frontend/src/locales/zh_CN/play.json index c636d39e2..ece528b81 100644 --- a/frontend/src/locales/zh_CN/play.json +++ b/frontend/src/locales/zh_CN/play.json @@ -1,7 +1,7 @@ { "full-screen": "全屏", "play": "游玩", - "reset-session": "重置会话", + "save-and-quit": "保存并退出", "back-to-game-details": "返回游戏详情", "back-to-gallery": "返回游戏库" } diff --git a/frontend/src/utils/indexdb-monitor.ts b/frontend/src/utils/indexdb-monitor.ts index c1cc81b32..00385706b 100644 --- a/frontend/src/utils/indexdb-monitor.ts +++ b/frontend/src/utils/indexdb-monitor.ts @@ -23,7 +23,7 @@ type EventType = "change" | "error"; type EventsListener = (changes: Change[]) => void; type ErrorsListener = (error: Error) => void; -interface DiffMonitor { +export interface DiffMonitor { start: () => void; stop: () => void; getChanges: () => Change[]; diff --git a/frontend/src/views/Player/EmulatorJS/Base.vue b/frontend/src/views/Player/EmulatorJS/Base.vue index a12ae1d7d..96de9654a 100644 --- a/frontend/src/views/Player/EmulatorJS/Base.vue +++ b/frontend/src/views/Player/EmulatorJS/Base.vue @@ -12,6 +12,7 @@ import { isNull } from "lodash"; import { onMounted, ref } from "vue"; import { useRoute } from "vue-router"; import { useI18n } from "vue-i18n"; +import { saveSave, saveState } from "./utils"; const EMULATORJS_VERSION = "4.2.1"; @@ -63,6 +64,20 @@ function onFullScreenChange() { localStorage.setItem("fullScreenOnPlay", fullScreenOnPlay.value.toString()); } +async function saveAndQuit() { + if (!rom.value) return window.history.back(); + + // Force a save of the current state + const stateFile = window.EJS_emulator.gameManager.getState(); + await saveState({ rom: rom.value, state: stateRef.value, file: stateFile }); + + // Force a save of the save file + const saveFile = window.EJS_emulator.gameManager.getSaveFile(); + await saveSave({ rom: rom.value, save: saveRef.value, file: saveFile }); + + window.history.back(); +} + onMounted(async () => { const romResponse = await romApi.getRom({ romId: parseInt(route.params.rom as string), @@ -270,9 +285,14 @@ onMounted(async () => { diff --git a/frontend/src/locales/de_DE/play.json b/frontend/src/locales/de_DE/play.json index c4748f091..90dc5c8af 100644 --- a/frontend/src/locales/de_DE/play.json +++ b/frontend/src/locales/de_DE/play.json @@ -8,5 +8,7 @@ "clear-cache": "EmulatorJS-Cache löschen", "clear-cache-title": "Möchtest du den EmulatorJS-Cache wirklich löschen?", "clear-cache-warning": "Dadurch werden alle im Browser gespeicherten Spielstände und Speicherungen entfernt.", - "clear-cache-description": "Es hat keine Auswirkungen auf Spielstände und Speicherungen, die auf dem Server gespeichert sind." + "clear-cache-description": "Es hat keine Auswirkungen auf Spielstände und Speicherungen, die auf dem Server gespeichert sind.", + "select-save": "Speicherstand auswählen", + "select-state": "Speicherstand auswählen" } diff --git a/frontend/src/locales/en_GB/play.json b/frontend/src/locales/en_GB/play.json index 8330b5e30..4674ef1d0 100644 --- a/frontend/src/locales/en_GB/play.json +++ b/frontend/src/locales/en_GB/play.json @@ -8,5 +8,7 @@ "clear-cache": "Clear EmulatorJS Cache", "clear-cache-title": "Are you sure you want to clear the EmulatorJS cache?", "clear-cache-warning": "This will remove all saves and states stored in the browser.", - "clear-cache-description": "Any saves or states stored on the server will not be affected." + "clear-cache-description": "Any saves or states stored on the server will not be affected.", + "select-save": "Select save", + "select-state": "Select state" } diff --git a/frontend/src/locales/en_US/play.json b/frontend/src/locales/en_US/play.json index 8330b5e30..4674ef1d0 100644 --- a/frontend/src/locales/en_US/play.json +++ b/frontend/src/locales/en_US/play.json @@ -8,5 +8,7 @@ "clear-cache": "Clear EmulatorJS Cache", "clear-cache-title": "Are you sure you want to clear the EmulatorJS cache?", "clear-cache-warning": "This will remove all saves and states stored in the browser.", - "clear-cache-description": "Any saves or states stored on the server will not be affected." + "clear-cache-description": "Any saves or states stored on the server will not be affected.", + "select-save": "Select save", + "select-state": "Select state" } diff --git a/frontend/src/locales/es_ES/play.json b/frontend/src/locales/es_ES/play.json index badc011cb..0a1974383 100644 --- a/frontend/src/locales/es_ES/play.json +++ b/frontend/src/locales/es_ES/play.json @@ -8,5 +8,7 @@ "clear-cache": "Limpiar caché de EmulatorJS", "clear-cache-title": "¿Estás seguro de que quieres limpiar la caché de EmulatorJS?", "clear-cache-warning": "Esto eliminará todas las partidas y estados almacenados en el navegador.", - "clear-cache-description": "No afectará a las partidas o estados almacenados en el servidor." + "clear-cache-description": "No afectará a las partidas o estados almacenados en el servidor.", + "select-save": "Seleccionar partida", + "select-state": "Seleccionar estado" } diff --git a/frontend/src/locales/fr_FR/play.json b/frontend/src/locales/fr_FR/play.json index 17bfd56a9..263e48251 100644 --- a/frontend/src/locales/fr_FR/play.json +++ b/frontend/src/locales/fr_FR/play.json @@ -8,5 +8,7 @@ "clear-cache": "Effacer le cache EmulatorJS", "clear-cache-title": "Êtes-vous sûr de vouloir effacer le cache EmulatorJS ?", "clear-cache-warning": "Cela supprimera toutes les sauvegardes et les états stockés dans le navigateur.", - "clear-cache-description": "Les sauvegardes ou les états stockés sur le serveur ne seront pas affectés." + "clear-cache-description": "Les sauvegardes ou les états stockés sur le serveur ne seront pas affectés.", + "select-save": "Sélectionner la sauvegarde", + "select-state": "Sélectionner l'état" } diff --git a/frontend/src/locales/ja_JP/play.json b/frontend/src/locales/ja_JP/play.json index 31ccb970a..712f18820 100644 --- a/frontend/src/locales/ja_JP/play.json +++ b/frontend/src/locales/ja_JP/play.json @@ -8,5 +8,7 @@ "clear-cache": "EmulatorJS キャッシュをクリア", "clear-cache-title": "EmulatorJS キャッシュをクリアしてもよろしいですか?", "clear-cache-warning": "これにより、ブラウザに保存されているすべてのセーブデータとステートが削除されます。", - "clear-cache-description": "サーバーに保存されているセーブデータやステートには影響しません。" + "clear-cache-description": "サーバーに保存されているセーブデータやステートには影響しません。", + "select-save": "セーブデータを選択", + "select-state": "ステートを選択" } diff --git a/frontend/src/locales/ko_KR/play.json b/frontend/src/locales/ko_KR/play.json index 10b0efb7d..2d85c95c3 100644 --- a/frontend/src/locales/ko_KR/play.json +++ b/frontend/src/locales/ko_KR/play.json @@ -8,5 +8,7 @@ "clear-cache": "EmulatorJS 캐시 지우기", "clear-cache-title": "EmulatorJS 캐시를 지우시겠습니까?", "clear-cache-warning": "이로 인해 브라우저에 저장된 모든 세이브 및 상태가 제거됩니다.", - "clear-cache-description": "서버에 저장된 세이브 및 상태에는 영향을 주지 않습니다." + "clear-cache-description": "서버에 저장된 세이브 및 상태에는 영향을 주지 않습니다.", + "select-save": "세이브 선택", + "select-state": "상태 선택" } diff --git a/frontend/src/locales/pt_BR/play.json b/frontend/src/locales/pt_BR/play.json index 36d5fd896..a8b717cbe 100644 --- a/frontend/src/locales/pt_BR/play.json +++ b/frontend/src/locales/pt_BR/play.json @@ -8,5 +8,7 @@ "clear-cache": "Limpar cache do EmulatorJS", "clear-cache-title": "Tem certeza de que deseja limpar o cache do EmulatorJS?", "clear-cache-warning": "Isso removerá todos os saves e estados armazenados no navegador.", - "clear-cache-description": "Não afetará nenhum save ou estado armazenado no servidor." + "clear-cache-description": "Não afetará nenhum save ou estado armazenado no servidor.", + "select-save": "Selecionar save", + "select-state": "Selecionar estado" } diff --git a/frontend/src/locales/ro_RO/play.json b/frontend/src/locales/ro_RO/play.json index 6b4a576b4..47d2140c9 100644 --- a/frontend/src/locales/ro_RO/play.json +++ b/frontend/src/locales/ro_RO/play.json @@ -8,5 +8,7 @@ "clear-cache": "Șterge cache-ul EmulatorJS", "clear-cache-title": "Ești sigur că vrei să ștergi cache-ul EmulatorJS?", "clear-cache-warning": "Acest lucru va elimina toate salvările și stările stocate în browser.", - "clear-cache-description": "Nu va afecta nicio salvare sau stare stocată pe server." + "clear-cache-description": "Nu va afecta nicio salvare sau stare stocată pe server.", + "select-save": "Selectează salvare", + "select-state": "Selectează stare" } diff --git a/frontend/src/locales/ru_RU/play.json b/frontend/src/locales/ru_RU/play.json index 042fb34b9..2285cd4ce 100644 --- a/frontend/src/locales/ru_RU/play.json +++ b/frontend/src/locales/ru_RU/play.json @@ -8,5 +8,7 @@ "clear-cache": "Очистить кэш EmulatorJS", "clear-cache-title": "Вы уверены, что хотите очистить кэш EmulatorJS?", "clear-cache-warning": "Это удалит все сохранения и состояния, хранящиеся в браузере.", - "clear-cache-description": "Любые сохранения или состояния, хранящиеся на сервере, не будут затронуты." + "clear-cache-description": "Любые сохранения или состояния, хранящиеся на сервере, не будут затронуты.", + "select-save": "Выбрать сохранение", + "select-state": "Выбрать состояние" } diff --git a/frontend/src/views/Player/EmulatorJS/Base.vue b/frontend/src/views/Player/EmulatorJS/Base.vue index 131b843b5..f9e7426ce 100644 --- a/frontend/src/views/Player/EmulatorJS/Base.vue +++ b/frontend/src/views/Player/EmulatorJS/Base.vue @@ -9,11 +9,14 @@ import { formatBytes, formatTimestamp, getSupportedEJSCores } from "@/utils"; import { ROUTES } from "@/plugins/router"; import Player from "@/views/Player/EmulatorJS/Player.vue"; import { isNull } from "lodash"; -import { onMounted, ref } from "vue"; +import { inject, onBeforeUnmount, onMounted, ref } from "vue"; import { useRoute } from "vue-router"; import { useI18n } from "vue-i18n"; import { saveSave, saveState } from "./utils"; import CacheDialog from "./CacheDialog.vue"; +import type { Emitter } from "mitt"; +import type { Events } from "@/types/emitter"; +import { getEmptyCoverImage } from "@/utils/covers"; const EMULATORJS_VERSION = "4.2.1"; @@ -32,6 +35,7 @@ const supportedCores = ref([]); const gameRunning = ref(false); const storedFSOP = localStorage.getItem("fullScreenOnPlay"); const fullScreenOnPlay = ref(isNull(storedFSOP) ? true : storedFSOP === "true"); +const emitter = inject>("emitter"); // Functions function onPlay() { @@ -93,6 +97,22 @@ async function saveAndQuit() { window.history.back(); } +function saveSelected(save: SaveSchema) { + saveRef.value = save; + localStorage.setItem( + `player:${rom.value?.platform_slug}:save_id`, + save.id.toString(), + ); +} + +function stateSelected(state: StateSchema) { + stateRef.value = state; + localStorage.setItem( + `player:${rom.value?.platform_slug}:state_id`, + state.id.toString(), + ); +} + onMounted(async () => { const romResponse = await romApi.getRom({ romId: parseInt(route.params.rom as string), @@ -133,6 +153,15 @@ onMounted(async () => { if (storedDisc) { discRef.value = parseInt(storedDisc); } + + emitter?.on("saveSelected", saveSelected); + emitter?.on("stateSelected", stateSelected); +}); + +onBeforeUnmount(async () => { + emitter?.off("saveSelected", saveSelected); + emitter?.off("stateSelected", stateSelected); + window.EJS_emulator?.callEvent("exit"); }); @@ -208,6 +237,7 @@ onMounted(async () => { " /> { })) ?? [] " /> - - - - - - - - + {{ t("play.select-save") }} + + + + + @@ -348,7 +394,7 @@ onMounted(async () => { {