BIN
.github/resources/romm_complete.png
vendored
Normal file
|
After Width: | Height: | Size: 124 KiB |
@@ -2,12 +2,12 @@
|
||||
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.22.3
|
||||
version: 1.22.4
|
||||
# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.6.1
|
||||
ref: v1.6.2
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes)
|
||||
runtimes:
|
||||
@@ -19,24 +19,24 @@ runtimes:
|
||||
lint:
|
||||
enabled:
|
||||
- markdownlint@0.41.0
|
||||
- eslint@9.9.0
|
||||
- eslint@9.9.1
|
||||
- actionlint@1.7.1
|
||||
- bandit@1.7.9
|
||||
- black@24.8.0
|
||||
- checkov@3.2.228
|
||||
- checkov@3.2.239
|
||||
- git-diff-check
|
||||
- isort@5.13.2
|
||||
- mypy@1.11.1
|
||||
- osv-scanner@1.8.3
|
||||
- mypy@1.11.2
|
||||
- osv-scanner@1.8.4
|
||||
- oxipng@9.1.2
|
||||
- prettier@3.3.3
|
||||
- ruff@0.6.0
|
||||
- ruff@0.6.3
|
||||
- shellcheck@0.10.0
|
||||
- shfmt@3.6.0
|
||||
- svgo@3.3.2
|
||||
- taplo@0.9.3
|
||||
- trivy@0.54.1
|
||||
- trufflehog@3.81.9
|
||||
- trufflehog@3.81.10
|
||||
- yamllint@1.35.1
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
|
||||
79
.vscode/tasks.json
vendored
@@ -1,41 +1,42 @@
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Launch frontend",
|
||||
"type": "npm",
|
||||
"path": "frontend",
|
||||
"script": "dev",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Launch backend",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run python3 main.py",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Launch worker",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run python3 worker.py",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Execute tests",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run pytest -vv -c ../pytest.ini",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Setup development environment",
|
||||
"type": "shell",
|
||||
"command": "docker compose up -d",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Setup testing environment",
|
||||
"type": "shell",
|
||||
"command": "export $(cat .env | grep DB_ROOT_PASSWD | xargs) && docker exec -i mariadb mariadb -u root -p$DB_ROOT_PASSWD < backend/romm_test/setup.sql",
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Launch frontend",
|
||||
"type": "npm",
|
||||
"path": "frontend",
|
||||
"script": "dev",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Launch backend",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run python3 main.py",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Launch worker",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run python3 worker.py",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Execute tests",
|
||||
"type": "shell",
|
||||
"command": "cd backend && poetry run pytest -vv -c ../pytest.ini",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Setup development environment",
|
||||
"type": "shell",
|
||||
"command": "docker compose up -d",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Setup testing environment",
|
||||
"type": "shell",
|
||||
"command": "export $(cat .env | grep DB_ROOT_PASSWD | xargs) && docker exec -i mariadb mariadb -u root -p$DB_ROOT_PASSWD < backend/romm_test/setup.sql",
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- trunk-ignore(markdownlint/MD041) -->
|
||||
<div align="center">
|
||||
|
||||
<img src=".github/resources/romm_complete.svg" height="220px" width="auto" alt="romm logo">
|
||||
<img src=".github/resources/romm_complete.png" height="220px" width="auto" alt="romm logo">
|
||||
|
||||
<h3 style="font-size: 25px;">
|
||||
A beautiful, powerful, self-hosted rom manager.
|
||||
|
||||
@@ -12,8 +12,9 @@ def str_to_bool(value: str) -> bool:
|
||||
|
||||
|
||||
# GUNICORN
|
||||
DEV_PORT: Final = int(os.environ.get("VITE_BACKEND_DEV_PORT", "5000"))
|
||||
DEV_HOST: Final = "127.0.0.1"
|
||||
DEV_MODE: Final = str_to_bool(os.environ.get("DEV_MODE", "false"))
|
||||
DEV_HOST: Final = os.environ.get("DEV_HOST", "127.0.0.1")
|
||||
DEV_PORT: Final = int(os.environ.get("DEV_PORT", "5000"))
|
||||
GUNICORN_WORKERS: Final = int(os.environ.get("GUNICORN_WORKERS", 2))
|
||||
|
||||
# PATHS
|
||||
|
||||
@@ -6,6 +6,7 @@ from urllib.parse import quote
|
||||
|
||||
from anyio import Path, open_file
|
||||
from config import (
|
||||
DEV_MODE,
|
||||
DISABLE_DOWNLOAD_ENDPOINT_AUTH,
|
||||
LIBRARY_BASE_PATH,
|
||||
RESOURCES_BASE_PATH,
|
||||
@@ -23,6 +24,7 @@ from handler.filesystem.base_handler import CoverSize
|
||||
from handler.metadata import meta_igdb_handler, meta_moby_handler
|
||||
from logger.logger import log
|
||||
from starlette.requests import ClientDisconnect
|
||||
from starlette.responses import FileResponse
|
||||
from streaming_form_data import StreamingFormDataParser
|
||||
from streaming_form_data.targets import FileTarget, NullTarget
|
||||
from utils.filesystem import sanitize_filename
|
||||
@@ -178,9 +180,22 @@ async def head_rom_content(
|
||||
if not rom:
|
||||
raise RomNotFoundInDatabaseException(id)
|
||||
|
||||
rom_path = f"{LIBRARY_BASE_PATH}/{rom.full_path}"
|
||||
files_to_check = files or [r["filename"] for r in rom.files]
|
||||
|
||||
if not rom.multi:
|
||||
# Serve the file directly in development mode for emulatorjs
|
||||
if DEV_MODE:
|
||||
return FileResponse(
|
||||
path=rom_path,
|
||||
filename=rom.file_name,
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{quote(rom.file_name)}"',
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": str(rom.file_size_bytes),
|
||||
},
|
||||
)
|
||||
|
||||
return Response(
|
||||
media_type="application/octet-stream",
|
||||
headers={
|
||||
|
||||
@@ -227,13 +227,13 @@ class DBRomsHandler(DBBaseHandler):
|
||||
rom_user = self.get_rom_user_by_id(id)
|
||||
|
||||
if data["is_main_sibling"]:
|
||||
rom = self.get_rom(rom_user.rom_id)
|
||||
|
||||
session.execute(
|
||||
update(RomUser)
|
||||
.where(
|
||||
and_(
|
||||
RomUser.rom_id.in_(
|
||||
[rom.id for rom in rom_user.rom.get_sibling_roms()]
|
||||
),
|
||||
RomUser.rom_id.in_(r.id for r in rom.sibling_roms),
|
||||
RomUser.user_id == rom_user.user_id,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -12,10 +12,17 @@ from typing import Any, Final, TypedDict
|
||||
|
||||
import magic
|
||||
import py7zr
|
||||
import zipfile_deflate64 # trunk-ignore(ruff/F401): Patches zipfile to support deflate64 compression
|
||||
from config import LIBRARY_BASE_PATH
|
||||
from config.config_manager import config_manager as cm
|
||||
from exceptions.fs_exceptions import RomAlreadyExistsException, RomsNotFoundException
|
||||
from models.rom import RomFile
|
||||
from py7zr.exceptions import (
|
||||
Bad7zFile,
|
||||
DecompressionError,
|
||||
PasswordRequired,
|
||||
UnsupportedCompressionMethodError,
|
||||
)
|
||||
from utils.filesystem import iter_directories, iter_files
|
||||
from utils.hashing import crc32_to_hex
|
||||
|
||||
@@ -108,7 +115,12 @@ def read_7z_file(file_path: Path) -> Iterator[bytes]:
|
||||
for _name, bio in f.readall().items():
|
||||
while chunk := bio.read(FILE_READ_CHUNK_SIZE):
|
||||
yield chunk
|
||||
except py7zr.Bad7zFile:
|
||||
except (
|
||||
Bad7zFile,
|
||||
DecompressionError,
|
||||
PasswordRequired,
|
||||
UnsupportedCompressionMethodError,
|
||||
):
|
||||
for chunk in read_basic_file(file_path):
|
||||
yield chunk
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ class IGDBBaseHandler(MetadataHandler):
|
||||
|
||||
return wrapper
|
||||
|
||||
# trunk-ignore(ruff/ASYNC109): timeout is used for request
|
||||
async def _request(self, url: str, data: str, timeout: int = 120) -> list:
|
||||
httpx_client = ctx_httpx_client.get()
|
||||
try:
|
||||
|
||||
@@ -48,7 +48,13 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(title="RomM API", version=get_version(), lifespan=lifespan)
|
||||
app = FastAPI(
|
||||
title="RomM API",
|
||||
version=get_version(),
|
||||
lifespan=lifespan,
|
||||
docs_url="/api/docs",
|
||||
redoc_url="/api/redoc",
|
||||
)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ROMM_BASE_PATH=/path/to/romm_mock
|
||||
VITE_BACKEND_DEV_PORT=5000
|
||||
DEV_MODE=true
|
||||
|
||||
# Gunicorn (optional)
|
||||
GUNICORN_WORKERS=4 # (2 × CPU cores) + 1
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#9205f2" />
|
||||
<meta name="msapplication-TileColor" content="#9205f2" />
|
||||
<meta name="theme-color" content="#2a0145" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RomM</title>
|
||||
|
||||
BIN
frontend/public/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/public/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
frontend/public/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
9
frontend/public/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#9205f2</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
BIN
frontend/public/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
frontend/public/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 15 KiB |
BIN
frontend/public/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
1
frontend/public/safari-pinned-tab.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1612" height="1612" version="1.0" viewBox="0 0 1209 1209"><path d="M566 .3c-.3.2-4.8.7-10 1.1-12.1.8-37.7 4.1-52.8 6.7-104.2 18-199 61.5-282.2 129.2-29.6 24.1-78.2 74.6-94.9 98.5l-2.3 3.3 8.9 9c35.4 36.5 89.5 69.1 145 87.5 9 3 17 5.4 17.8 5.4s10.3-8.9 21.2-19.8c31.4-31.4 55.1-49.9 88.8-69.3 45.9-26.3 105-45.6 155-50.4 3.9-.4 8.1-.9 9.5-1.2 4.4-.9 57.3-1.2 64.5-.3 3.9.4 10.4 1.1 14.5 1.4 35.4 3.2 86.5 17 120.5 32.6 15.4 7 18.5 8.6 31.4 15.7C914.2 312.3 991 426.3 1006.6 555c.3 3 .8 6.6 1 8 .9 5 1.1 61.9.3 74-.5 6.9-1.6 17-2.5 22.5s-1.8 11.3-2.1 13c-1.3 8.4-7.8 35.5-11.3 47.2-7.6 25.1-14.6 42.6-26.5 66.3-19.3 38.7-40.7 68.3-72.3 100-21.1 21.3-30.2 29.5-43.2 39.3-58 43.7-130.6 73-197.5 79.6-5.5.6-12.7 1.3-16 1.6-8.4.8-51.3.9-61.5.1-80.8-6.4-156.3-36-219.3-85.9-47-37.1-83.5-81.5-110.2-134.1-5-9.8-7.5-13.6-8.7-13.6-1 0-7.1 1.7-13.6 3.9-39.5 13.1-73.7 30.9-101.2 52.7-16.1 12.9-42.5 40.7-49.1 51.8l-2 3.5 3.4 6.8c8.1 16.1 30.6 51.2 46 71.8 44.7 59.7 99.2 110.4 161.5 150.3 6.2 3.9 11.4 7.2 11.6 7.2s4.5 2.5 9.5 5.5c16.6 9.9 35.9 19.7 65.6 33.1 13 5.8 43 16.6 62.2 22.3 34 10.1 61.4 16 96.5 20.6 11.1 1.5 14.5 1.9 32.3 3.4 23.3 2 76 1.8 98.5-.4 7.5-.8 38.3-4.5 40.6-4.9 1.1-.2 3.9-.7 6.4-1.1 22.1-3.6 55-11.3 75.4-17.6 15.8-4.9 40.6-13.6 48.1-16.9 1.1-.5 6.5-2.8 12-5 16-6.6 54.7-26.1 71.3-35.9 59-34.7 110.9-78.6 155.3-131.3 76.9-91.1 124.9-202 138.3-319.3.8-7.2 1.8-15 2.1-17.5 1-7.2 1.4-88.6.5-98-.5-4.7-1.4-13.2-2-19-11.9-109.6-53.2-214-118.8-300-20.8-27.3-36.9-45-70.4-77.6-24.9-24.3-66.3-55.6-100.1-75.8C858.5 50.9 792.3 25 728 12c-19.9-4.1-47.2-8.3-61.5-9.5-4.4-.4-9.1-1-10.5-1.2-3.3-.6-89.4-1.5-90-1"/><path d="M535.3 302.2c-7.1.6-12.1 1.4-25.8 4.2-1.1.3-6 1.6-11 3.1-19.3 5.6-39.1 14.8-59 27.3-6.6 4.1-16.2 9.5-21.4 12-15 7.1-61.7 21.7-82.6 25.8-12.8 2.5-25.4 4.3-37 5.2-12.2 1-71.5.9-84.4-.1-40.4-3.1-95.1-14.5-139.3-29L59 345.5l-2.6 5.5c-8.3 17.3-23.9 58.4-29.9 79-17 57.9-24.9 113-24.9 173 0 28.3 2.3 65.9 4.9 80 .2 1.4.7 4.5 1 7 2.6 19.8 10.4 57.3 12.3 59.2.8.8 6-.5 17.4-4 46.6-14.6 88.3-24.1 140.8-32.2 6.9-1 15-2.2 18-2.5s6.2-.8 7-1c2.4-.6 42.2-4.4 56-5.2 25.2-1.6 85.8-.8 108.5 1.3 75.3 7.1 103.2 14.3 133.2 34.4 9.8 6.6 11.1 7.8 24.8 21.5 10.6 10.6 15.6 17.1 44 56.5 44.5 61.9 53.9 74.3 63.8 83.6 16.1 15.3 37.7 27.1 58.2 31.9 17 4 44.8 4.1 59.5.2 30-8 50.1-20.3 68.1-41.7 13.6-16.1 22.7-35.6 28.5-61.5.3-1.7.8-11.6 1-22 .5-28.1 0-30.3-18.3-80-4.7-12.7-9.3-25.3-10.3-28-7.1-19.4-63.7-169.5-76.1-201.5-8.3-21.7-16.2-42.2-17.4-45.5-6.8-18-22.4-55.6-27.4-66-12.7-26.4-29.7-46.4-51.6-60.7-20.3-13.2-49.1-23.1-71-24.3-16.4-1-32.5-1.1-41.2-.3m9.8 141.6c9.9 4.8 15.9 13.8 16.6 25.1 1.2 16.5-10.2 29.7-26.7 30.9-18 1.3-31.9-10.8-32.1-28-.2-14.7 7.3-25.4 21.1-29.9 4.7-1.5 16.2-.5 21.1 1.9m-62.9 56.5c13.4 3.5 22.5 16.8 21.2 30.9-1 10.1-6.2 18.2-15.3 23.6-3.5 2.1-5.9 2.6-12 2.8-11.9.4-15.6-.9-22.8-8.1-5-5-6.5-7.2-7.8-12-4.2-14.3 2.2-28.7 15.7-35.5 6.8-3.3 12.9-3.9 21-1.7m121.3 1.5c5.4 2.7 10.9 8.4 13.7 14.1 1.8 3.7 2.3 6.3 2.3 13.1 0 7.6-.3 9.1-3 13.8-3.5 6.4-7.1 9.7-14.4 13-4.6 2.1-6.3 2.4-13.5 2-9-.5-12.5-1.9-18.7-7.5-5.9-5.3-8.1-10.4-8.7-19.4-.8-13.9 4.8-23.7 17.1-29.5 4.6-2.2 6.2-2.5 13.2-2.1 5.5.3 9.4 1.1 12 2.5m-58.6 58.3c22.4 9.6 22.3 44.2 0 53.8-8.6 3.8-21.7 3.1-28.6-1.5-20.3-13.2-17.1-44.4 5.5-53.5 6-2.5 15.9-2 23.1 1.2"/></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
19
frontend/public/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "RomM",
|
||||
"short_name": "RomM",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#2a0145",
|
||||
"background_color": "#2a0145",
|
||||
"display": "standalone"
|
||||
}
|
||||
@@ -138,8 +138,8 @@ function closeDialog() {
|
||||
imagePreviewUrl
|
||||
? imagePreviewUrl
|
||||
: user.avatar_path
|
||||
? `/assets/romm/assets/${user.avatar_path}?ts=${user.updated_at}`
|
||||
: defaultAvatarPath
|
||||
? `/assets/romm/assets/${user.avatar_path}?ts=${user.updated_at}`
|
||||
: defaultAvatarPath
|
||||
"
|
||||
>
|
||||
<v-fade-transition>
|
||||
|
||||
@@ -21,7 +21,7 @@ const romUser = ref(
|
||||
note_raw_markdown: "",
|
||||
note_is_public: false,
|
||||
is_main_sibling: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
const publicNotes =
|
||||
props.rom.user_notes?.filter((note) => note.user_id !== auth.user?.id) ?? [];
|
||||
@@ -61,7 +61,7 @@ watch(
|
||||
note_is_public: false,
|
||||
is_main_sibling: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
@@ -131,11 +131,7 @@ watch(
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-card
|
||||
rounded="0"
|
||||
v-if="publicNotes && publicNotes.length > 0"
|
||||
class="mt-2"
|
||||
>
|
||||
<v-card rounded="0" v-if="publicNotes && publicNotes.length > 0" class="mt-2">
|
||||
<v-card-title class="bg-terciary">
|
||||
<v-list-item class="pl-2 pr-0">
|
||||
<span class="text-h6">Public notes</span>
|
||||
|
||||
@@ -60,7 +60,7 @@ async function downloasSaves() {
|
||||
function updateDataTablePages() {
|
||||
if (props.rom.user_saves) {
|
||||
pageCount.value = Math.ceil(
|
||||
props.rom.user_saves.length / itemsPerPage.value
|
||||
props.rom.user_saves.length / itemsPerPage.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ async function downloasStates() {
|
||||
function updateDataTablePages() {
|
||||
if (props.rom.user_states) {
|
||||
pageCount.value = Math.ceil(
|
||||
props.rom.user_states.length / itemsPerPage.value
|
||||
props.rom.user_states.length / itemsPerPage.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useDisplay } from "vuetify";
|
||||
import AdminMenu from "@/components/Gallery/AppBar/Platform/AdminMenu.vue";
|
||||
import FilterBtn from "@/components/Gallery/AppBar/common/FilterBtn.vue";
|
||||
import FilterTextField from "@/components/Gallery/AppBar/common/FilterTextField.vue";
|
||||
import FirmwareBtn from "@/components/Gallery/AppBar/Platform/FirmwareBtn.vue";
|
||||
import FirmwareDrawer from "@/components/Gallery/AppBar/Platform/FirmwareDrawer.vue";
|
||||
import FilterBtn from "@/components/Gallery/AppBar/common/FilterBtn.vue";
|
||||
import FilterDrawer from "@/components/Gallery/AppBar/common/FilterDrawer/Base.vue";
|
||||
import FilterTextField from "@/components/Gallery/AppBar/common/FilterTextField.vue";
|
||||
import GalleryViewBtn from "@/components/Gallery/AppBar/common/GalleryViewBtn.vue";
|
||||
import SelectingBtn from "@/components/Gallery/AppBar/common/SelectingBtn.vue";
|
||||
import FilterDrawer from "@/components/Gallery/AppBar/common/FilterDrawer/Base.vue";
|
||||
import FirmwareDrawer from "@/components/Gallery/AppBar/Platform/FirmwareDrawer.vue";
|
||||
import PlatformIcon from "@/components/common/Platform/Icon.vue";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
const { xs } = useDisplay();
|
||||
const romsStore = storeRoms();
|
||||
@@ -28,7 +28,7 @@ const auth = storeAuth();
|
||||
:slug="currentPlatform.slug"
|
||||
:name="currentPlatform.name"
|
||||
:size="36"
|
||||
class="mx-2"
|
||||
class="ml-3 mr-2 platform-icon"
|
||||
/>
|
||||
<firmware-btn />
|
||||
<filter-btn />
|
||||
@@ -60,4 +60,7 @@ const auth = storeAuth();
|
||||
#gallery-app-bar {
|
||||
z-index: 999 !important;
|
||||
}
|
||||
.platform-icon {
|
||||
filter: drop-shadow(0px 0px 2px #a452fe);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -53,7 +53,7 @@ function deleteSelectedFirmware() {
|
||||
|
||||
function updateDataTablePages() {
|
||||
pageCount.value = Math.ceil(
|
||||
Number(currentPlatform.value?.firmware?.length) / itemsPerPage.value
|
||||
Number(currentPlatform.value?.firmware?.length) / itemsPerPage.value,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,10 +74,7 @@ function closeDialog() {
|
||||
<v-row class="justify-center mb-2" no-gutters>
|
||||
<v-btn-group divided density="compact">
|
||||
<v-btn class="bg-terciary" @click="closeDialog"> Cancel </v-btn>
|
||||
<v-btn
|
||||
class="bg-terciary text-romm-red"
|
||||
@click="deleteBindPlatform"
|
||||
>
|
||||
<v-btn class="bg-terciary text-romm-red" @click="deleteBindPlatform">
|
||||
Confirm
|
||||
</v-btn>
|
||||
</v-btn-group>
|
||||
|
||||
@@ -146,13 +146,15 @@ function closeDialog() {
|
||||
<template #append-inner>
|
||||
<v-btn-group rounded="0" divided density="compact">
|
||||
<v-btn
|
||||
:disabled="!heartbeat.value.METADATA_SOURCES?.STEAMGRIDDB_ENABLED"
|
||||
:disabled="
|
||||
!heartbeat.value.METADATA_SOURCES?.STEAMGRIDDB_ENABLED
|
||||
"
|
||||
size="small"
|
||||
class="translucent-dark"
|
||||
@click="
|
||||
emitter?.emit(
|
||||
'showSearchCoverDialog',
|
||||
collection.name as string
|
||||
collection.name as string,
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -134,7 +134,11 @@ function closeDialog() {
|
||||
<v-col>
|
||||
<v-switch
|
||||
v-model="collection.is_public"
|
||||
:label="collection.is_public ? 'Public (visible to everyone)' : 'Private (only visible to me)'"
|
||||
:label="
|
||||
collection.is_public
|
||||
? 'Public (visible to everyone)'
|
||||
: 'Private (only visible to me)'
|
||||
"
|
||||
color="romm-accent-1"
|
||||
class="px-2"
|
||||
hide-details
|
||||
@@ -155,13 +159,15 @@ function closeDialog() {
|
||||
<template #append-inner>
|
||||
<v-btn-group rounded="0" divided density="compact">
|
||||
<v-btn
|
||||
:disabled="!heartbeat.value.METADATA_SOURCES?.STEAMGRIDDB_ENABLED"
|
||||
:disabled="
|
||||
!heartbeat.value.METADATA_SOURCES?.STEAMGRIDDB_ENABLED
|
||||
"
|
||||
size="small"
|
||||
class="translucent-dark"
|
||||
@click="
|
||||
emitter?.emit(
|
||||
'showSearchCoverDialog',
|
||||
collection.name as string
|
||||
collection.name as string,
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -40,7 +40,7 @@ const PER_PAGE_OPTIONS = [10, 25, 50, 100];
|
||||
async function removeRomsFromCollection() {
|
||||
if (!selectedCollection.value) return;
|
||||
selectedCollection.value.roms = selectedCollection.value.roms.filter(
|
||||
(id) => !roms.value.map((r) => r.id).includes(id)
|
||||
(id) => !roms.value.map((r) => r.id).includes(id),
|
||||
);
|
||||
await collectionApi
|
||||
.updateCollection({ collection: selectedCollection.value })
|
||||
|
||||
@@ -21,7 +21,6 @@ const collectionsStore = storeCollections();
|
||||
const romsStore = storeRoms();
|
||||
const { favCollection } = storeToRefs(collectionsStore);
|
||||
|
||||
// Functions
|
||||
async function switchFromFavourites() {
|
||||
if (!favCollection.value) {
|
||||
await collectionApi
|
||||
@@ -53,7 +52,7 @@ async function switchFromFavourites() {
|
||||
} else {
|
||||
if (favCollection.value) {
|
||||
favCollection.value.roms = favCollection.value.roms.filter(
|
||||
(id) => id !== props.rom.id
|
||||
(id) => id !== props.rom.id,
|
||||
);
|
||||
if (romsStore.currentCollection?.name.toLowerCase() == "favourites") {
|
||||
romsStore.remove([props.rom]);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import AdminMenu from "@/components/common/Game/AdminMenu.vue";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeDownload from "@/stores/download";
|
||||
import storeHeartbeat from "@/stores/heartbeat";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { isEJSEmulationSupported, isRuffleEmulationSupported } from "@/utils";
|
||||
import { computed } from "vue";
|
||||
|
||||
// Props
|
||||
const props = defineProps<{ rom: SimpleRom }>();
|
||||
@@ -37,7 +37,10 @@ const ruffleEmulationSupported = computed(() => {
|
||||
@click="romApi.downloadRom({ rom })"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col class="d-flex">
|
||||
<v-col
|
||||
v-if="ejsEmulationSupported || ruffleEmulationSupported"
|
||||
class="d-flex"
|
||||
>
|
||||
<v-btn
|
||||
v-if="ejsEmulationSupported"
|
||||
class="action-bar-btn-small flex-grow-1"
|
||||
@@ -67,19 +70,21 @@ const ruffleEmulationSupported = computed(() => {
|
||||
variant="text"
|
||||
/>
|
||||
</v-col>
|
||||
<v-menu location="bottom">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
class="action-bar-btn-small flex-grow-1"
|
||||
size="x-small"
|
||||
v-bind="props"
|
||||
icon="mdi-dots-vertical"
|
||||
rounded="0"
|
||||
variant="text"
|
||||
/>
|
||||
</template>
|
||||
<admin-menu :rom="rom" />
|
||||
</v-menu>
|
||||
<v-col class="d-flex">
|
||||
<v-menu location="bottom">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
class="action-bar-btn-small flex-grow-1"
|
||||
size="x-small"
|
||||
v-bind="props"
|
||||
icon="mdi-dots-vertical"
|
||||
rounded="0"
|
||||
variant="text"
|
||||
/>
|
||||
</template>
|
||||
<admin-menu :rom="rom" />
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ function confirm() {
|
||||
updateRom(
|
||||
Object.assign(selectedMatchRom.value, {
|
||||
url_cover: selectedCover.value.url_cover,
|
||||
})
|
||||
}),
|
||||
);
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ async function switchFromFavourites() {
|
||||
} else {
|
||||
if (favCollection.value) {
|
||||
favCollection.value.roms = favCollection.value.roms.filter(
|
||||
(id) => id !== props.rom.id
|
||||
(id) => id !== props.rom.id,
|
||||
);
|
||||
if (romsStore.currentCollection?.name.toLowerCase() == "favourites") {
|
||||
romsStore.remove([props.rom]);
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from "@/utils";
|
||||
import { isNull } from "lodash";
|
||||
import type { Emitter } from "mitt";
|
||||
import { inject, onMounted, ref, watch } from "vue";
|
||||
import { inject, onMounted, ref, watch, computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
@@ -77,6 +77,10 @@ const HEADERS = [
|
||||
{ title: "", align: "end", key: "actions", sortable: false },
|
||||
] as const;
|
||||
|
||||
const selectedRomIDs = computed(() =>
|
||||
romsStore.selectedRoms.map((rom) => rom.id),
|
||||
);
|
||||
|
||||
// Functions
|
||||
function rowClick(_: Event, row: { item: SimpleRom }) {
|
||||
router.push({ name: "rom", params: { rom: row.item.id } });
|
||||
@@ -100,6 +104,14 @@ function checkIfRuffleEmulationSupported(platformSlug: string) {
|
||||
return isRuffleEmulationSupported(platformSlug, heartbeatStore.value);
|
||||
}
|
||||
|
||||
function updateSelectedRom(rom: SimpleRom) {
|
||||
if (selectedRomIDs.value.includes(rom.id)) {
|
||||
romsStore.removeFromSelection(rom);
|
||||
} else {
|
||||
romsStore.addToSelection(rom);
|
||||
}
|
||||
}
|
||||
|
||||
watch(itemsPerPage, async () => {
|
||||
localStorage.setItem("romsPerPage", itemsPerPage.value.toString());
|
||||
updateDataTablePages();
|
||||
@@ -123,7 +135,7 @@ onMounted(() => {
|
||||
:item-value="(item) => item.id"
|
||||
:items="romsStore.filteredRoms"
|
||||
:headers="HEADERS"
|
||||
v-model="romsStore._selectedIDs"
|
||||
v-model="selectedRomIDs"
|
||||
v-model:page="page"
|
||||
show-select
|
||||
fixed-header
|
||||
@@ -131,6 +143,13 @@ onMounted(() => {
|
||||
hide-default-footer
|
||||
hover
|
||||
>
|
||||
<template #item.data-table-select="{ item }">
|
||||
<v-checkbox-btn
|
||||
:value="item.id"
|
||||
@click.stop
|
||||
@click="updateSelectedRom(item)"
|
||||
/>
|
||||
</template>
|
||||
<template #item.name="{ item }">
|
||||
<td class="name-row">
|
||||
<v-list-item class="px-0">
|
||||
|
||||
@@ -29,7 +29,7 @@ withDefaults(
|
||||
icon: null,
|
||||
width: "",
|
||||
height: "",
|
||||
}
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(["update:modelValue", "close"]);
|
||||
const hasToolbarSlot = ref(false);
|
||||
|
||||
@@ -47,7 +47,7 @@ async function searchCovers() {
|
||||
coverType.value === "all"
|
||||
? game.resources
|
||||
: game.resources.filter(
|
||||
(resource) => resource.type === coverType.value
|
||||
(resource) => resource.type === coverType.value,
|
||||
),
|
||||
};
|
||||
})
|
||||
@@ -81,7 +81,7 @@ function filterCovers() {
|
||||
coverType.value === "all"
|
||||
? game.resources
|
||||
: game.resources.filter(
|
||||
(resource) => resource.type === coverType.value
|
||||
(resource) => resource.type === coverType.value,
|
||||
),
|
||||
};
|
||||
})
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import storeUpload from "@/stores/upload";
|
||||
import { formatBytes } from "@/utils";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ref, watch } from "vue";
|
||||
import { useDisplay } from "vuetify";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
const { xs } = useDisplay();
|
||||
const uploadStore = storeUpload();
|
||||
@@ -49,8 +49,8 @@ watch(files, (newList) => {
|
||||
<v-list-item-title class="d-flex justify-space-between">
|
||||
{{ file.filename }}
|
||||
<v-icon
|
||||
:icon="file.finished ? `mdi-check` : `mdi-loading mdi-spin`"
|
||||
:color="file.finished ? `green` : `white`"
|
||||
:icon="file.finished ? 'mdi-check' : 'mdi-loading mdi-spin'"
|
||||
:color="file.finished ? 'green' : 'romm-accent-1'"
|
||||
class="mx-2"
|
||||
/>
|
||||
</v-list-item-title>
|
||||
@@ -58,7 +58,7 @@ watch(files, (newList) => {
|
||||
<v-progress-linear
|
||||
v-model="file.progress"
|
||||
height="4"
|
||||
color="white"
|
||||
color="romm-accent-1"
|
||||
class="mt-1"
|
||||
/>
|
||||
<div class="upload-speeds d-flex justify-space-between mt-1">
|
||||
|
||||
@@ -68,6 +68,7 @@ async function getRoms({
|
||||
search_term: searchTerm,
|
||||
order_by: orderBy,
|
||||
order_dir: orderDir,
|
||||
limit: 2500,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ watch(
|
||||
() => route.fullPath,
|
||||
async () => {
|
||||
await fetchDetails();
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ onBeforeMount(async () => {
|
||||
collectionsStore.set(collections);
|
||||
collectionsStore.setFavCollection(
|
||||
collections.find(
|
||||
(collection) => collection.name.toLowerCase() === "favourites"
|
||||
)
|
||||
(collection) => collection.name.toLowerCase() === "favourites",
|
||||
),
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { defineConfig, loadEnv } from "vite";
|
||||
export default defineConfig(({ mode }) => {
|
||||
// Load ENV variables from the parent directory and the current directory.
|
||||
const env = { ...loadEnv(mode, "../"), ...loadEnv(mode, "./") };
|
||||
const backendPort = env.VITE_BACKEND_DEV_PORT ?? "5000";
|
||||
const backendPort = env.DEV_PORT ?? "5000";
|
||||
|
||||
return {
|
||||
build: {
|
||||
|
||||
91
poetry.lock
generated
@@ -390,43 +390,38 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "42.0.8"
|
||||
version = "43.0.1"
|
||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
|
||||
{file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"},
|
||||
{file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"},
|
||||
{file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"},
|
||||
{file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"},
|
||||
{file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"},
|
||||
{file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"},
|
||||
{file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"},
|
||||
{file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"},
|
||||
{file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"},
|
||||
{file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -439,7 +434,7 @@ nox = ["nox"]
|
||||
pep8test = ["check-sdist", "click", "mypy", "ruff"]
|
||||
sdist = ["build"]
|
||||
ssh = ["bcrypt (>=3.1.5)"]
|
||||
test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
|
||||
test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
|
||||
test-randomorder = ["pytest-randomly"]
|
||||
|
||||
[[package]]
|
||||
@@ -2885,6 +2880,7 @@ description = "Automatically mock your HTTP interactions to simplify and speed u
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "vcrpy-6.0.1-py2.py3-none-any.whl", hash = "sha256:621c3fb2d6bd8aa9f87532c688e4575bcbbde0c0afeb5ebdb7e14cac409edfdd"},
|
||||
{file = "vcrpy-6.0.1.tar.gz", hash = "sha256:9e023fee7f892baa0bbda2f7da7c8ac51165c1c6e38ff8688683a12a4bde9278"},
|
||||
]
|
||||
|
||||
@@ -3229,7 +3225,32 @@ files = [
|
||||
idna = ">=2.0"
|
||||
multidict = ">=4.0"
|
||||
|
||||
[[package]]
|
||||
name = "zipfile-deflate64"
|
||||
version = "0.2.0"
|
||||
description = "Extract Deflate64 ZIP archives with Python's zipfile API."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "zipfile-deflate64-0.2.0.tar.gz", hash = "sha256:875a3299de102edf1c17f8cafcc528b1ca80b62dc4814b9cb56867ec59fbfd18"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:5ed1c3edc08e8da8fe646b23105e2840f305ce2a75360aa0df7523c1263f43aa"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b4ab8d83bb277983ff273cbf4fcf831023abbc2303f90af9dd4bde3ab4b9c2"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:f868343cd24bd3c66fbcba9316c6a970f934653bf3d0be89f25fa0335a7ea3ff"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:f5313c31e92a8be7e0fed7648b553f041287715d7a28fbfbbadec1dd8e7b773b"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096cc9c2a896436ffb27e2cfff60402ca4304b1fbe782265a8c1b2d11dc598a"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5b9e0a0d5d742aa4006ab18d31eabc9a83809be3d27dad34707fa136cafa0950"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:3f7b5f3305880a784e335c9fa1bc33a6a3a8436cdbf3e473690f4da0eb866645"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c79e8d3356eb72b9be25bcc36ce3320cbe1f50606f355193d6ad8ead8130fd5"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:84432465d0c497c774122073b79ec7fa9ebf28cf066cce5f1a5726dad455086f"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:f30f7981689dcf06e2789a2adbf3ff0711e58a710780205c2747ec793373fa2e"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc673ff44f1e7fa673b34507d04e6e0b750be372e4f33e40a9364858ef22411f"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:dadfdd07f15c0abf394e0599b06a894120ca6f40ded9720c68b267a4ecf8bf48"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:d6bb582256f374f5a8570616480f07df0d74460b8c80aaa5fb047a73ff38bcd2"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8557a77c2b6ee8afb49759d9b4c1a9785ca05366cbc4b2c577a859ecba62b85"},
|
||||
{file = "zipfile_deflate64-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:a16cd144c12de642f0ace1aeab7f50e7abc7492c81381faa2b17cc36f38272c4"},
|
||||
]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.12"
|
||||
content-hash = "cfe0cc6ccf4d75141fa2c4c5ebce9011b17040ff09171595a579d317710b9789"
|
||||
content-hash = "68a20b03af6c0f1bdf77a7f110c3b7cb331abf28ea90572bc6e24da85ae58825"
|
||||
|
||||
@@ -43,6 +43,7 @@ certifi = "2024.07.04"
|
||||
python-magic = "^0.4.27"
|
||||
py7zr = "^0.21.1"
|
||||
streaming-form-data = "^1.16.0"
|
||||
zipfile-deflate64 = "^0.2.0"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
fakeredis = "^2.21.3"
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<Container version="2">
|
||||
<Name>RomM</Name>
|
||||
<Repository>rommapp/romm:latest</Repository>
|
||||
<Registry>https://hub.docker.com/r/rommapp/romm</Registry>
|
||||
<Network>bridge</Network>
|
||||
<MyIP/>
|
||||
<Shell>sh</Shell>
|
||||
<Privileged>false</Privileged>
|
||||
<Support>https://github.com/rommapp/romm/issues</Support>
|
||||
<Project>https://github.com/rommapp/romm</Project>
|
||||
<Overview>RomM is a game library manager focused on retro games. Manage and organize all of your games from a web browser.</Overview>
|
||||
<ExtraSearchTerms>rom emulation gaming</ExtraSearchTerms>
|
||||
<Beta>False</Beta>
|
||||
<Category>MediaApp:Other</Category>
|
||||
<Date>2023-08-06</Date>
|
||||
<WebUI>http://[IP]:[PORT:8080]</WebUI>
|
||||
<TemplateURL/>
|
||||
<Icon>https://raw.githubusercontent.com/rommapp/romm/master/.github/resources/isotipo.png</Icon>
|
||||
<ExtraParams/>
|
||||
<PostArgs/>
|
||||
<CPUset/>
|
||||
<Requires>
|
||||
MariaDB
|
||||
</Requires>
|
||||
<Screenshot>https://raw.githubusercontent.com/rommapp/romm/master/.github/resources/screenshots/home.png</Screenshot>
|
||||
<Screenshot>https://raw.githubusercontent.com/rommapp/romm/master/.github/resources/screenshots/gallery.png</Screenshot>
|
||||
<Screenshot>https://raw.githubusercontent.com/rommapp/romm/master/.github/resources/screenshots/details.png</Screenshot>
|
||||
<Screenshot>https://raw.githubusercontent.com/rommapp/romm/master/.github/resources/screenshots/search.png</Screenshot>
|
||||
<Config Name="Port" Target="8080" Default="8080" Mode="tcp" Description="" Type="Port" Display="always" Required="false" Mask="false">8080</Config>
|
||||
<Config Name="Library" Target="/romm/library/" Default="/romm/library" Mode="rw" Description="Game files" Type="Path" Display="always" Required="true" Mask="false"/>
|
||||
<Config Name="Resources" Target="/romm/resources/" Default="" Mode="rw" Description="Metadata storage (covers, screenshots, etc.)" Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/romm/resources</Config>
|
||||
<Config Name="Assets" Target="/romm/assets/" Default="" Mode="rw" Description="Uploaded saves, states, etc." Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/romm/assets</Config>
|
||||
<Config Name="IGDB_CLIENT_ID" Target="IGDB_CLIENT_ID" Default="" Mode="" Description="IGDB Client ID" Type="Variable" Display="always" Required="true" Mask="false"/>
|
||||
<Config Name="IGDB_CLIENT_SECRET" Target="IGDB_CLIENT_SECRET" Default="" Mode="" Description="IGDB Client Secret" Type="Variable" Display="always" Required="true" Mask="true"/>
|
||||
<Config Name="DB_HOST" Target="DB_HOST" Default="mariadb" Mode="" Description="Database host" Type="Variable" Display="advanced" Required="true" Mask="false"/>
|
||||
<Config Name="DB_PORT" Target="DB_PORT" Default="3306" Mode="" Description="Database port" Type="Variable" Display="advanced" Required="true" Mask="false"/>
|
||||
<Config Name="DB_USER" Target="DB_USER" Default="romm" Mode="" Description="Database user" Type="Variable" Display="advanced" Required="true" Mask="false"/>
|
||||
<Config Name="DB_NAME" Target="DB_NAME" Default="romm" Mode="" Description="Database name" Type="Variable" Display="advanced" Required="true" Mask="false"/>
|
||||
<Config Name="DB_PASSWD" Target="DB_PASSWD" Default="" Mode="" Description="Database password for DB_USER" Type="Variable" Display="advanced" Required="true" Mask="true"/>
|
||||
<Config Name="REDIS_HOST" Target="REDIS_HOST" Default="127.0.0.1" Mode="" Description="Redis host" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_PORT" Target="REDIS_PORT" Default="6379" Mode="" Description="Redis port" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_PASSWORD" Target="REDIS_PASSWORD" Default="" Mode="" Description="Redis password" Type="Variable" Display="advanced" Required="false" Mask="true"/>
|
||||
<Config Name="REDIS_USERNAME" Target="REDIS_USERNAME" Default="" Mode="" Description="Redis username" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_DB" Target="REDIS_DB" Default="0" Mode="" Description="Redis database" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ROMM_AUTH_PASSWORD" Target="ROMM_AUTH_PASSWORD" Default="" Mode="" Description="Default admin password" Type="Variable" Display="advanced" Required="false" Mask="true"/>
|
||||
<Config Name="ROMM_AUTH_SECRET_KEY" Target="ROMM_AUTH_SECRET_KEY" Default="" Mode="" Description="Generate a key with `openssl rand -hex 32`" Type="Variable" Display="advanced" Required="false" Mask="true"/>
|
||||
<Config Name="ENABLE_RESCAN_ON_FILESYSTEM_CHANGE" Target="ENABLE_RESCAN_ON_FILESYSTEM_CHANGE" Default="false" Mode="" Description="Run a scan when the filesystem changes" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="RESCAN_ON_FILESYSTEM_CHANGE_DELAY" Target="RESCAN_ON_FILESYSTEM_CHANGE_DELAY" Default="5" Mode="" Description="Delay in seconds before running a scan" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ENABLE_SCHEDULED_RESCAN" Target="ENABLE_SCHEDULED_RESCAN" Default="false" Mode="" Description="Run a scan on a schedule" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="SCHEDULED_RESCAN_CRON" Target="SCHEDULED_RESCAN_CRON" Default="0 3 * * *" Mode="" Description="Cron expression for scheduled scan" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ENABLE_SCHEDULED_UPDATE_SWITCH_TITLEDB" Target="ENABLE_SCHEDULED_UPDATE_SWITCH_TITLEDB" Default="false" Mode="" Description="Update Switch TitleDB on a schedule" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON" Target="SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON" Default="0 4 * * *" Mode="" Description="Cron expression for scheduled Switch TitleDB update" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
</Container>
|
||||