Merge branch 'master' into true-pagination

This commit is contained in:
Georges-Antoine Assi
2025-03-29 11:00:14 -04:00
14 changed files with 137 additions and 42 deletions

View File

@@ -3,7 +3,6 @@ import shutil
import httpx
from anyio import Path, open_file
from config import RESOURCES_BASE_PATH
from fastapi import HTTPException, status
from logger.logger import log
from models.collection import Collection
from models.rom import Rom
@@ -67,13 +66,9 @@ class FSResourcesHandler(FSHandler):
async with await cover_file.open("wb") as f:
async for chunk in response.aiter_raw():
await f.write(chunk)
except httpx.NetworkError as exc:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Unable to fetch cover at {url_cover}: {str(exc)}",
) from exc
except httpx.ProtocolError:
log.warning(f"Failure writing cover {url_cover} to file (ProtocolError)")
except httpx.TransportError as exc:
log.error(f"Unable to fetch cover at {url_cover}: {str(exc)}")
return None
if size == CoverSize.SMALL:
with Image.open(cover_file) as img:
@@ -150,19 +145,21 @@ class FSResourcesHandler(FSHandler):
return path_cover_l, path_cover_s, artwork_path
@staticmethod
async def _store_screenshot(rom: Rom, url: str, idx: int):
async def _store_screenshot(rom: Rom, url_screenhot: str, idx: int):
"""Store roms resources in filesystem
Args:
rom: Rom object
url: url to get the screenshot
url_screenhot: URL to get the screenshot
"""
screenshot_file = f"{idx}.jpg"
screenshot_path = f"{RESOURCES_BASE_PATH}/{rom.fs_resources_path}/screenshots"
httpx_client = ctx_httpx_client.get()
try:
async with httpx_client.stream("GET", url, timeout=120) as response:
async with httpx_client.stream(
"GET", url_screenhot, timeout=120
) as response:
if response.status_code == 200:
await Path(screenshot_path).mkdir(parents=True, exist_ok=True)
async with await open_file(
@@ -170,13 +167,9 @@ class FSResourcesHandler(FSHandler):
) as f:
async for chunk in response.aiter_raw():
await f.write(chunk)
except httpx.NetworkError as exc:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Unable to fetch screenshot at {url}: {str(exc)}",
) from exc
except httpx.ProtocolError:
log.warning(f"Failure writing screenshot {url} to file (ProtocolError)")
except httpx.TransportError as exc:
log.error(f"Unable to fetch screenshot at {url_screenhot}: {str(exc)}")
return None
@staticmethod
def _get_screenshot_path(rom: Rom, idx: str):
@@ -195,8 +188,8 @@ class FSResourcesHandler(FSHandler):
return []
path_screenshots: list[str] = []
for idx, url in enumerate(url_screenshots):
await self._store_screenshot(rom, url, idx)
for idx, url_screenhot in enumerate(url_screenshots):
await self._store_screenshot(rom, url_screenhot, idx)
path_screenshots.append(self._get_screenshot_path(rom, str(idx)))
return path_screenshots
@@ -229,13 +222,9 @@ class FSResourcesHandler(FSHandler):
async with await manual_file.open("wb") as f:
async for chunk in response.aiter_raw():
await f.write(chunk)
except httpx.NetworkError as exc:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Unable to fetch cover at {url_manual}: {str(exc)}",
) from exc
except httpx.ProtocolError:
log.warning(f"Failure writing cover {url_manual} to file (ProtocolError)")
except httpx.TransportError as exc:
log.error(f"Unable to fetch manual at {url_manual}: {str(exc)}")
return None
@staticmethod
async def _get_manual_path(rom: Rom) -> str:

View File

@@ -3,5 +3,9 @@
"play": "Spielen",
"reset-session": "Session zurücksetzen",
"back-to-game-details": "Zurück zu den Spieldetails",
"back-to-gallery": "Zurück zur Plattformübersicht"
"back-to-gallery": "Zurück zur Plattformübersicht",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "Play",
"reset-session": "Reset Session",
"back-to-game-details": "Back to game details",
"back-to-gallery": "Back to gallery"
"back-to-gallery": "Back to gallery",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "Play",
"reset-session": "Reset Session",
"back-to-game-details": "Back to game details",
"back-to-gallery": "Back to gallery"
"back-to-gallery": "Back to gallery",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "Jugar",
"reset-session": "Restablecer sesión",
"back-to-game-details": "Volver a detalles",
"back-to-gallery": "Volver a galería"
"back-to-gallery": "Volver a galería",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "Jouer",
"reset-session": "Réinitialiser la session",
"back-to-game-details": "Retour aux détails du jeu",
"back-to-gallery": "Retour à la galerie"
"back-to-gallery": "Retour à la galerie",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "プレイ",
"reset-session": "セッションをリセット",
"back-to-game-details": "ゲーム詳細へ戻る",
"back-to-gallery": "ギャラリーへ戻る"
"back-to-gallery": "ギャラリーへ戻る",
"clear-cache": "EmulatorJS キャッシュをクリア",
"clear-cache-title": "EmulatorJS キャッシュをクリアしてもよろしいですか?",
"clear-cache-warning": "これにより、ブラウザに保存されているすべてのセーブデータとステートが削除されます。",
"clear-cache-description": "サーバーに保存されているセーブデータやステートには影響しません。"
}

View File

@@ -3,5 +3,9 @@
"play": "실행",
"reset-session": "세션 초기화",
"back-to-game-details": "게임 설명으로 가기",
"back-to-gallery": "갤러리로 가기"
"back-to-gallery": "갤러리로 가기",
"clear-cache": "EmulatorJS 캐시 지우기",
"clear-cache-title": "EmulatorJS 캐시를 지우시겠습니까?",
"clear-cache-warning": "이로 인해 브라우저에 저장된 모든 세이브 및 상태가 제거됩니다.",
"clear-cache-description": "서버에 저장된 세이브 및 상태에는 영향을 주지 않습니다."
}

View File

@@ -3,5 +3,9 @@
"play": "Jogar",
"reset-session": "Redefinir sessão",
"back-to-game-details": "Voltar aos detalhes do jogo",
"back-to-gallery": "Voltar à galeria"
"back-to-gallery": "Voltar à galeria",
"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."
}

View File

@@ -3,5 +3,9 @@
"play": "Joacă",
"reset-session": "Resetează sesiunea",
"back-to-game-details": "Înapoi la detaliile jocului",
"back-to-gallery": "Înapoi la galerie"
"back-to-gallery": "Înapoi la galerie",
"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."
}

View File

@@ -1,7 +1,11 @@
{
"full-screen": "Full Screen",
"play": "Play",
"reset-session": "Reset Session",
"back-to-game-details": "Back to game details",
"back-to-gallery": "Back to gallery"
"full-screen": "Полный экран",
"play": "Играть",
"reset-session": "Сбросить сессию",
"back-to-game-details": "Вернуться к деталям игры",
"back-to-gallery": "Вернуться в галерею",
"clear-cache": "Очистить кэш EmulatorJS",
"clear-cache-title": "Вы уверены, что хотите очистить кэш EmulatorJS?",
"clear-cache-warning": "Это удалит все сохранения и состояния, хранящиеся в браузере.",
"clear-cache-description": "Любые сохранения или состояния, хранящиеся на сервере, не будут затронуты."
}

View File

@@ -3,5 +3,9 @@
"play": "游玩",
"reset-session": "重置会话",
"back-to-game-details": "返回游戏详情",
"back-to-gallery": "返回游戏库"
"back-to-gallery": "返回游戏库",
"clear-cache": "清除 EmulatorJS 缓存",
"clear-cache-title": "您确定要清除 EmulatorJS 缓存吗?",
"clear-cache-warning": "这将删除浏览器中存储的所有保存和状态。",
"clear-cache-description": "这不会影响服务器上存储的任何保存或状态。"
}

View File

@@ -12,6 +12,7 @@ import { isNull } from "lodash";
import { onMounted, ref } from "vue";
import { useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import CacheDialog from "./CacheDialog.vue";
const EMULATORJS_VERSION = "4.2.1";
@@ -378,6 +379,7 @@ onMounted(async () => {
"
>{{ t("play.back-to-gallery") }}
</v-btn>
<cache-dialog v-if="!gameRunning" />
</v-col>
</v-row>
</v-col>

View File

@@ -0,0 +1,60 @@
<script setup lang="ts">
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import RDialog from "@/components/common/RDialog.vue";
const { t } = useI18n();
const show = ref(false);
function clearIndexDB() {
window.indexedDB.deleteDatabase("/data/saves");
window.indexedDB.deleteDatabase("EmulatorJS-roms");
window.indexedDB.deleteDatabase("EmulatorJS-core");
window.indexedDB.deleteDatabase("EmulatorJS-states");
closeDialog();
}
function closeDialog() {
show.value = false;
}
</script>
<template>
<v-btn
class="mt-12 text-romm-red"
block
variant="outlined"
size="large"
prepend-icon="mdi-database-remove"
@click="show = true"
>{{ t("play.clear-cache") }}
</v-btn>
<r-dialog v-model="show" @close="closeDialog" icon="mdi-database-remove">
<template #header>
<v-row class="ml-2">
{{ t("play.clear-cache") }}
</v-row>
</template>
<template #content>
<div class="text-h6 pa-4">{{ t("play.clear-cache-title") }}</div>
<div class="text-body-1 px-4 pb-4">
<strong>{{ t("play.clear-cache-warning") }}</strong>
<br />
{{ t("play.clear-cache-description") }}
</div>
</template>
<template #append>
<v-row class="justify-center pa-2" no-gutters>
<v-btn-group divided density="compact">
<v-btn class="bg-toplayer" @click="closeDialog">
{{ t("common.cancel") }}
</v-btn>
<v-btn class="bg-toplayer text-romm-red" @click="clearIndexDB">
{{ t("common.confirm") }}
</v-btn>
</v-btn-group>
</v-row>
</template>
</r-dialog>
</template>