mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Merge branch 'master' into trunk-io
This commit is contained in:
@@ -31,7 +31,6 @@ class ScreenshotSchema(BaseAsset):
|
||||
class UploadedScreenshotsResponse(TypedDict):
|
||||
uploaded: int
|
||||
screenshots: list[ScreenshotSchema]
|
||||
url_screenshots: list[str]
|
||||
merged_screenshots: list[str]
|
||||
|
||||
|
||||
|
||||
@@ -92,16 +92,8 @@ class RomSchema(BaseModel):
|
||||
|
||||
multi: bool
|
||||
files: list[str]
|
||||
url_screenshots: list[str]
|
||||
merged_screenshots: list[str]
|
||||
full_path: str
|
||||
|
||||
sibling_roms: list["RomSchema"] = Field(default_factory=list)
|
||||
user_saves: list[SaveSchema] = Field(default_factory=list)
|
||||
user_states: list[StateSchema] = Field(default_factory=list)
|
||||
user_screenshots: list[ScreenshotSchema] = Field(default_factory=list)
|
||||
user_notes: list[RomNoteSchema] = Field(default_factory=list)
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
@@ -118,8 +110,17 @@ class RomSchema(BaseModel):
|
||||
.lower()
|
||||
)
|
||||
|
||||
|
||||
class DetailedRomSchema(RomSchema):
|
||||
merged_screenshots: list[str]
|
||||
sibling_roms: list["RomSchema"] = Field(default_factory=list)
|
||||
user_saves: list[SaveSchema] = Field(default_factory=list)
|
||||
user_states: list[StateSchema] = Field(default_factory=list)
|
||||
user_screenshots: list[ScreenshotSchema] = Field(default_factory=list)
|
||||
user_notes: list[RomNoteSchema] = Field(default_factory=list)
|
||||
|
||||
@classmethod
|
||||
def from_orm_with_request(cls, db_rom: Rom, request: Request) -> "RomSchema":
|
||||
def from_orm_with_request(cls, db_rom: Rom, request: Request) -> "DetailedRomSchema":
|
||||
rom = cls.model_validate(db_rom)
|
||||
user_id = request.user.id
|
||||
|
||||
|
||||
@@ -9,4 +9,3 @@ class SearchRomSchema(BaseModel):
|
||||
summary: str
|
||||
igdb_url_cover: str = ""
|
||||
moby_url_cover: str = ""
|
||||
url_screenshots: list[str]
|
||||
|
||||
@@ -10,14 +10,13 @@ from endpoints.responses import MessageResponse
|
||||
from endpoints.responses.rom import (
|
||||
AddRomsResponse,
|
||||
CustomStreamingResponse,
|
||||
DetailedRomSchema,
|
||||
RomNoteSchema,
|
||||
RomSchema,
|
||||
)
|
||||
from exceptions.fs_exceptions import RomAlreadyExistsException
|
||||
from fastapi import APIRouter, HTTPException, Query, Request, UploadFile, status
|
||||
from fastapi import APIRouter, HTTPException, Query, Request, UploadFile, File, status
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi_pagination.cursor import CursorPage, CursorParams
|
||||
from fastapi_pagination.ext.sqlalchemy import paginate
|
||||
from handler.database import db_platform_handler, db_rom_handler
|
||||
from handler.filesystem import fs_resource_handler, fs_rom_handler
|
||||
from handler.filesystem.base_handler import CoverSize
|
||||
@@ -87,13 +86,12 @@ def add_roms(
|
||||
@protected_route(router.get, "/roms", ["roms.read"])
|
||||
def get_roms(
|
||||
request: Request,
|
||||
platform_id: int | None = None,
|
||||
size: int = 60,
|
||||
cursor: str = "",
|
||||
platform_id: int = None,
|
||||
search_term: str = "",
|
||||
limit: int = None,
|
||||
order_by: str = "name",
|
||||
order_dir: str = "asc",
|
||||
) -> CursorPage[RomSchema]:
|
||||
) -> list[RomSchema]:
|
||||
"""Get roms endpoint
|
||||
|
||||
Args:
|
||||
@@ -101,18 +99,18 @@ def get_roms(
|
||||
id (int, optional): Rom internal id
|
||||
|
||||
Returns:
|
||||
RomSchema: Rom stored in the database
|
||||
list[RomSchema]: List of roms stored in the database
|
||||
"""
|
||||
|
||||
with db_rom_handler.session.begin() as session:
|
||||
cursor_params = CursorParams(size=size, cursor=cursor)
|
||||
qq = db_rom_handler.get_roms(
|
||||
platform_id=platform_id,
|
||||
search_term=search_term.lower(),
|
||||
order_by=order_by.lower(),
|
||||
order_dir=order_dir.lower(),
|
||||
)
|
||||
return paginate(session, qq, cursor_params)
|
||||
return session.scalars(
|
||||
db_rom_handler.get_roms(
|
||||
platform_id=platform_id,
|
||||
search_term=search_term.lower(),
|
||||
order_by=order_by.lower(),
|
||||
order_dir=order_dir.lower(),
|
||||
).limit(limit)
|
||||
).all()
|
||||
|
||||
|
||||
@protected_route(
|
||||
@@ -120,7 +118,7 @@ def get_roms(
|
||||
"/roms/{id}",
|
||||
[] if DISABLE_DOWNLOAD_ENDPOINT_AUTH else ["roms.read"],
|
||||
)
|
||||
def get_rom(request: Request, id: int) -> RomSchema:
|
||||
def get_rom(request: Request, id: int) -> DetailedRomSchema:
|
||||
"""Get rom endpoint
|
||||
|
||||
Args:
|
||||
@@ -128,9 +126,9 @@ def get_rom(request: Request, id: int) -> RomSchema:
|
||||
id (int): Rom internal id
|
||||
|
||||
Returns:
|
||||
RomSchema: Rom stored in the database
|
||||
DetailedRomSchema: Rom stored in the database
|
||||
"""
|
||||
return RomSchema.from_orm_with_request(db_rom_handler.get_roms(id), request)
|
||||
return DetailedRomSchema.from_orm_with_request(db_rom_handler.get_roms(id), request)
|
||||
|
||||
|
||||
@protected_route(
|
||||
@@ -250,8 +248,8 @@ async def update_rom(
|
||||
id: int,
|
||||
rename_as_igdb: bool = False,
|
||||
remove_cover: bool = False,
|
||||
artwork: Optional[UploadFile] = None,
|
||||
) -> RomSchema:
|
||||
artwork: Optional[UploadFile] = File(None),
|
||||
) -> DetailedRomSchema:
|
||||
"""Update rom endpoint
|
||||
|
||||
Args:
|
||||
@@ -264,7 +262,7 @@ async def update_rom(
|
||||
HTTPException: If a rom already have that name when enabling the rename_as_igdb flag
|
||||
|
||||
Returns:
|
||||
RomSchema: Rom stored in the database
|
||||
DetailedRomSchema: Rom stored in the database
|
||||
"""
|
||||
|
||||
data = await request.form()
|
||||
@@ -378,7 +376,7 @@ async def update_rom(
|
||||
|
||||
db_rom_handler.update_rom(id, cleaned_data)
|
||||
|
||||
return db_rom_handler.get_roms(id)
|
||||
return DetailedRomSchema.from_orm_with_request(db_rom_handler.get_roms(id), request)
|
||||
|
||||
|
||||
@protected_route(router.post, "/roms/delete", ["roms.write"])
|
||||
|
||||
@@ -55,6 +55,5 @@ def add_screenshots(
|
||||
return {
|
||||
"uploaded": len(screenshots),
|
||||
"screenshots": [s for s in rom.screenshots if s.user_id == current_user.id],
|
||||
"url_screenshots": rom.url_screenshots,
|
||||
"merged_screenshots": rom.merged_screenshots,
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ async def search_rom(
|
||||
"summary": "",
|
||||
"igdb_url_cover": "",
|
||||
"moby_url_cover": "",
|
||||
"url_screenshots": [],
|
||||
},
|
||||
**item,
|
||||
}
|
||||
|
||||
@@ -92,7 +92,9 @@ async def scan_platforms(
|
||||
if platform and scan_type == ScanType.NEW_PLATFORMS:
|
||||
continue
|
||||
|
||||
scanned_platform = scan_platform(platform_slug, fs_platforms)
|
||||
scanned_platform = scan_platform(
|
||||
platform_slug, fs_platforms, metadata_sources=metadata_sources
|
||||
)
|
||||
if platform:
|
||||
scanned_platform.id = platform.id
|
||||
# Keep the existing ids if they exist on the platform
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
from fastapi.testclient import TestClient
|
||||
from unittest.mock import patch
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from main import app
|
||||
|
||||
client = TestClient(app)
|
||||
@@ -27,8 +26,8 @@ def test_get_all_roms(access_token, rom, platform):
|
||||
assert response.status_code == 200
|
||||
|
||||
body = response.json()
|
||||
assert len(body["items"]) == 1
|
||||
assert body["items"][0]["id"] == rom.id
|
||||
assert len(body) == 1
|
||||
assert body[0]["id"] == rom.id
|
||||
|
||||
|
||||
@patch("endpoints.rom.fs_rom_handler.rename_file")
|
||||
@@ -45,12 +44,6 @@ def test_update_rom(rename_file_mock, get_rom_by_id_mock, access_token, rom):
|
||||
"file_name": "Metroid Prime Remastered.zip",
|
||||
"summary": "summary test",
|
||||
"url_cover": "https://images.igdb.com/igdb/image/upload/t_cover_big/co2l7z.jpg",
|
||||
"url_screenshots": json.dumps(
|
||||
[
|
||||
"https://images.igdb.com/igdb/image/upload/t_original/qhiqlmwvvuaqxxn4cxlr.jpg",
|
||||
"https://images.igdb.com/igdb/image/upload/t_original/kqkixazzsokqgoxmuish.jpg",
|
||||
]
|
||||
),
|
||||
"genres": '[{"id": 5, "name": "Shooter"}, {"id": 8, "name": "Platform"}, {"id": 31, "name": "Adventure"}]',
|
||||
"franchises": '[{"id": 756, "name": "Metroid"}]',
|
||||
"collections": '[{"id": 243, "name": "Metroid"}, {"id": 6240, "name": "Metroid Prime"}]',
|
||||
|
||||
@@ -21,7 +21,11 @@ class DBFirmwareHandler(DBBaseHandler):
|
||||
return (
|
||||
session.scalar(select(Firmware).filter_by(id=id).limit(1))
|
||||
if id
|
||||
else select(Firmware).filter_by(platform_id=platform_id).all()
|
||||
else session.scalars(
|
||||
select(Firmware)
|
||||
.filter_by(platform_id=platform_id)
|
||||
.order_by(Firmware.file_name.asc())
|
||||
).all()
|
||||
)
|
||||
|
||||
@begin_session
|
||||
|
||||
@@ -11,8 +11,8 @@ from handler.filesystem import (
|
||||
fs_rom_handler,
|
||||
)
|
||||
from handler.metadata import meta_igdb_handler, meta_moby_handler
|
||||
from handler.metadata.igdb_handler import IGDBRom
|
||||
from handler.metadata.moby_handler import MobyGamesRom
|
||||
from handler.metadata.igdb_handler import IGDBRom, IGDBPlatform
|
||||
from handler.metadata.moby_handler import MobyGamesRom, MobyGamesPlatform
|
||||
from logger.logger import log
|
||||
from models.assets import Save, Screenshot, State
|
||||
from models.firmware import Firmware
|
||||
@@ -51,6 +51,7 @@ def _get_main_platform_igdb_id(platform: Platform):
|
||||
def scan_platform(
|
||||
fs_slug: str,
|
||||
fs_platforms: list[str],
|
||||
metadata_sources: list[str] = ["igdb", "moby"],
|
||||
) -> Platform:
|
||||
"""Get platform details
|
||||
|
||||
@@ -86,8 +87,16 @@ def scan_platform(
|
||||
except (KeyError, TypeError, AttributeError):
|
||||
platform_attrs["slug"] = fs_slug
|
||||
|
||||
igdb_platform = meta_igdb_handler.get_platform(platform_attrs["slug"])
|
||||
moby_platform = meta_moby_handler.get_platform(platform_attrs["slug"])
|
||||
igdb_platform = (
|
||||
meta_igdb_handler.get_platform(platform_attrs["slug"])
|
||||
if "igdb" in metadata_sources
|
||||
else IGDBPlatform(igdb_id=None, slug=platform_attrs["slug"])
|
||||
)
|
||||
moby_platform = (
|
||||
meta_moby_handler.get_platform(platform_attrs["slug"])
|
||||
if "moby" in metadata_sources
|
||||
else MobyGamesPlatform(moby_id=None, slug=platform_attrs["slug"])
|
||||
)
|
||||
|
||||
platform_attrs["name"] = platform_attrs["slug"].replace("-", " ").title()
|
||||
platform_attrs.update({**moby_platform, **igdb_platform}) # Reverse order
|
||||
|
||||
@@ -25,7 +25,6 @@ from endpoints import (
|
||||
)
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi_pagination import add_pagination
|
||||
from handler.auth import auth_handler
|
||||
from handler.auth.base_handler import ALGORITHM
|
||||
from handler.auth.hybrid_auth import HybridAuthBackend
|
||||
@@ -95,7 +94,6 @@ app.include_router(raw.router)
|
||||
app.include_router(screenshots.router)
|
||||
app.include_router(firmware.router)
|
||||
|
||||
add_pagination(app)
|
||||
app.mount("/ws", socket_handler.socket_app)
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ from sqlalchemy import (
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
func,
|
||||
select,
|
||||
and_,
|
||||
or_,
|
||||
)
|
||||
from sqlalchemy.dialects.mysql.json import JSON as MySQLJSON
|
||||
from sqlalchemy.orm import Mapped, relationship
|
||||
@@ -108,14 +111,17 @@ class Rom(BaseModel):
|
||||
def get_sibling_roms(self) -> list["Rom"]:
|
||||
from handler.database import db_rom_handler
|
||||
|
||||
if not self.igdb_id:
|
||||
return []
|
||||
|
||||
with db_rom_handler.session.begin() as session:
|
||||
return session.scalars(
|
||||
db_rom_handler.get_roms(platform_id=self.platform_id).filter(
|
||||
Rom.id != self.id,
|
||||
Rom.igdb_id == self.igdb_id,
|
||||
select(Rom).where(
|
||||
and_(
|
||||
Rom.platform_id == self.platform_id,
|
||||
Rom.id != self.id,
|
||||
or_(
|
||||
and_(Rom.igdb_id == self.igdb_id, Rom.igdb_id != None), # noqa
|
||||
and_(Rom.moby_id == self.moby_id, Rom.moby_id != None), # noqa
|
||||
),
|
||||
)
|
||||
)
|
||||
).all()
|
||||
|
||||
|
||||
@@ -34,45 +34,55 @@ error_log() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_for_gunicorn_socket () {
|
||||
info_log "waiting for gunicorn socket file..."
|
||||
while [ ! -S /tmp/gunicorn.sock ]; do
|
||||
sleep 1
|
||||
done
|
||||
info_log "gunicorn socket file found"
|
||||
}
|
||||
|
||||
# function that runs or main process and creates a corresponding PID file,
|
||||
start_bin_gunicorn() {
|
||||
# cleanup potentially leftover socket
|
||||
rm /tmp/gunicorn.sock -f
|
||||
# Commands to start our main application and store its PID to check for crashes
|
||||
info_log "starting gunicorn"
|
||||
gunicorn \
|
||||
--access-logfile - \
|
||||
--error-logfile - \
|
||||
--worker-class uvicorn.workers.UvicornWorker \
|
||||
--bind=0.0.0.0:5000 \
|
||||
--bind=unix:/tmp/gunicorn.sock \
|
||||
--pid=/tmp/gunicorn.pid \
|
||||
--workers "${GUNICORN_WORKERS:=2}" \
|
||||
main:app &
|
||||
start_bin_gunicorn () {
|
||||
# cleanup potentially leftover socket
|
||||
rm /tmp/gunicorn.sock -f
|
||||
|
||||
# commands to start our main application and store its PID to check for crashes
|
||||
info_log "starting gunicorn"
|
||||
gunicorn \
|
||||
--access-logfile - \
|
||||
--error-logfile - \
|
||||
--worker-class uvicorn.workers.UvicornWorker \
|
||||
--bind=0.0.0.0:5000 \
|
||||
--bind=unix:/tmp/gunicorn.sock \
|
||||
--pid=/tmp/gunicorn.pid \
|
||||
--workers ${GUNICORN_WORKERS:=2} \
|
||||
main:app &
|
||||
}
|
||||
|
||||
# Commands to start nginx (handling PID creation internally)
|
||||
start_bin_nginx() {
|
||||
info_log "starting nginx"
|
||||
if [[ ${EUID} -ne 0 ]]; then
|
||||
nginx
|
||||
else
|
||||
# if container runs as root, drop permissions
|
||||
nginx -g 'user romm;'
|
||||
fi
|
||||
start_bin_nginx () {
|
||||
wait_for_gunicorn_socket
|
||||
|
||||
info_log "starting nginx"
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
nginx
|
||||
else
|
||||
# if container runs as root, drop permissions
|
||||
nginx -g 'user romm;'
|
||||
fi
|
||||
}
|
||||
|
||||
start_bin_redis-server() {
|
||||
info_log "starting redis-server"
|
||||
|
||||
# Check if /usr/local/etc/redis/redis.conf exists and use it if so
|
||||
if [[ -f /usr/local/etc/redis/redis.conf ]]; then
|
||||
redis-server /usr/local/etc/redis/redis.conf &
|
||||
else
|
||||
redis-server --dir /redis-data &
|
||||
fi
|
||||
REDIS_PID=$!
|
||||
echo "${REDIS_PID}" >/tmp/redis-server.pid
|
||||
start_bin_redis-server () {
|
||||
info_log "starting redis-server"
|
||||
# Check if /usr/local/etc/redis/redis.conf exists and use it if so
|
||||
if [ -f /usr/local/etc/redis/redis.conf ]; then
|
||||
redis-server /usr/local/etc/redis/redis.conf &
|
||||
else
|
||||
redis-server --dir /redis-data &
|
||||
fi
|
||||
REDIS_PID=$!
|
||||
echo $REDIS_PID > /tmp/redis-server.pid
|
||||
}
|
||||
|
||||
# function that runs our independent python scripts and creates corresponding PID files,
|
||||
@@ -113,6 +123,9 @@ cd /backend || { error_log "/backend directory doesn't seem to exist"; }
|
||||
|
||||
info_log "Starting up, please wait..."
|
||||
|
||||
# clear any leftover PID files
|
||||
rm /tmp/*.pid -f
|
||||
|
||||
# function definition done, lets start our main loop
|
||||
while true; do
|
||||
# check for died processes every 5 seconds
|
||||
@@ -137,17 +150,17 @@ while true; do
|
||||
debug_log "database schema already upgraded during current container lifecycle"
|
||||
fi
|
||||
|
||||
# Start nginx if we dont have a corresponding PID file
|
||||
watchdog_process_pid bin nginx
|
||||
# Start gunicorn if we dont have a corresponding PID file
|
||||
watchdog_process_pid bin gunicorn
|
||||
|
||||
# Start nginx if we dont have a corresponding PID file
|
||||
watchdog_process_pid bin nginx
|
||||
|
||||
# Start uvicorn if we dont have a corresponding PID file
|
||||
watchdog_process_pid bin gunicorn
|
||||
|
||||
# only start the watcher.py if we actually want to use the rescan on fs change feature
|
||||
if [[ ${ENABLE_RESCAN_ON_FILESYSTEM_CHANGE} == "true" ]]; then
|
||||
# Start watcher if we dont have a corresponding PID file
|
||||
watchdog_process_pid python watcher
|
||||
fi
|
||||
# only start the watcher.py if we actually want to use the rescan on fs change feature
|
||||
if [[ ${ENABLE_RESCAN_ON_FILESYSTEM_CHANGE} == "true" ]]; then
|
||||
# Start watcher if we dont have a corresponding PID file
|
||||
watchdog_process_pid python watcher
|
||||
fi
|
||||
|
||||
# Start background worker processes
|
||||
debug_log "Starting worker and scheduler"
|
||||
|
||||
131
examples/config.es-de.example.yml
Normal file
131
examples/config.es-de.example.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
# This config file is compatible with the ES-DE Emulation Frontend
|
||||
# Rename this file to `config.yml`, copy it to a `config` folder, and mount that folder as per the docker-compose.example.yml
|
||||
# Only uncomment the lines you want to use/modify, or add new ones where needed
|
||||
|
||||
exclude:
|
||||
roms:
|
||||
single_file:
|
||||
extensions:
|
||||
- 'xml'
|
||||
- 'txt'
|
||||
names:
|
||||
- 'info.txt'
|
||||
- 'metadata.txt'
|
||||
- 'systeminfo.txt'
|
||||
- 'psy.ggjud.iso'
|
||||
- 'psy.ggjud.nfo'
|
||||
multi_file:
|
||||
names:
|
||||
- 'roms'
|
||||
- 'pfx'
|
||||
- 'mlc01'
|
||||
- '.Trash*'
|
||||
|
||||
system:
|
||||
platforms:
|
||||
3do: '3do' # 3DO Interactive Multiplayer
|
||||
n3ds: '3ds' # Nintendo 3DS
|
||||
amstradcpc: 'acpc' # Amstrad CPC
|
||||
amiga: 'amiga' # Amiga
|
||||
amigacd32: 'amiga-cd32' # Amiga CD32
|
||||
android: 'android' # Android
|
||||
apple2gs: 'apple2gs' # Apple IIGD
|
||||
apple2: 'appleii' # Apple II
|
||||
arcade: 'arcade' # Arcade
|
||||
arcadia: 'arcadia-2001' # Arcadia 2001
|
||||
arduboy: 'arduboy' # Arduboy
|
||||
astrocde: 'astrocade' # Bally Astrocade
|
||||
apfm1000: 'apf' # APF-M1000/Imagination Machine
|
||||
atarijaguarcd: 'atari-jaguar-cd' # Atari Jaguar CD
|
||||
atarist: 'atari-st' # Atari ST/STE
|
||||
atari2600: 'atari2600' # Atari 2600
|
||||
atari5200: 'atari5200' # Atari 5200
|
||||
atari7800: 'atari7800' # Atari 7800
|
||||
atari800: 'atari8bit' # Atari 8-bit
|
||||
c16: 'c16' # Commodore 16
|
||||
c64: 'c64' # Commodore C64/128/MAX
|
||||
pv1000: 'casio-pv-1000' # Casio PV-1000
|
||||
colecovision: 'colecovision' # ColecoVision
|
||||
cdtv: 'commodore-cdtv' # CDTV
|
||||
crvision: 'creativision' # CreatiVision
|
||||
dreamcast: 'dc' # Dreamcast
|
||||
dos: 'dos' # DOS
|
||||
dragon32: 'dragon-32-slash-64' # Dragon 32/64
|
||||
channelf: 'fairchild-channel-f' # Channel F
|
||||
famicom: 'famicom' # Family Computer
|
||||
fds: 'fds' # Family Computer Disk System
|
||||
fmtowns: 'fm-towns' # FM Towns
|
||||
gameandwatch: 'g-and-w' # Game & Watch
|
||||
gamecom: 'game-dot-com' # Game.Com
|
||||
gb: 'gb' # Game Boy
|
||||
gba: 'gba' # Game Boy Advance
|
||||
gbc: 'gbc' # Game Boy Color
|
||||
megadrive: 'genesis-slash-megadrive' # Genesis/Mega Drive
|
||||
lcdgames: 'handheld-electronic-lcd' # Handheld Electronic LCD
|
||||
intellivision: 'intellivision' # Intellivision
|
||||
j2me: 'j2me' # J2ME
|
||||
atarijaguar: 'jaguar' # Atari Jaguar
|
||||
atarilynx: 'lynx' # Atari Lynx
|
||||
macintosh: 'mac' # Mac
|
||||
megaduck: 'mega-duck-slash-cougar-boy' # Mega Duck/Cougar Boy
|
||||
msx: 'msx' # MSX
|
||||
msx2: 'msx2' # MSX2
|
||||
n64: 'n64' # Nintendo 64
|
||||
nds: 'nds' # Nintendo DS
|
||||
neogeocd: 'neo-geo-cd' # Neo Geo CD
|
||||
ngp: 'neo-geo-pocket' # Neo Geo Pocket
|
||||
ngpc: 'neo-geo-pocket-color' # Neo Geo Pocket Color
|
||||
neogeo: 'neogeoaes' # Neo Geo
|
||||
nes: 'nes' # Nintendo Entertainment System
|
||||
gc: 'ngc' # GameCube
|
||||
n64dd: 'nintendo-64dd' # Nintendo 64DD
|
||||
odyssey2: 'odyssey-2-slash-videopac-g7000' # Odyssey 2/Videopac G7000
|
||||
oric: 'oric' # Oric
|
||||
palm: 'palm-os' # Palm OS
|
||||
pc88: 'pc-8800-series' # PC-8800 Series
|
||||
pc98: 'pc-9800-series' # PC-9800 Series
|
||||
pcfx: 'pc-fx' # PC-FX
|
||||
pokemini: 'pokemon-mini' # Pokémon mini
|
||||
psx: 'ps' # PlayStation
|
||||
ps2: 'ps2' # PlayStation 2
|
||||
ps3: 'ps3' # PlayStation 3
|
||||
ps4: 'ps4--1' # PlayStation 4
|
||||
psp: 'psp' # PlayStation Portable
|
||||
samcoupe: 'sam-coupe' # SAM Coupé
|
||||
satellaview: 'satellaview' # Satellaview
|
||||
sega32x: 'sega-32x' # SEGA 32X
|
||||
mastersystem: 'sega-master-system' # SEGA Master System
|
||||
sega32x: 'sega32' # Sega 32X
|
||||
megacd: 'segacd' # SEGA CD
|
||||
sfc: 'sfam' # Super Famicom
|
||||
sg-1000: 'sg1000' # SG-1000
|
||||
x68000: 'sharp-x68000' # Sharp X68000
|
||||
snes: 'snes' # Super Nintendo Entertainment System
|
||||
spectravideo: 'spectravideo' # Spectravideo
|
||||
supergrafx: 'supergrafx' # PC Engine SuperGrafx
|
||||
supervision: 'supervision' # Supervision
|
||||
switch: 'switch' # Nintendo Switch
|
||||
symbian: 'symbian' # Symbian
|
||||
ti99: 'ti-99' # Texas Instruments TI-99
|
||||
trs-80: 'trs-80' # TRS-80
|
||||
tg-cd: 'turbografx-16-slash-pc-engine-cd' # TurboGrafx CD
|
||||
tg16: 'turbografx16--1' # TurboGrafx-16
|
||||
vectrex: 'vectrex' # Vectrex
|
||||
vic20: 'vic-20' # Commodore VIC-20
|
||||
videopac: 'videopac-g7400' # Videopac+ G7400
|
||||
virtualboy: 'virtualboy' # Virtual Boy
|
||||
vsmile: 'vsmile' # V.Smile
|
||||
wii: 'wii' # Wii
|
||||
wiiu: 'wiiu' # Wii U
|
||||
pc: 'win' # PC (Microsoft Windows)
|
||||
wonderswan: 'wonderswan' # WonderSwan
|
||||
wonderswancolor: 'wonderswan-color' # WonderSwan Color
|
||||
x1: 'x1' # Sharp X1
|
||||
xbox: 'xbox' # Xbox
|
||||
xbox360: 'xbox360' # Xbox 360
|
||||
zmachine: 'z-machine' # Z-machine
|
||||
zx81: 'zx80' # ZX80
|
||||
zxspectrum: 'zxs' # ZX Spectrum
|
||||
naomi: 'arcade'
|
||||
naomi2: 'arcade'
|
||||
naomigd: 'arcade'
|
||||
@@ -1,51 +1,56 @@
|
||||
# This is a generic example of a configuration file
|
||||
# Rename this file to `config.yml`, copy it to a `config` folder, and mount that folder as per the docker-compose.example.yml
|
||||
# Only uncomment the lines you want to use/modify, or add new ones where needed
|
||||
|
||||
exclude:
|
||||
# Exclude platforms to be scanned
|
||||
platforms:
|
||||
- "romm"
|
||||
# - 'romm'
|
||||
|
||||
# Exclude roms or parts of roms to be scanned
|
||||
roms:
|
||||
## Single file games section.
|
||||
# Single file games section.
|
||||
# Will not apply to files that are in sub-folders (multi-disc roms, games with updates, DLC, patches, etc.)
|
||||
single_file:
|
||||
# Exclude all files with certain extensions to be scanned
|
||||
extensions:
|
||||
- "xml"
|
||||
# - 'xml'
|
||||
# Exclude matched file names to be scanned
|
||||
names:
|
||||
- "info.txt"
|
||||
- "._*" # Supports unix filename pattern matching
|
||||
- "*.nfo" # Can also exclude files by extension
|
||||
# - 'info.txt'
|
||||
# - '._*' # Supports unix filename pattern matching
|
||||
# - '*.nfo' # Can also exclude files by extension
|
||||
|
||||
## Multi files games section
|
||||
# Multi files games section
|
||||
# Will apply to files that are in sub-folders (multi-disc roms, games with updates, DLC, patches, etc.)
|
||||
multi_file:
|
||||
# Exclude matched 'folder' names to be scanned (RomM identifies folders as multi file games)
|
||||
names:
|
||||
- "my_multi_file_game"
|
||||
- "DLC"
|
||||
# - 'my_multi_file_game'
|
||||
# - 'DLC'
|
||||
# Exclude files within sub-folders.
|
||||
parts:
|
||||
# Exclude matched file names to be scanned from multi file roms
|
||||
# Keep in mind that RomM doesn't scan folders inside multi files games,
|
||||
# so there is no need to exclude folders from inside of multi files games.
|
||||
names:
|
||||
- "data.xml"
|
||||
- "._*" # Supports unix filename pattern matching
|
||||
# - 'data.xml'
|
||||
# - '._*' # Supports unix filename pattern matching
|
||||
# Exclude all files with certain extensions to be scanned from multi file roms
|
||||
extensions:
|
||||
- "txt"
|
||||
# - 'txt'
|
||||
|
||||
system:
|
||||
# Asociate different platform names to your current file system platform names
|
||||
# [your custom platform folder name]: [RomM platform name]
|
||||
platforms:
|
||||
# [your custom platform folder name]: [RomM platform name]
|
||||
gc: "ngc" # In this example if you have a 'gc' folder, RomM will treat it like the 'ngc' folder
|
||||
psx: "ps"
|
||||
# gc: 'ngc' # In this example if you have a 'gc' folder, RomM will treat it like the 'ngc' folder
|
||||
# psx: 'ps' # In this example if you have a 'psx' folder, RomM will treat it like the 'ps' folder
|
||||
|
||||
# Asociate one platform to it's main version
|
||||
versions:
|
||||
naomi: "arcade"
|
||||
# naomi: 'arcade'
|
||||
|
||||
# The folder name where your roms are located
|
||||
filesystem:
|
||||
# The folder name where your roms are located
|
||||
roms_folder: "roms" # For example if your folder structure is /home/user/library/roms_folder
|
||||
# roms_folder: 'roms' # For example if your folder structure is /home/user/library/roms_folder
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RomM</title>
|
||||
</head>
|
||||
|
||||
@@ -7,7 +7,7 @@ import socket from "@/services/socket";
|
||||
import storeConfig from "@/stores/config";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import storeHeartbeat from "@/stores/heartbeat";
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import storeScanning from "@/stores/scanning";
|
||||
@@ -42,7 +42,7 @@ socket.on(
|
||||
}
|
||||
);
|
||||
|
||||
socket.on("scan:scanning_rom", (rom: Rom) => {
|
||||
socket.on("scan:scanning_rom", (rom: SimpleRom) => {
|
||||
scanningStore.set(true);
|
||||
if (romsStore.platformID === rom.platform_id) {
|
||||
romsStore.add([rom]);
|
||||
|
||||
2
frontend/src/__generated__/index.ts
generated
2
frontend/src/__generated__/index.ts
generated
@@ -14,7 +14,7 @@ export type { Body_token_token_post } from "./models/Body_token_token_post";
|
||||
export type { Body_update_rom_roms__id__put } from "./models/Body_update_rom_roms__id__put";
|
||||
export type { Body_update_user_users__id__put } from "./models/Body_update_user_users__id__put";
|
||||
export type { ConfigResponse } from "./models/ConfigResponse";
|
||||
export type { CursorPage_RomSchema_ } from "./models/CursorPage_RomSchema_";
|
||||
export type { DetailedRomSchema } from "./models/DetailedRomSchema";
|
||||
export type { FirmwareSchema } from "./models/FirmwareSchema";
|
||||
export type { HeartbeatResponse } from "./models/HeartbeatResponse";
|
||||
export type { HTTPValidationError } from "./models/HTTPValidationError";
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/* generated using openapi-typescript-codegen -- do no edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { RomSchema } from "./RomSchema";
|
||||
|
||||
export type CursorPage_RomSchema_ = {
|
||||
items: Array<RomSchema>;
|
||||
/**
|
||||
* Total items
|
||||
*/
|
||||
total?: number | null;
|
||||
/**
|
||||
* Cursor to refetch the current page
|
||||
*/
|
||||
current_page?: string | null;
|
||||
/**
|
||||
* Cursor to refetch the current page starting from the last item
|
||||
*/
|
||||
current_page_backwards?: string | null;
|
||||
/**
|
||||
* Cursor for the previous page
|
||||
*/
|
||||
previous_page?: string | null;
|
||||
/**
|
||||
* Cursor for the next page
|
||||
*/
|
||||
next_page?: string | null;
|
||||
};
|
||||
57
frontend/src/__generated__/models/DetailedRomSchema.ts
generated
Normal file
57
frontend/src/__generated__/models/DetailedRomSchema.ts
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
/* generated using openapi-typescript-codegen -- do no edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { RomIGDBMetadata } from "./RomIGDBMetadata";
|
||||
import type { RomMobyMetadata } from "./RomMobyMetadata";
|
||||
import type { RomNoteSchema } from "./RomNoteSchema";
|
||||
import type { RomSchema } from "./RomSchema";
|
||||
import type { SaveSchema } from "./SaveSchema";
|
||||
import type { ScreenshotSchema } from "./ScreenshotSchema";
|
||||
import type { StateSchema } from "./StateSchema";
|
||||
|
||||
export type DetailedRomSchema = {
|
||||
id: number;
|
||||
igdb_id: number | null;
|
||||
sgdb_id: number | null;
|
||||
moby_id: number | null;
|
||||
platform_id: number;
|
||||
platform_slug: string;
|
||||
platform_name: string;
|
||||
file_name: string;
|
||||
file_name_no_tags: string;
|
||||
file_name_no_ext: string;
|
||||
file_extension: string;
|
||||
file_path: string;
|
||||
file_size_bytes: number;
|
||||
name: string | null;
|
||||
slug: string | null;
|
||||
summary: string | null;
|
||||
first_release_date: number | null;
|
||||
alternative_names: Array<string>;
|
||||
genres: Array<string>;
|
||||
franchises: Array<string>;
|
||||
collections: Array<string>;
|
||||
companies: Array<string>;
|
||||
game_modes: Array<string>;
|
||||
igdb_metadata: RomIGDBMetadata | null;
|
||||
moby_metadata: RomMobyMetadata | null;
|
||||
path_cover_s: string | null;
|
||||
path_cover_l: string | null;
|
||||
has_cover: boolean;
|
||||
url_cover: string | null;
|
||||
revision: string | null;
|
||||
regions: Array<string>;
|
||||
languages: Array<string>;
|
||||
tags: Array<string>;
|
||||
multi: boolean;
|
||||
files: Array<string>;
|
||||
full_path: string;
|
||||
merged_screenshots: Array<string>;
|
||||
sibling_roms?: Array<RomSchema>;
|
||||
user_saves?: Array<SaveSchema>;
|
||||
user_states?: Array<StateSchema>;
|
||||
user_screenshots?: Array<ScreenshotSchema>;
|
||||
user_notes?: Array<RomNoteSchema>;
|
||||
};
|
||||
@@ -9,11 +9,11 @@ export type PlatformSchema = {
|
||||
id: number;
|
||||
slug: string;
|
||||
fs_slug: string;
|
||||
name: string;
|
||||
rom_count: number;
|
||||
igdb_id?: number | null;
|
||||
sgdb_id?: number | null;
|
||||
moby_id?: number | null;
|
||||
name: string;
|
||||
logo_path?: string | null;
|
||||
rom_count: number;
|
||||
firmware?: Array<FirmwareSchema>;
|
||||
};
|
||||
|
||||
@@ -10,4 +10,5 @@ export type RomNoteSchema = {
|
||||
last_edited_at: string;
|
||||
raw_markdown: string;
|
||||
is_public: boolean;
|
||||
user__username: string;
|
||||
};
|
||||
|
||||
11
frontend/src/__generated__/models/RomSchema.ts
generated
11
frontend/src/__generated__/models/RomSchema.ts
generated
@@ -5,10 +5,6 @@
|
||||
|
||||
import type { RomIGDBMetadata } from "./RomIGDBMetadata";
|
||||
import type { RomMobyMetadata } from "./RomMobyMetadata";
|
||||
import type { RomNoteSchema } from "./RomNoteSchema";
|
||||
import type { SaveSchema } from "./SaveSchema";
|
||||
import type { ScreenshotSchema } from "./ScreenshotSchema";
|
||||
import type { StateSchema } from "./StateSchema";
|
||||
|
||||
export type RomSchema = {
|
||||
id: number;
|
||||
@@ -46,12 +42,5 @@ export type RomSchema = {
|
||||
tags: Array<string>;
|
||||
multi: boolean;
|
||||
files: Array<string>;
|
||||
url_screenshots: Array<string>;
|
||||
merged_screenshots: Array<string>;
|
||||
full_path: string;
|
||||
sibling_roms?: Array<RomSchema>;
|
||||
user_saves?: Array<SaveSchema>;
|
||||
user_states?: Array<StateSchema>;
|
||||
user_screenshots?: Array<ScreenshotSchema>;
|
||||
user_notes?: Array<RomNoteSchema>;
|
||||
};
|
||||
|
||||
@@ -11,5 +11,4 @@ export type SearchRomSchema = {
|
||||
summary: string;
|
||||
igdb_url_cover?: string;
|
||||
moby_url_cover?: string;
|
||||
url_screenshots: Array<string>;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,5 @@ import type { ScreenshotSchema } from "./ScreenshotSchema";
|
||||
export type UploadedScreenshotsResponse = {
|
||||
uploaded: number;
|
||||
screenshots: Array<ScreenshotSchema>;
|
||||
url_screenshots: Array<string>;
|
||||
merged_screenshots: Array<string>;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ const emitter = inject<Emitter<Events>>("emitter");
|
||||
<template>
|
||||
<v-btn @click="emitter?.emit('toggleDrawer', null)" rounded="0" icon>
|
||||
<v-avatar rounded="0">
|
||||
<v-img src="/assets/isotipo.svg" />
|
||||
<img src="/assets/isotipo.svg" />
|
||||
</v-avatar>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
@@ -19,7 +19,7 @@ onMounted(() => {
|
||||
romApi
|
||||
.getRecentRoms()
|
||||
.then(({ data: recentData }) => {
|
||||
romsStore.setRecentRoms(recentData.items);
|
||||
romsStore.setRecentRoms(recentData);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
@@ -3,20 +3,19 @@ import AdminMenu from "@/components/Game/AdminMenu/Base.vue";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import storeDownload from "@/stores/download";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import { getDownloadLink, platformSlugEJSCoreMap } from "@/utils";
|
||||
import { getDownloadLink, isEmulationSupported } from "@/utils";
|
||||
import type { Emitter } from "mitt";
|
||||
import { inject, ref } from "vue";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
const downloadStore = storeDownload();
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
const auth = storeAuth();
|
||||
const emulation = ref(false);
|
||||
const playInfoIcon = ref("mdi-play");
|
||||
const emulationSupported =
|
||||
props.rom.platform_slug.toLowerCase() in platformSlugEJSCoreMap;
|
||||
const emulationSupported = isEmulationSupported(props.rom.platform_slug);
|
||||
|
||||
function toggleEmulation() {
|
||||
emulation.value = !emulation.value;
|
||||
@@ -24,7 +23,7 @@ function toggleEmulation() {
|
||||
emitter?.emit("showEmulation", null);
|
||||
}
|
||||
|
||||
async function copyDownloadLink(rom: Rom) {
|
||||
async function copyDownloadLink(rom: DetailedRom) {
|
||||
const downloadLink =
|
||||
location.protocol +
|
||||
"//" +
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
import { useTheme } from "vuetify";
|
||||
const theme = useTheme();
|
||||
</script>
|
||||
@@ -41,23 +41,16 @@ const theme = useTheme();
|
||||
)}`
|
||||
: `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:lazy-src="
|
||||
`${expansion.cover_url}`
|
||||
? `https:${expansion.cover_url.replace(
|
||||
't_thumb',
|
||||
't_cover_big'
|
||||
)}`
|
||||
: `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
><v-chip
|
||||
>
|
||||
<v-chip
|
||||
class="px-2 position-absolute chip-type text-white translucent"
|
||||
density="compact"
|
||||
label
|
||||
>
|
||||
<span>expansion</span>
|
||||
</v-chip></v-img
|
||||
>
|
||||
</v-chip>
|
||||
</v-img>
|
||||
</v-card>
|
||||
</a>
|
||||
</v-col>
|
||||
@@ -94,12 +87,8 @@ const theme = useTheme();
|
||||
? `https:${dlc.cover_url.replace('t_thumb', 't_cover_big')}`
|
||||
: `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:lazy-src="
|
||||
`${dlc.cover_url}`
|
||||
? `https:${dlc.cover_url.replace('t_thumb', 't_cover_small')}`
|
||||
: `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
lazy
|
||||
><v-chip
|
||||
class="px-2 position-absolute chip-type text-white translucent"
|
||||
density="compact"
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import type { RomSchema } from "@/__generated__";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { useTheme } from "vuetify";
|
||||
const theme = useTheme();
|
||||
|
||||
const props = defineProps<{ rom: RomSchema }>();
|
||||
const imgSrc =
|
||||
!props.rom.igdb_id && !props.rom.moby_id && !props.rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: !props.rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${props.rom.path_cover_s}`;
|
||||
const imgSrcLazy =
|
||||
!props.rom.igdb_id && !props.rom.moby_id && !props.rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !props.rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${props.rom.path_cover_s}`;
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card rounded="0">
|
||||
<v-img :src="imgSrc" :lazy-src="imgSrcLazy" id="background-header" />
|
||||
<v-img
|
||||
:src="
|
||||
!rom.igdb_id && !rom.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
id="background-header"
|
||||
lazy
|
||||
>
|
||||
<template v-slot:error>
|
||||
<v-img
|
||||
:src="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
:aspect-ratio="3 / 4"
|
||||
></v-img>
|
||||
</template>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
<v-progress-circular
|
||||
:width="2"
|
||||
:size="40"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</v-img>
|
||||
</v-card>
|
||||
</template>
|
||||
<style scoped>
|
||||
|
||||
@@ -1,28 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import storeDownload from "@/stores/download";
|
||||
import { type SimpleRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ romId: number; src: string; lazySrc: string }>();
|
||||
defineProps<{ rom: SimpleRom }>();
|
||||
const downloadStore = storeDownload();
|
||||
import { useTheme } from "vuetify";
|
||||
const theme = useTheme();
|
||||
</script>
|
||||
<template>
|
||||
<v-card
|
||||
elevation="2"
|
||||
:loading="downloadStore.value.includes(romId) ? 'romm-accent-1' : false"
|
||||
:loading="downloadStore.value.includes(rom.id) ? 'romm-accent-1' : false"
|
||||
>
|
||||
<v-img
|
||||
:value="romId"
|
||||
:key="romId"
|
||||
:src="src"
|
||||
:lazy-src="lazySrc"
|
||||
:value="rom.id"
|
||||
:key="rom.id"
|
||||
:src="
|
||||
!rom.igdb_id && !rom.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
lazy
|
||||
>
|
||||
<slot name="editable"></slot>
|
||||
<template v-slot:error>
|
||||
<v-img
|
||||
:src="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
:aspect-ratio="3 / 4"
|
||||
></v-img>
|
||||
</template>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
<v-progress-circular
|
||||
color="romm-accent-1"
|
||||
:width="2"
|
||||
:size="20"
|
||||
:size="40"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
<template>
|
||||
<v-row no-gutters>
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
import { isNull } from "lodash";
|
||||
import type { FirmwareSchema, SaveSchema, StateSchema } from "@/__generated__";
|
||||
import rom from "@/services/api/rom";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import { formatBytes } from "@/utils";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { formatBytes, getSupportedCores } from "@/utils";
|
||||
import Player from "@/views/Play/Player.vue";
|
||||
import { ref } from "vue";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
|
||||
const props = defineProps<{ rom: Rom; platform: Platform }>();
|
||||
const props = defineProps<{ rom: DetailedRom; platform: Platform }>();
|
||||
const biosRef = ref<FirmwareSchema | null>(null);
|
||||
const saveRef = ref<SaveSchema | null>(null);
|
||||
const stateRef = ref<StateSchema | null>(null);
|
||||
const gameRunning = ref(false);
|
||||
|
||||
const supportedCores = getSupportedCores(props.platform.slug);
|
||||
const coreRef = ref<string | null>(supportedCores[0]);
|
||||
|
||||
const storedFSOP = localStorage.getItem("fullScreenOnPlay");
|
||||
const fullScreenOnPlay = ref(isNull(storedFSOP) ? true : storedFSOP === "true");
|
||||
|
||||
@@ -35,6 +38,22 @@ function onFullScreenChange() {
|
||||
<template>
|
||||
<v-row v-if="rom && !gameRunning" no-gutters class="align-center">
|
||||
<v-col cols="5" class="text-truncate mx-1">
|
||||
<v-select
|
||||
v-if="supportedCores.length > 1"
|
||||
density="compact"
|
||||
class="my-2"
|
||||
hide-details
|
||||
variant="outlined"
|
||||
clearable
|
||||
label="Core"
|
||||
v-model="coreRef"
|
||||
:items="
|
||||
supportedCores.map((c) => ({
|
||||
title: c,
|
||||
value: c,
|
||||
}))
|
||||
"
|
||||
/>
|
||||
<v-select
|
||||
density="compact"
|
||||
class="my-2"
|
||||
@@ -137,7 +156,13 @@ function onFullScreenChange() {
|
||||
|
||||
<v-row no-gutters>
|
||||
<v-col v-if="gameRunning" cols="12" rounded id="game-wrapper">
|
||||
<player :rom="props.rom" :state="stateRef" :save="saveRef" :bios="biosRef" />
|
||||
<player
|
||||
:rom="props.rom"
|
||||
:state="stateRef"
|
||||
:save="saveRef"
|
||||
:bios="biosRef"
|
||||
:core="coreRef"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
<template>
|
||||
<v-col class="pa-0" cols="4" sm="2" md="3" lg="3" v-for="game in rom.igdb_metadata?.expanded_games">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
<template>
|
||||
<v-row no-gutters>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { PlatformSchema } from "@/__generated__";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import FileInfo from "@/components/Details/Info/FileInfo.vue";
|
||||
import GameInfo from "@/components/Details/Info/GameInfo.vue";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom; platform: PlatformSchema }>();
|
||||
defineProps<{ rom: DetailedRom; platform: Platform }>();
|
||||
</script>
|
||||
<template>
|
||||
<file-info :rom="rom" :platform="platform" />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { PlatformSchema } from "@/__generated__";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import VersionSwitcher from "@/components/Details/VersionSwitcher.vue";
|
||||
import storeDownload from "@/stores/download";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { formatBytes } from "@/utils";
|
||||
|
||||
defineProps<{ rom: Rom; platform: PlatformSchema }>();
|
||||
defineProps<{ rom: DetailedRom; platform: Platform }>();
|
||||
const downloadStore = storeDownload();
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
const { xs } = useDisplay();
|
||||
const galleryFilter = storeGalleryFilter();
|
||||
</script>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
import { ref } from "vue";
|
||||
import { useTheme } from "vuetify";
|
||||
|
||||
import { type Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import romApi from "@/services/api/rom";
|
||||
import { MdEditor, MdPreview } from "md-editor-v3";
|
||||
import "md-editor-v3/lib/style.css";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
const auth = storeAuth();
|
||||
const theme = useTheme();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { ref } from "vue";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
const combined = ref([
|
||||
...(props.rom.igdb_metadata?.remakes ?? []),
|
||||
...(props.rom.igdb_metadata?.remasters ?? []),
|
||||
@@ -39,12 +39,8 @@ const theme = useTheme();
|
||||
? `https:${game.cover_url.replace('t_thumb', 't_cover_big')}`
|
||||
: `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:lazy-src="
|
||||
`${game.cover_url}`
|
||||
? `https:${game.cover_url.replace('t_thumb', 't_cover_small')}`
|
||||
: `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
lazy
|
||||
><v-chip
|
||||
class="px-2 position-absolute chip-type text-white translucent"
|
||||
density="compact"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
<template>
|
||||
<v-row no-gutters>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
<template>
|
||||
<v-row class="mb-3" no-gutters>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { SaveSchema } from "@/__generated__";
|
||||
import saveApi from "@/services/api/save";
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type DetailedRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import { formatBytes } from "@/utils";
|
||||
import type { Emitter } from "mitt";
|
||||
import { inject, ref } from "vue";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
const savesToUpload = ref<File[]>([]);
|
||||
const selectedSaves = ref<SaveSchema[]>([]);
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
const { xs } = useDisplay();
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: DetailedRom }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -5,11 +5,11 @@ import type { Emitter } from "mitt";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import { formatBytes } from "@/utils";
|
||||
import stateApi from "@/services/api/state";
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type DetailedRom } from "@/stores/roms";
|
||||
|
||||
import type { StateSchema } from "@/__generated__";
|
||||
|
||||
const props = defineProps<{ rom: Rom }>();
|
||||
const props = defineProps<{ rom: DetailedRom }>();
|
||||
const statesToUpload = ref<File[]>([]);
|
||||
const selectedStates = ref<StateSchema[]>([]);
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
import { identity } from "lodash";
|
||||
import PlatformIcon from "@/components/Platform/PlatformIcon.vue";
|
||||
import { regionToEmoji, languageToEmoji } from "@/utils";
|
||||
import type { RomSchema, PlatformSchema } from "@/__generated__/";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
defineProps<{ rom: RomSchema; platform: PlatformSchema }>();
|
||||
defineProps<{ rom: DetailedRom; platform: Platform }>();
|
||||
const { smAndDown } = useDisplay();
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type { PlatformSchema } from "@/__generated__";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { languageToEmoji, regionToEmoji } from "@/utils";
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const props = defineProps<{ rom: Rom; platform: PlatformSchema }>();
|
||||
const props = defineProps<{ rom: DetailedRom; platform: Platform }>();
|
||||
const router = useRouter();
|
||||
const version = ref(props.rom.id);
|
||||
|
||||
function formatItem(rom: Rom) {
|
||||
function formatItem(rom: DetailedRom) {
|
||||
const langs = rom.languages.map((l) => languageToEmoji(l)).join(" ");
|
||||
const regions = rom.regions.map((r) => regionToEmoji(r)).join(" ");
|
||||
const tags = rom.tags.map((t) => `(${t})`).join(" ");
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useDisplay } from "vuetify";
|
||||
import type { Emitter } from "mitt";
|
||||
import type { Events } from "@/types/emitter";
|
||||
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type DetailedRom } from "@/stores/roms";
|
||||
import saveApi from "@/services/api/save";
|
||||
import stateApi from "@/services/api/state";
|
||||
import type { SaveSchema, StateSchema } from "@/__generated__";
|
||||
@@ -13,7 +13,7 @@ const { xs, mdAndDown, lgAndUp } = useDisplay();
|
||||
const romsStore = storeRoms();
|
||||
const show = ref(false);
|
||||
const assetType = ref<"user_saves" | "user_states">("user_saves");
|
||||
const romRef = ref<Rom | null>(null);
|
||||
const romRef = ref<DetailedRom | null>(null);
|
||||
const assets = ref<(SaveSchema | StateSchema)[]>([]);
|
||||
const deleteFromFs = ref(false);
|
||||
|
||||
|
||||
@@ -21,15 +21,11 @@ emitter?.on("showLoadingDialog", (args) => {
|
||||
width="auto"
|
||||
persistent
|
||||
>
|
||||
<v-card outlined color="transparent">
|
||||
<v-card-text class="pa-4">
|
||||
<v-progress-circular
|
||||
:width="3"
|
||||
:size="70"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-progress-circular
|
||||
:width="3"
|
||||
:size="70"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
@@ -179,25 +179,7 @@ function closeDialog() {
|
||||
<v-col cols="12" md="4" lg="3">
|
||||
<cover
|
||||
:class="{ 'mx-16': smAndDown, 'ml-2': md, 'my-4': smAndDown }"
|
||||
:romId="rom.id"
|
||||
:src="
|
||||
imagePreviewUrl
|
||||
? imagePreviewUrl
|
||||
: !rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
:lazy-src="
|
||||
imagePreviewUrl
|
||||
? imagePreviewUrl
|
||||
: !rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_s}`
|
||||
"
|
||||
:rom="rom"
|
||||
>
|
||||
<template v-slot:editable>
|
||||
<v-chip-group class="position-absolute edit-cover pa-0">
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { SearchRomSchema } from "@/__generated__";
|
||||
import SelectSourceDialog from "@/components/Dialog/Rom/MatchRom/SelectSource.vue";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeHeartbeat from "@/stores/heartbeat";
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Emitter } from "mitt";
|
||||
import { inject, onBeforeUnmount, ref } from "vue";
|
||||
@@ -11,7 +11,7 @@ import { useDisplay, useTheme } from "vuetify";
|
||||
|
||||
const { xs, mdAndDown, lgAndUp } = useDisplay();
|
||||
const show = ref(false);
|
||||
const rom = ref<Rom | null>(null);
|
||||
const rom = ref<SimpleRom | null>(null);
|
||||
const romsStore = storeRoms();
|
||||
const renameAsIGDB = ref(false);
|
||||
const searching = ref(false);
|
||||
@@ -358,13 +358,6 @@ onBeforeUnmount(() => {
|
||||
? matchedRom.igdb_url_cover
|
||||
: matchedRom.moby_url_cover
|
||||
"
|
||||
:lazy-src="
|
||||
!matchedRom.igdb_url_cover && !matchedRom.moby_url_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: matchedRom.igdb_url_cover
|
||||
? matchedRom.igdb_url_cover
|
||||
: matchedRom.moby_url_cover
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import type { SearchRomSchema } from "@/__generated__";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Emitter } from "mitt";
|
||||
@@ -59,7 +58,7 @@ function closeDialog() {
|
||||
<v-row class="justify-center" no-gutters>
|
||||
<v-col
|
||||
class="pa-2"
|
||||
:class="{'cover':!xs, 'cover-xs': xs}"
|
||||
:class="{ cover: !xs, 'cover-xs': xs }"
|
||||
v-for="source in sources"
|
||||
>
|
||||
<v-hover v-slot="{ isHovering, props }">
|
||||
@@ -76,12 +75,8 @@ function closeDialog() {
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: source.url_cover
|
||||
"
|
||||
:lazy-src="
|
||||
!source.url_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: source.url_cover
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
lazy
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import type { RomSchema } from "@/__generated__";
|
||||
import PlatformIcon from "@/components/Platform/PlatformIcon.vue";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
@@ -10,6 +9,7 @@ import type { Emitter } from "mitt";
|
||||
import { inject, onBeforeUnmount, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useDisplay, useTheme } from "vuetify";
|
||||
import { type SimpleRom } from "@/stores/roms";
|
||||
|
||||
const theme = useTheme();
|
||||
const { xs, mdAndDown, lgAndUp } = useDisplay();
|
||||
@@ -47,8 +47,8 @@ async function searchRoms() {
|
||||
inputElement?.blur();
|
||||
searching.value = true;
|
||||
searchedRoms.value = (
|
||||
await romApi.getRoms({ searchTerm: searchValue.value, size: 250 })
|
||||
).data.items.sort((a, b) => {
|
||||
await romApi.getRoms({ searchTerm: searchValue.value })
|
||||
).data.sort((a, b) => {
|
||||
return a.platform_name.localeCompare(b.platform_name);
|
||||
});
|
||||
platforms.value = [
|
||||
@@ -73,7 +73,7 @@ async function filterRoms() {
|
||||
}
|
||||
}
|
||||
|
||||
function romDetails(rom: RomSchema) {
|
||||
function romDetails(rom: SimpleRom) {
|
||||
router.push({
|
||||
name: "rom",
|
||||
params: { rom: rom.id },
|
||||
@@ -249,28 +249,27 @@ onBeforeUnmount(() => {
|
||||
<v-img
|
||||
v-bind="props"
|
||||
:src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
!rom.igdb_id && !rom.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
:lazy-src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_s}`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
lazy
|
||||
>
|
||||
<template v-slot:error>
|
||||
<v-img
|
||||
:src="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
:aspect-ratio="3 / 4"
|
||||
></v-img>
|
||||
</template>
|
||||
<template v-slot:placeholder>
|
||||
<div
|
||||
class="d-flex align-center justify-center fill-height"
|
||||
>
|
||||
<v-progress-circular
|
||||
color="romm-accent-1"
|
||||
:width="2"
|
||||
:size="40"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -29,10 +29,10 @@ onBeforeMount(async () => {
|
||||
"https://api.github.com/repos/rommapp/romm/releases/latest"
|
||||
);
|
||||
const json = await response.json();
|
||||
GITHUB_VERSION.value = json.name;
|
||||
GITHUB_VERSION.value = json.tag_name;
|
||||
latestVersionDismissed.value =
|
||||
VERSION === "development" ||
|
||||
json.name === localStorage.getItem("dismissedVersion");
|
||||
json.tag_name === localStorage.getItem("dismissedVersion");
|
||||
});
|
||||
|
||||
async function logout() {
|
||||
@@ -108,7 +108,7 @@ async function logout() {
|
||||
<v-col class="py-1">
|
||||
<span
|
||||
>New version available
|
||||
<span class="text-romm-accent-1">{{ GITHUB_VERSION }}</span></span
|
||||
<span class="text-romm-accent-1">v{{ GITHUB_VERSION }}</span></span
|
||||
>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -119,7 +119,7 @@ async function logout() {
|
||||
><span class="ml-4"
|
||||
><a
|
||||
target="_blank"
|
||||
:href="`https://github.com/rommapp/romm/releases/tag/v${GITHUB_VERSION}`"
|
||||
:href="`https://github.com/rommapp/romm/releases/tag/${GITHUB_VERSION}`"
|
||||
>See what's new!</a
|
||||
></span
|
||||
>
|
||||
|
||||
@@ -4,7 +4,7 @@ import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Emitter } from "mitt";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { inject, ref } from "vue";
|
||||
import { inject, ref, nextTick } from "vue";
|
||||
|
||||
// Props
|
||||
const showFilterBar = ref(false);
|
||||
@@ -27,50 +27,50 @@ const {
|
||||
<div v-if="showFilterBar">
|
||||
<v-row no-gutters class="pa-1">
|
||||
<filter-unmatched-btn />
|
||||
<v-select
|
||||
<v-autocomplete
|
||||
hide-details
|
||||
clearable
|
||||
label="Genre"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
class="ma-1"
|
||||
@update:model-value="emitter?.emit('filter', null);"
|
||||
@update:model-value="nextTick(() => emitter?.emit('filter', null))"
|
||||
v-model="selectedGenre"
|
||||
:items="galleryFilterStore.filterGenres"
|
||||
></v-select>
|
||||
<v-select
|
||||
></v-autocomplete>
|
||||
<v-autocomplete
|
||||
hide-details
|
||||
clearable
|
||||
label="Franchise"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
class="ma-1"
|
||||
@update:model-value="emitter?.emit('filter', null)"
|
||||
@update:model-value="nextTick(() => emitter?.emit('filter', null))"
|
||||
v-model="selectedFranchise"
|
||||
:items="galleryFilterStore.filterFranchises"
|
||||
></v-select>
|
||||
<v-select
|
||||
></v-autocomplete>
|
||||
<v-autocomplete
|
||||
hide-details
|
||||
clearable
|
||||
label="Collection"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
class="ma-1"
|
||||
@update:model-value="emitter?.emit('filter', null)"
|
||||
@update:model-value="nextTick(() => emitter?.emit('filter', null))"
|
||||
v-model="selectedCollection"
|
||||
:items="galleryFilterStore.filterCollections"
|
||||
></v-select>
|
||||
<v-select
|
||||
></v-autocomplete>
|
||||
<v-autocomplete
|
||||
hide-details
|
||||
clearable
|
||||
label="Company"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
class="ma-1"
|
||||
@update:model-value="emitter?.emit('filter', null)"
|
||||
@update:model-value="nextTick(() => emitter?.emit('filter', null))"
|
||||
v-model="selectedCompany"
|
||||
:items="galleryFilterStore.filterCompanies"
|
||||
></v-select>
|
||||
></v-autocomplete>
|
||||
</v-row>
|
||||
<v-divider
|
||||
:thickness="2"
|
||||
|
||||
@@ -3,7 +3,6 @@ import socket from "@/services/socket";
|
||||
import storeHeartbeat from "@/stores/heartbeat";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import storeScanning from "@/stores/scanning";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
// Props
|
||||
const scanningStore = storeScanning();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import { inject } from "vue";
|
||||
import type { Emitter } from "mitt";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import storeHeartbeat from "@/stores/heartbeat";
|
||||
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: SimpleRom }>();
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
const heartbeat = storeHeartbeat();
|
||||
</script>
|
||||
|
||||
@@ -3,11 +3,11 @@ import romApi from "@/services/api/rom";
|
||||
import storeDownload from "@/stores/download";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import AdminMenu from "@/components/Game/AdminMenu/Base.vue";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import { platformSlugEJSCoreMap } from "@/utils";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { isEmulationSupported } from "@/utils";
|
||||
|
||||
// Props
|
||||
defineProps<{ rom: Rom }>();
|
||||
defineProps<{ rom: SimpleRom }>();
|
||||
const auth = storeAuth();
|
||||
const downloadStore = storeDownload();
|
||||
</script>
|
||||
@@ -25,7 +25,7 @@ const downloadStore = storeDownload();
|
||||
variant="text"
|
||||
/>
|
||||
<v-btn
|
||||
v-if="rom.platform_slug.toLowerCase() in platformSlugEJSCoreMap"
|
||||
v-if="isEmulationSupported(rom.platform_slug)"
|
||||
class="action-bar-btn"
|
||||
:href="`/play/${rom.id}`"
|
||||
icon="mdi-play"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import storeRoms, { type Rom } from "@/stores/roms.js";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms.js";
|
||||
import ActionBar from "@/components/Game/Card/ActionBar.vue";
|
||||
import Cover from "@/components/Game/Card/Cover.vue";
|
||||
|
||||
// Props
|
||||
const props = defineProps<{
|
||||
rom: Rom;
|
||||
rom: SimpleRom;
|
||||
index: number;
|
||||
selected: boolean;
|
||||
showSelector: boolean;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import LazyImage from "@/components/LazyImage.vue";
|
||||
import storeDownload from "@/stores/download";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import storeRoms, { type Rom } from "@/stores/roms";
|
||||
import storeRoms, { type SimpleRom } from "@/stores/roms";
|
||||
import { languageToEmoji, regionToEmoji } from "@/utils";
|
||||
import { identity, isNull } from "lodash";
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import { useTheme } from "vuetify";
|
||||
|
||||
// Props
|
||||
defineProps<{
|
||||
rom: Rom;
|
||||
rom: SimpleRom;
|
||||
isHoveringTop: boolean;
|
||||
showSelector: boolean;
|
||||
selected: boolean;
|
||||
@@ -57,6 +58,18 @@ function onTouchStart(event: TouchEvent) {
|
||||
function onTouchEnd() {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", onScroll);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("scroll", onScroll);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -86,74 +99,80 @@ function onTouchEnd() {
|
||||
:value="rom.id"
|
||||
:key="rom.id"
|
||||
v-bind="props"
|
||||
:placeholder="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
:src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
!rom.igdb_id && !rom.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
:lazy-src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
!rom.igdb_id && !rom.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_s}`
|
||||
"
|
||||
:aspect-ratio="3 / 4"
|
||||
>
|
||||
<div v-bind="props" style="position: absolute; top: 0; width: 100%">
|
||||
<v-expand-transition>
|
||||
<div
|
||||
v-if="isHovering || !rom.has_cover"
|
||||
class="translucent text-caption"
|
||||
:class="{
|
||||
'text-truncate': galleryViewStore.current == 0 && !isHovering,
|
||||
}"
|
||||
>
|
||||
<v-list-item>{{ rom.name }}</v-list-item>
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
<v-row no-gutters class="text-white px-1">
|
||||
<v-chip
|
||||
v-if="rom.regions.filter(identity).length > 0 && showRegions"
|
||||
:title="`Regions: ${rom.regions.join(', ')}`"
|
||||
class="translucent mr-1 mt-1 px-1"
|
||||
:class="{ 'emoji-collection': rom.regions.length > 3 }"
|
||||
density="compact"
|
||||
>
|
||||
<span class="emoji" v-for="region in rom.regions.slice(0, 3)">
|
||||
{{ regionToEmoji(region) }}
|
||||
</span>
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="rom.languages.filter(identity).length > 0 && showLanguages"
|
||||
:title="`Languages: ${rom.languages.join(', ')}`"
|
||||
class="translucent mr-1 mt-1 px-1"
|
||||
:class="{ 'emoji-collection': rom.languages.length > 3 }"
|
||||
density="compact"
|
||||
>
|
||||
<span class="emoji" v-for="language in rom.languages.slice(0, 3)">
|
||||
{{ languageToEmoji(language) }}
|
||||
</span>
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="rom.siblings && rom.siblings.length > 0 && showSiblings"
|
||||
:title="`${rom.siblings.length + 1} versions`"
|
||||
class="translucent mr-1 mt-1"
|
||||
density="compact"
|
||||
>
|
||||
+{{ rom.siblings.length }}
|
||||
</v-chip>
|
||||
</v-row>
|
||||
</div>
|
||||
<template v-slot:error>
|
||||
<v-img
|
||||
:src="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
:aspect-ratio="3 / 4"
|
||||
></v-img>
|
||||
</template>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
<v-progress-circular
|
||||
color="romm-accent-1"
|
||||
:width="2"
|
||||
:size="40"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<v-expand-transition>
|
||||
<div
|
||||
v-if="isHovering || !rom.has_cover"
|
||||
class="translucent text-caption"
|
||||
:class="{
|
||||
'text-truncate': galleryViewStore.current == 0 && !isHovering,
|
||||
}"
|
||||
>
|
||||
<v-list-item>{{ rom.name }}</v-list-item>
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
<v-row no-gutters class="text-white px-1">
|
||||
<v-chip
|
||||
v-if="rom.regions.filter(identity).length > 0 && showRegions"
|
||||
:title="`Regions: ${rom.regions.join(', ')}`"
|
||||
class="translucent mr-1 mt-1 px-1"
|
||||
:class="{ 'emoji-collection': rom.regions.length > 3 }"
|
||||
density="compact"
|
||||
>
|
||||
<span class="emoji" v-for="region in rom.regions.slice(0, 3)">
|
||||
{{ regionToEmoji(region) }}
|
||||
</span>
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="rom.languages.filter(identity).length > 0 && showLanguages"
|
||||
:title="`Languages: ${rom.languages.join(', ')}`"
|
||||
class="translucent mr-1 mt-1 px-1"
|
||||
:class="{ 'emoji-collection': rom.languages.length > 3 }"
|
||||
density="compact"
|
||||
>
|
||||
<span class="emoji" v-for="language in rom.languages.slice(0, 3)">
|
||||
{{ languageToEmoji(language) }}
|
||||
</span>
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="rom.siblings && rom.siblings.length > 0 && showSiblings"
|
||||
:title="`${rom.siblings.length + 1} versions`"
|
||||
class="translucent mr-1 mt-1"
|
||||
density="compact"
|
||||
>
|
||||
+{{ rom.siblings.length }}
|
||||
</v-chip>
|
||||
</v-row>
|
||||
</v-img>
|
||||
</v-hover>
|
||||
</router-link>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref, inject, onMounted, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import AdminMenu from "@/components/Game/AdminMenu/Base.vue";
|
||||
@@ -7,10 +7,12 @@ import romApi from "@/services/api/rom";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import storeDownload from "@/stores/download";
|
||||
import storeRoms from "@/stores/roms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Emitter } from "mitt";
|
||||
import {
|
||||
formatBytes,
|
||||
languageToEmoji,
|
||||
platformSlugEJSCoreMap,
|
||||
isEmulationSupported,
|
||||
regionToEmoji,
|
||||
} from "@/utils";
|
||||
import { useTheme } from "vuetify";
|
||||
@@ -62,21 +64,39 @@ const HEADERS = [
|
||||
{ title: "", align: "end", key: "actions", sortable: false },
|
||||
] as const;
|
||||
|
||||
const PER_PAGE_OPTIONS = [
|
||||
{ value: -1, title: "$vuetify.dataFooter.itemsPerPageAll" },
|
||||
] as const;
|
||||
const PER_PAGE_OPTIONS = [10, 25, 50, 100];
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
emitter?.on("updateDataTablePages", updateDataTablePages);
|
||||
|
||||
// Props
|
||||
const router = useRouter();
|
||||
const downloadStore = storeDownload();
|
||||
const romsStore = storeRoms();
|
||||
const auth = storeAuth();
|
||||
const romsPerPage = ref(-1);
|
||||
const page = ref(1);
|
||||
const storedRomsPerPage = parseInt(localStorage.getItem("romsPerPage") ?? "");
|
||||
const romsPerPage = ref(isNaN(storedRomsPerPage) ? 25 : storedRomsPerPage);
|
||||
const pageCount = ref(0);
|
||||
|
||||
// Functions
|
||||
function rowClick(_: Event, row: any) {
|
||||
router.push({ name: "rom", params: { rom: row.item.id } });
|
||||
}
|
||||
|
||||
function updateDataTablePages() {
|
||||
pageCount.value = Math.ceil(
|
||||
romsStore.filteredRoms.length / romsPerPage.value
|
||||
);
|
||||
}
|
||||
|
||||
watch(romsPerPage, async () => {
|
||||
localStorage.setItem("romsPerPage", romsPerPage.value.toString());
|
||||
updateDataTablePages();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
updateDataTablePages();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -91,6 +111,7 @@ function rowClick(_: Event, row: any) {
|
||||
@click:row="rowClick"
|
||||
show-select
|
||||
v-model="romsStore._selectedIDs"
|
||||
v-model:page="page"
|
||||
>
|
||||
<template v-slot:item.path_cover_s="{ item }">
|
||||
<v-avatar :rounded="0">
|
||||
@@ -102,23 +123,44 @@ function rowClick(_: Event, row: any) {
|
||||
/>
|
||||
<v-img
|
||||
:src="
|
||||
!item.igdb_id && !item.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !item.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${item.path_cover_s}`
|
||||
!item.igdb_id && !item.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: `/assets/romm/resources/${item.path_cover_l}`
|
||||
"
|
||||
:lazy-src="
|
||||
!item.igdb_id && !item.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !item.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
!item.igdb_id && !item.moby_id
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: `/assets/romm/resources/${item.path_cover_s}`
|
||||
"
|
||||
min-height="150"
|
||||
/>
|
||||
>
|
||||
<template v-slot:error>
|
||||
<v-img
|
||||
:src="`/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`"
|
||||
></v-img>
|
||||
</template>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
<v-progress-circular
|
||||
:width="2"
|
||||
:size="20"
|
||||
color="romm-accent-1"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</v-img>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<template v-slot:item.name="{ item }">
|
||||
<span>
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:item.file_name="{ item }">
|
||||
<span>
|
||||
{{ item.file_name }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:item.file_size_bytes="{ item }">
|
||||
<span>
|
||||
{{ formatBytes(item.file_size_bytes) }}
|
||||
@@ -147,7 +189,7 @@ function rowClick(_: Event, row: any) {
|
||||
<v-icon>mdi-download</v-icon>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="item.platform_slug.toLowerCase() in platformSlugEJSCoreMap"
|
||||
v-if="isEmulationSupported(item.platform_slug)"
|
||||
size="small"
|
||||
variant="text"
|
||||
:href="`/play/${item.id}`"
|
||||
@@ -171,5 +213,31 @@ function rowClick(_: Event, row: any) {
|
||||
<admin-menu :rom="item" />
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<template v-slot:bottom>
|
||||
<v-divider class="border-opacity-25" />
|
||||
<v-row no-gutters class="pt-2 align-center">
|
||||
<v-col cols="11" class="px-6">
|
||||
<v-pagination
|
||||
rounded="0"
|
||||
:show-first-last-page="true"
|
||||
active-color="romm-accent-1"
|
||||
v-model="page"
|
||||
:length="pageCount"
|
||||
></v-pagination>
|
||||
</v-col>
|
||||
<v-col cols="5" sm="2" xl="1">
|
||||
<v-select
|
||||
class="pa-2"
|
||||
label="Roms per page"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
:items="PER_PAGE_OPTIONS"
|
||||
v-model="romsPerPage"
|
||||
hide-details
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</template>
|
||||
|
||||
98
frontend/src/components/LazyImage.vue
Normal file
98
frontend/src/components/LazyImage.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
reactive,
|
||||
computed,
|
||||
ref,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
useAttrs,
|
||||
} from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
src: string;
|
||||
placeholder: string;
|
||||
srcset?: string;
|
||||
intersectionOptions?: IntersectionObserverInit;
|
||||
usePicture?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["load", "error", "intersect"]);
|
||||
const attrs = useAttrs();
|
||||
|
||||
const root = ref<HTMLPictureElement | HTMLImageElement | null>(null);
|
||||
const state = reactive<{
|
||||
observer: IntersectionObserver | null;
|
||||
intersected: boolean;
|
||||
loaded: boolean;
|
||||
}>({
|
||||
observer: null,
|
||||
intersected: false,
|
||||
loaded: false,
|
||||
});
|
||||
|
||||
const srcImage = computed(() =>
|
||||
state.intersected && props.src ? props.src : props.placeholder
|
||||
);
|
||||
const srcsetImage = computed(() =>
|
||||
state.intersected && props.srcset ? props.srcset : ""
|
||||
);
|
||||
|
||||
const load = () => {
|
||||
if (root.value && root.value.getAttribute("src") !== props.placeholder) {
|
||||
state.loaded = true;
|
||||
emit("load", root.value);
|
||||
}
|
||||
};
|
||||
const error = () => emit("error", root.value);
|
||||
|
||||
// Hooks
|
||||
onMounted(() => {
|
||||
if ("IntersectionObserver" in window) {
|
||||
state.observer = new IntersectionObserver((entries) => {
|
||||
const image = entries[0];
|
||||
if (image.isIntersecting) {
|
||||
state.intersected = true;
|
||||
state.observer?.disconnect();
|
||||
emit("intersect");
|
||||
}
|
||||
}, props.intersectionOptions ?? {});
|
||||
|
||||
if (root.value) state.observer.observe(root.value);
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if ("IntersectionObserver" in window && state.observer) {
|
||||
state.observer.disconnect();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<picture v-if="usePicture" ref="root" @load="load">
|
||||
<slot v-if="state.intersected"></slot>
|
||||
<img
|
||||
v-else
|
||||
:src="srcImage"
|
||||
:srcSet="srcsetImage"
|
||||
v-bind="attrs"
|
||||
:class="[attrs.class, 'v-responsive v-img v-lazy-image', { 'v-lazy-image-loaded': state.loaded }]"
|
||||
@load="load"
|
||||
@error="error"
|
||||
>
|
||||
<slot />
|
||||
</img>
|
||||
</picture>
|
||||
<img
|
||||
v-else
|
||||
ref="root"
|
||||
:src="srcImage"
|
||||
:srcSet="srcsetImage"
|
||||
v-bind="attrs"
|
||||
:class="[attrs.class, 'v-responsive v-img v-lazy-image', { 'v-lazy-image-loaded': state.loaded }]"
|
||||
@load="load"
|
||||
@error="error"
|
||||
>
|
||||
<slot />
|
||||
</img>
|
||||
</template>
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { MessageResponse, PlatformSchema } from "@/__generated__";
|
||||
import type { MessageResponse } from "@/__generated__";
|
||||
import api from "@/services/api/index";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
|
||||
export const platformApi = api;
|
||||
|
||||
@@ -7,28 +8,28 @@ async function uploadPlatform({
|
||||
fsSlug,
|
||||
}: {
|
||||
fsSlug: string;
|
||||
}): Promise<{ data: PlatformSchema }> {
|
||||
}): Promise<{ data: Platform }> {
|
||||
return api.post("/platforms", { fs_slug: fsSlug });
|
||||
}
|
||||
|
||||
async function getPlatforms(): Promise<{ data: PlatformSchema[] }> {
|
||||
async function getPlatforms(): Promise<{ data: Platform[] }> {
|
||||
return api.get("/platforms");
|
||||
}
|
||||
|
||||
async function getPlatform(
|
||||
id: number | undefined,
|
||||
): Promise<{ data: PlatformSchema }> {
|
||||
): Promise<{ data: Platform }> {
|
||||
return api.get(`/platforms/${id}`);
|
||||
}
|
||||
|
||||
async function getSupportedPlatforms(): Promise<{ data: PlatformSchema[] }> {
|
||||
async function getSupportedPlatforms(): Promise<{ data: Platform[] }> {
|
||||
return api.get("/platforms/supported");
|
||||
}
|
||||
|
||||
async function updatePlatform({
|
||||
platform,
|
||||
}: {
|
||||
platform: PlatformSchema;
|
||||
platform: Platform;
|
||||
}): Promise<{ data: MessageResponse }> {
|
||||
return api.delete(`/platforms/${platform.id}`);
|
||||
}
|
||||
@@ -36,7 +37,7 @@ async function updatePlatform({
|
||||
async function deletePlatform({
|
||||
platform,
|
||||
}: {
|
||||
platform: PlatformSchema;
|
||||
platform: Platform;
|
||||
}): Promise<{ data: MessageResponse }> {
|
||||
return api.delete(`/platforms/${platform.id}`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type {
|
||||
AddRomsResponse,
|
||||
CursorPage_RomSchema_,
|
||||
MessageResponse,
|
||||
RomSchema,
|
||||
SearchRomSchema,
|
||||
@@ -8,7 +7,7 @@ import type {
|
||||
import api from "@/services/api/index";
|
||||
import socket from "@/services/socket";
|
||||
import storeDownload from "@/stores/download";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { SimpleRom, DetailedRom } from "@/stores/roms";
|
||||
import { getDownloadLink } from "@/utils";
|
||||
|
||||
export const romApi = api;
|
||||
@@ -33,24 +32,18 @@ async function uploadRoms({
|
||||
|
||||
async function getRoms({
|
||||
platformId = null,
|
||||
size = 60,
|
||||
cursor = "",
|
||||
searchTerm = "",
|
||||
orderBy = "name",
|
||||
orderDir = "asc",
|
||||
}: {
|
||||
platformId?: number | null;
|
||||
size?: number | null;
|
||||
cursor?: string | null;
|
||||
searchTerm?: string | null;
|
||||
orderBy?: string | null;
|
||||
orderDir?: string | null;
|
||||
}): Promise<{ data: CursorPage_RomSchema_ }> {
|
||||
}): Promise<{ data: SimpleRom[] }> {
|
||||
return api.get(`/roms`, {
|
||||
params: {
|
||||
platform_id: platformId,
|
||||
size: size,
|
||||
cursor: cursor,
|
||||
search_term: searchTerm,
|
||||
order_by: orderBy,
|
||||
order_dir: orderDir,
|
||||
@@ -58,13 +51,13 @@ async function getRoms({
|
||||
});
|
||||
}
|
||||
|
||||
async function getRecentRoms(): Promise<{ data: CursorPage_RomSchema_ }> {
|
||||
async function getRecentRoms(): Promise<{ data: SimpleRom[] }> {
|
||||
return api.get("/roms", {
|
||||
params: { size: 15, order_by: "id", order_dir: "desc" },
|
||||
params: { order_by: "id", order_dir: "desc", limit: 15 },
|
||||
});
|
||||
}
|
||||
|
||||
async function getRom({ romId }: { romId: number }): Promise<{ data: Rom }> {
|
||||
async function getRom({ romId }: { romId: number }): Promise<{ data: DetailedRom }> {
|
||||
return api.get(`/roms/${romId}`);
|
||||
}
|
||||
|
||||
@@ -105,7 +98,7 @@ async function downloadRom({
|
||||
rom,
|
||||
files = [],
|
||||
}: {
|
||||
rom: Rom;
|
||||
rom: SimpleRom;
|
||||
files?: string[];
|
||||
}) {
|
||||
const a = document.createElement("a");
|
||||
@@ -124,7 +117,7 @@ async function downloadRom({
|
||||
}
|
||||
}
|
||||
|
||||
export type UpdateRom = Rom & {
|
||||
export type UpdateRom = SimpleRom & {
|
||||
artwork?: File;
|
||||
};
|
||||
|
||||
@@ -136,7 +129,7 @@ async function updateRom({
|
||||
rom: UpdateRom;
|
||||
renameAsIGDB?: boolean;
|
||||
removeCover?: boolean;
|
||||
}): Promise<{ data: RomSchema }> {
|
||||
}): Promise<{ data: DetailedRom }> {
|
||||
var formData = new FormData();
|
||||
if (rom.igdb_id) formData.append("igdb_id", rom.igdb_id.toString());
|
||||
if (rom.moby_id) formData.append("moby_id", rom.moby_id.toString());
|
||||
@@ -155,7 +148,7 @@ async function deleteRoms({
|
||||
roms,
|
||||
deleteFromFs = false,
|
||||
}: {
|
||||
roms: Rom[];
|
||||
roms: SimpleRom[];
|
||||
deleteFromFs: boolean;
|
||||
}): Promise<{ data: MessageResponse }> {
|
||||
return api.post("/roms/delete", {
|
||||
@@ -172,7 +165,7 @@ async function updateRomNote({
|
||||
romId: number;
|
||||
rawMarkdown: string;
|
||||
isPublic: boolean;
|
||||
}): Promise<{ data: RomSchema }> {
|
||||
}): Promise<{ data: DetailedRom }> {
|
||||
return api.put(`/roms/${romId}/note`, {
|
||||
raw_markdown: rawMarkdown,
|
||||
is_public: isPublic,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SaveSchema, UploadedSavesResponse } from "@/__generated__";
|
||||
import api from "@/services/api/index";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
export const saveApi = api;
|
||||
|
||||
@@ -9,7 +9,7 @@ async function uploadSaves({
|
||||
saves,
|
||||
emulator,
|
||||
}: {
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
saves: File[];
|
||||
emulator?: string;
|
||||
}): Promise<{ data: UploadedSavesResponse }> {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type {
|
||||
UploadedScreenshotsResponse,
|
||||
} from "@/__generated__";
|
||||
import api from "@/services/api/index";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
export const screenshotApi = api;
|
||||
|
||||
@@ -11,7 +11,7 @@ async function uploadScreenshots({
|
||||
rom,
|
||||
screenshots,
|
||||
}: {
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
screenshots: File[];
|
||||
}): Promise<{ data: UploadedScreenshotsResponse }> {
|
||||
let formData = new FormData();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { StateSchema, UploadedStatesResponse } from "@/__generated__";
|
||||
import api from "@/services/api/index";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
export const stateApi = api;
|
||||
|
||||
@@ -9,7 +9,7 @@ async function uploadStates({
|
||||
states,
|
||||
emulator,
|
||||
}: {
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
states: File[];
|
||||
emulator?: string;
|
||||
}): Promise<{ data: UploadedStatesResponse }> {
|
||||
|
||||
@@ -48,10 +48,11 @@ export default defineStore("galleryFilter", {
|
||||
this.filterUnmatched = !this.filterUnmatched;
|
||||
},
|
||||
isFiltered() {
|
||||
return (
|
||||
return Boolean(
|
||||
normalizeString(this.filterSearch).trim() != "" ||
|
||||
this.filterUnmatched ||
|
||||
this.selectedGenre ||
|
||||
this.filterFranchises ||
|
||||
this.selectedFranchise ||
|
||||
this.selectedCollection ||
|
||||
this.selectedCompany
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from "pinia";
|
||||
import type { PlatformSchema } from "@/__generated__";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
export type Platform = PlatformSchema;
|
||||
|
||||
@@ -15,11 +16,18 @@ export default defineStore("platforms", {
|
||||
filledPlatforms: ({ value }) => value.filter((p) => p.rom_count > 0),
|
||||
},
|
||||
actions: {
|
||||
_reorder() {
|
||||
this.value = this.value.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
this.value = uniqBy(this.value, "id");
|
||||
},
|
||||
set(platforms: Platform[]) {
|
||||
this.value = platforms;
|
||||
},
|
||||
add(platform: Platform) {
|
||||
this.value.push(platform);
|
||||
this._reorder();
|
||||
},
|
||||
exists(platform: Platform) {
|
||||
return this.value.filter((p) => p.fs_slug == platform.fs_slug).length > 0;
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
import type { PlatformSchema, RomSchema } from "@/__generated__/";
|
||||
import { groupBy, isNull, uniqBy } from "lodash";
|
||||
import type { RomSchema, DetailedRomSchema } from "@/__generated__/";
|
||||
import { groupBy, uniqBy } from "lodash";
|
||||
import { nanoid } from "nanoid";
|
||||
import { defineStore, type Store } from "pinia";
|
||||
import { defineStore } from "pinia";
|
||||
import storeGalleryFilter from "./galleryFilter";
|
||||
import type { ExtractPiniaStoreType } from "@/types";
|
||||
|
||||
type GalleryFilterStore = ExtractPiniaStoreType<typeof storeGalleryFilter>;
|
||||
|
||||
export type Rom = RomSchema & {
|
||||
export type SimpleRom = RomSchema & {
|
||||
siblings?: RomSchema[]; // Added by the frontend
|
||||
};
|
||||
|
||||
export type DetailedRom = DetailedRomSchema;
|
||||
|
||||
export default defineStore("roms", {
|
||||
state: () => ({
|
||||
_platformID: 0,
|
||||
_all: [] as Rom[],
|
||||
_grouped: [] as Rom[],
|
||||
_all: [] as SimpleRom[],
|
||||
_grouped: [] as SimpleRom[],
|
||||
_filteredIDs: [] as number[],
|
||||
_searchIDs: [] as number[],
|
||||
_selectedIDs: [] as number[],
|
||||
recentRoms: [] as Rom[],
|
||||
recentRoms: [] as SimpleRom[],
|
||||
lastSelectedIndex: -1,
|
||||
cursor: "" as string | null,
|
||||
searchCursor: "" as string | null,
|
||||
selecting: false,
|
||||
itemsPerBatch: 72,
|
||||
}),
|
||||
|
||||
getters: {
|
||||
@@ -62,7 +63,7 @@ export default defineStore("roms", {
|
||||
),
|
||||
)
|
||||
.map((games) => ({
|
||||
...(games.shift() as Rom),
|
||||
...(games.shift() as SimpleRom),
|
||||
siblings: games,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
@@ -72,23 +73,23 @@ export default defineStore("roms", {
|
||||
setPlatformID(platformID: number) {
|
||||
this._platformID = platformID;
|
||||
},
|
||||
setRecentRoms(roms: Rom[]) {
|
||||
setRecentRoms(roms: SimpleRom[]) {
|
||||
this.recentRoms = roms;
|
||||
},
|
||||
// All roms
|
||||
set(roms: Rom[]) {
|
||||
set(roms: SimpleRom[]) {
|
||||
this._all = roms;
|
||||
this._reorder();
|
||||
},
|
||||
add(roms: Rom[]) {
|
||||
add(roms: SimpleRom[]) {
|
||||
this._all = this._all.concat(roms);
|
||||
this._reorder();
|
||||
},
|
||||
update(rom: Rom) {
|
||||
update(rom: SimpleRom) {
|
||||
this._all = this._all.map((value) => (value.id === rom.id ? rom : value));
|
||||
this._reorder();
|
||||
},
|
||||
remove(roms: Rom[]) {
|
||||
remove(roms: SimpleRom[]) {
|
||||
this._all = this._all.filter((value) => {
|
||||
return !roms.find((rom) => {
|
||||
return rom.id === value.id;
|
||||
@@ -114,7 +115,7 @@ export default defineStore("roms", {
|
||||
this.lastSelectedIndex = -1;
|
||||
},
|
||||
// Filter roms by gallery filter store state
|
||||
setFiltered(roms: Rom[], galleryFilter: GalleryFilterStore) {
|
||||
setFiltered(roms: SimpleRom[], galleryFilter: GalleryFilterStore) {
|
||||
this._filteredIDs = roms.map((rom) => rom.id);
|
||||
if (galleryFilter.filterUnmatched) this.filterUnmatched();
|
||||
if (galleryFilter.selectedGenre) {
|
||||
@@ -164,17 +165,17 @@ export default defineStore("roms", {
|
||||
.map((rom) => rom.id);
|
||||
},
|
||||
// Search roms
|
||||
setSearch(roms: Rom[]) {
|
||||
setSearch(roms: SimpleRom[]) {
|
||||
this._searchIDs = roms.map((rom) => rom.id);
|
||||
},
|
||||
// Selected roms
|
||||
setSelection(roms: Rom[]) {
|
||||
setSelection(roms: SimpleRom[]) {
|
||||
this._selectedIDs = roms.map((rom) => rom.id);
|
||||
},
|
||||
addToSelection(rom: Rom) {
|
||||
addToSelection(rom: SimpleRom) {
|
||||
this._selectedIDs.push(rom.id);
|
||||
},
|
||||
removeFromSelection(rom: Rom) {
|
||||
removeFromSelection(rom: SimpleRom) {
|
||||
this._selectedIDs = this._selectedIDs.filter((id) => {
|
||||
return id !== rom.id;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from "pinia";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
|
||||
export default defineStore("scanning", {
|
||||
state: () => ({
|
||||
@@ -8,7 +8,7 @@ export default defineStore("scanning", {
|
||||
name: string;
|
||||
slug: string;
|
||||
id: number;
|
||||
roms: Rom[];
|
||||
roms: SimpleRom[];
|
||||
}[],
|
||||
scanStats: {
|
||||
scanned_platforms: 0,
|
||||
|
||||
15
frontend/src/types/emitter.d.ts
vendored
15
frontend/src/types/emitter.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import type { SaveSchema, SearchRomSchema, StateSchema } from "@/__generated__";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import type { User } from "@/stores/users";
|
||||
|
||||
export type UserItem = User & {
|
||||
@@ -17,12 +17,12 @@ export type SnackbarStatus = {
|
||||
|
||||
export type Events = {
|
||||
showDeletePlatformDialog: Platform;
|
||||
showMatchRomDialog: Rom;
|
||||
showMatchRomDialog: SimpleRom;
|
||||
showSelectSourceDialog: SearchRomSchema;
|
||||
showSearchRomDialog: null;
|
||||
showEditRomDialog: Rom;
|
||||
showEditRomDialog: SimpleRom;
|
||||
showCopyDownloadLinkDialog: string;
|
||||
showDeleteRomDialog: Rom[];
|
||||
showDeleteRomDialog: SimpleRom[];
|
||||
showUploadRomDialog: Platform | null;
|
||||
showFirmwareDialog: Platform;
|
||||
showAddPlatformDialog: null;
|
||||
@@ -47,11 +47,11 @@ export type Events = {
|
||||
showEditUserDialog: User;
|
||||
showDeleteUserDialog: User;
|
||||
showDeleteSavesDialog: {
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
saves: SaveSchema[];
|
||||
};
|
||||
showDeleteStatesDialog: {
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
states: StateSchema[];
|
||||
};
|
||||
showEmulation: null;
|
||||
@@ -68,6 +68,7 @@ export type Events = {
|
||||
filter: null;
|
||||
filterBarShow: null;
|
||||
filterBarReset: null;
|
||||
updateDataTablePages: null;
|
||||
sortBarShow: null;
|
||||
romUpdated: Rom;
|
||||
romUpdated: DetailedRom;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import cronstrue from "cronstrue";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
|
||||
export const views: Record<
|
||||
number,
|
||||
@@ -48,14 +48,6 @@ export const views: Record<
|
||||
|
||||
export const defaultAvatarPath = "/assets/default/user.png";
|
||||
|
||||
export function toTop() {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
|
||||
export function normalizeString(s: string) {
|
||||
return s
|
||||
.toLowerCase()
|
||||
@@ -75,19 +67,16 @@ export function getDownloadLink({
|
||||
rom,
|
||||
files = [],
|
||||
}: {
|
||||
rom: Rom;
|
||||
rom: SimpleRom;
|
||||
files?: string[];
|
||||
}) {
|
||||
// Force download of all multirom-parts when no part is selected
|
||||
if (files.length == 0) {
|
||||
files = rom.files;
|
||||
const queryParams = new URLSearchParams();
|
||||
if (files.length) {
|
||||
files.forEach((file) => queryParams.append("files", file));
|
||||
}
|
||||
|
||||
var filesParams = "";
|
||||
files.forEach((file) => {
|
||||
filesParams += `files=${file}&`;
|
||||
});
|
||||
return `/api/roms/${rom.id}/content/${rom.file_name}?${filesParams}`;
|
||||
return `/api/roms/${rom.id}/content/${
|
||||
rom.file_name
|
||||
}?${queryParams.toString()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,68 +266,89 @@ export function languageToEmoji(language: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export const platformSlugEJSCoreMap = {
|
||||
"3do": "opera",
|
||||
amiga: "puae",
|
||||
arcade: "mame2003_plus",
|
||||
atari2600: "stella2014",
|
||||
"atari-2600-plus": "stella2014",
|
||||
atari5200: "a5200",
|
||||
atari7800: "prosystem",
|
||||
c64: "vice_x64",
|
||||
"commodore-64c": "vice_x64",
|
||||
colecovision: "gearcoleco",
|
||||
jaguar: "virtualjaguar",
|
||||
lynx: "handy",
|
||||
"atari-lynx-mkii": "handy",
|
||||
"neo-geo-pocket": "mednafen_ngp",
|
||||
"neo-geo-pocket-color": "mednafen_ngp",
|
||||
nes: "fceumm",
|
||||
famicom: "fceumm",
|
||||
fds: "fceumm",
|
||||
"game-televisison": "fceumm",
|
||||
"new-style-nes": "fceumm",
|
||||
n64: "mupen64plus_next",
|
||||
"ique-player": "mupen64plus_next",
|
||||
nds: "melonds",
|
||||
"nintendo-ds-lite": "melonds",
|
||||
"nintendo-dsi": "melonds",
|
||||
"nintendo-dsi-xl": "melonds",
|
||||
gb: "gambatte",
|
||||
"game-boy-pocket": "gambatte",
|
||||
"game-boy-light": "gambatte",
|
||||
gba: "mgba",
|
||||
"game-boy-adavance-sp": "mgba",
|
||||
"game-boy-micro": "mgba",
|
||||
gbc: "gambatte",
|
||||
"pc-fx": "mednafen_pcfx",
|
||||
ps: "pcsx_rearmed",
|
||||
psp: "ppsspp",
|
||||
segacd: "genesis_plus_gx",
|
||||
// sega32: "picodrive", // Broken: https://github.com/EmulatorJS/EmulatorJS/issues/579
|
||||
gamegear: "genesis_plus_gx",
|
||||
sms: "genesis_plus_gx",
|
||||
"sega-mark-iii": "genesis_plus_gx",
|
||||
"sega-game-box-9": "genesis_plus_gx",
|
||||
"sega-master-system-ii": "genesis_plus_gx",
|
||||
"master-system-super-compact": "genesis_plus_gx",
|
||||
"master-system-girl": "genesis_plus_gx",
|
||||
"genesis-slash-megadrive": "genesis_plus_gx",
|
||||
"sega-mega-drive-2-slash-genesis": "genesis_plus_gx",
|
||||
"sega-mega-jet": "genesis_plus_gx",
|
||||
"mega-pc": "genesis_plus_gx",
|
||||
"tera-drive": "genesis_plus_gx",
|
||||
"sega-nomad": "genesis_plus_gx",
|
||||
saturn: "yabause",
|
||||
snes: "snes9x",
|
||||
sfam: "snes9x",
|
||||
"super-nintendo-original-european-version": "snes9x",
|
||||
"super-famicom-shvc-001": "snes9x",
|
||||
"super-famicom-jr-model-shvc-101": "snes9x",
|
||||
"new-style-super-nes-model-sns-101": "snes9x",
|
||||
"turbografx16--1": "mednafen_pce",
|
||||
virtualboy: "beetle_vb",
|
||||
wonderswan: "mednafen_wswan",
|
||||
swancrystal: "mednafen_wswan",
|
||||
"wonderswan-color": "mednafen_wswan",
|
||||
const _EJS_CORES_MAP = {
|
||||
"3do": ["opera"],
|
||||
amiga: ["puae"],
|
||||
arcade: [
|
||||
"mame2003",
|
||||
"mame2003_plus",
|
||||
"fbneo",
|
||||
"fbalpha2012_cps1",
|
||||
"fbalpha2012_cps2",
|
||||
],
|
||||
atari2600: ["stella2014"],
|
||||
"atari-2600-plus": ["stella2014"],
|
||||
atari5200: ["a5200"],
|
||||
atari7800: ["prosystem"],
|
||||
"c-plus-4": ["vice_xplus4"],
|
||||
c64: ["vice_x64sc", "vice_x64"],
|
||||
cpet: ["vice_xpet"],
|
||||
"commodore-64c": ["vice_x64sc", "vice_x64"],
|
||||
c128: ["vice_x128"],
|
||||
"commmodore-128": ["vice_x128"],
|
||||
colecovision: ["gearcoleco"],
|
||||
jaguar: ["virtualjaguar"],
|
||||
lynx: ["handy"],
|
||||
"atari-lynx-mkii": ["handy"],
|
||||
"neo-geo-pocket": ["mednafen_ngp"],
|
||||
"neo-geo-pocket-color": ["mednafen_ngp"],
|
||||
nes: ["fceumm", "nestopia"],
|
||||
famicom: ["fceumm", "nestopia"],
|
||||
fds: ["fceumm", "nestopia"],
|
||||
"game-televisison": ["fceumm"],
|
||||
"new-style-nes": ["fceumm"],
|
||||
n64: ["mupen64plus_next"],
|
||||
"ique-player": ["mupen64plus_next"],
|
||||
nds: ["melonds", "desmume2015"],
|
||||
"nintendo-ds-lite": ["melonds", "desmume2015"],
|
||||
"nintendo-dsi": ["melonds", "desmume2015"],
|
||||
"nintendo-dsi-xl": ["melonds", "desmume2015"],
|
||||
gb: ["gambatte", "mgba"],
|
||||
"game-boy-pocket": ["gambatte", "mgba"],
|
||||
"game-boy-light": ["gambatte", "mgba"],
|
||||
gba: ["mgba"],
|
||||
"game-boy-adavance-sp": ["mgba"],
|
||||
"game-boy-micro": ["mgba"],
|
||||
gbc: ["gambatte", "mgba"],
|
||||
"pc-fx": ["mednafen_pcfx"],
|
||||
ps: ["pcsx_rearmed", "mednafen_psx"],
|
||||
psp: ["ppsspp"],
|
||||
segacd: ["genesis_plus_gx", "picodrive"],
|
||||
// sega32: ["picodrive"], // Broken: https://github.com/EmulatorJS/EmulatorJS/issues/579
|
||||
gamegear: ["genesis_plus_gx"],
|
||||
sms: ["genesis_plus_gx"],
|
||||
"sega-mark-iii": ["genesis_plus_gx"],
|
||||
"sega-game-box-9": ["genesis_plus_gx"],
|
||||
"sega-master-system-ii": ["genesis_plus_gx", "smsplus"],
|
||||
"master-system-super-compact": ["genesis_plus_gx"],
|
||||
"master-system-girl": ["genesis_plus_gx"],
|
||||
"genesis-slash-megadrive": ["genesis_plus_gx"],
|
||||
"sega-mega-drive-2-slash-genesis": ["genesis_plus_gx"],
|
||||
"sega-mega-jet": ["genesis_plus_gx"],
|
||||
"mega-pc": ["genesis_plus_gx"],
|
||||
"tera-drive": ["genesis_plus_gx"],
|
||||
"sega-nomad": ["genesis_plus_gx"],
|
||||
saturn: ["yabause"],
|
||||
snes: ["snes9x"],
|
||||
sfam: ["snes9x"],
|
||||
"super-nintendo-original-european-version": ["snes9x"],
|
||||
"super-famicom-shvc-001": ["snes9x"],
|
||||
"super-famicom-jr-model-shvc-101": ["snes9x"],
|
||||
"new-style-super-nes-model-sns-101": ["snes9x"],
|
||||
"turbografx16--1": ["mednafen_pce"],
|
||||
"vic-20": ["vice_xvic"],
|
||||
virtualboy: ["beetle_vb"],
|
||||
wonderswan: ["mednafen_wswan"],
|
||||
swancrystal: ["mednafen_wswan"],
|
||||
"wonderswan-color": ["mednafen_wswan"],
|
||||
} as const;
|
||||
|
||||
export type EJSPlatformSlug = keyof typeof _EJS_CORES_MAP;
|
||||
|
||||
export function getSupportedCores(platformSlug: string) {
|
||||
return _EJS_CORES_MAP[platformSlug.toLowerCase() as EJSPlatformSlug] || [];
|
||||
}
|
||||
|
||||
export function isEmulationSupported(platformSlug: string) {
|
||||
return platformSlug.toLowerCase() in _EJS_CORES_MAP;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import type { PlatformSchema } from "@/__generated__";
|
||||
import ActionBar from "@/components/Details/ActionBar.vue";
|
||||
import AdditionalContent from "@/components/Details/AdditionalContent.vue";
|
||||
import BackgroundHeader from "@/components/Details/BackgroundHeader.vue";
|
||||
@@ -14,16 +13,17 @@ import TitleInfo from "@/components/Details/Title.vue";
|
||||
import platformApi from "@/services/api/platform";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeDownload from "@/stores/download";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { Emitter } from "mitt";
|
||||
import { inject, onBeforeMount, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useDisplay, useTheme } from "vuetify";
|
||||
import { useDisplay } from "vuetify";
|
||||
|
||||
const route = useRoute();
|
||||
const rom = ref<Rom>();
|
||||
const platform = ref<PlatformSchema>();
|
||||
const rom = ref<DetailedRom>();
|
||||
const platform = ref<Platform>();
|
||||
const tab = ref<
|
||||
| "details"
|
||||
| "saves"
|
||||
@@ -34,7 +34,6 @@ const tab = ref<
|
||||
| "relatedgames"
|
||||
| "emulation"
|
||||
>("details");
|
||||
const theme = useTheme();
|
||||
const { smAndDown, mdAndDown, mdAndUp, lgAndUp } = useDisplay();
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
const showEmulation = ref(false);
|
||||
@@ -42,6 +41,7 @@ emitter?.on("showEmulation", () => {
|
||||
showEmulation.value = !showEmulation.value;
|
||||
tab.value = showEmulation.value ? "emulation" : "details";
|
||||
});
|
||||
const noRomError = ref(false);
|
||||
|
||||
async function fetchDetails() {
|
||||
if (!route.params.rom) return;
|
||||
@@ -69,6 +69,7 @@ async function fetchDetails() {
|
||||
platform.value = response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
noRomError.value = true;
|
||||
console.log(error);
|
||||
emitter?.emit("snackbarShow", {
|
||||
msg: error.response.data.detail,
|
||||
@@ -118,23 +119,7 @@ watch(
|
||||
'cover-xs': smAndDown,
|
||||
}"
|
||||
>
|
||||
<cover
|
||||
:romId="rom.id"
|
||||
:src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/big_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_l}`
|
||||
"
|
||||
:lazy-src="
|
||||
!rom.igdb_id && !rom.moby_id && !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_unmatched.png`
|
||||
: !rom.has_cover
|
||||
? `/assets/default/cover/small_${theme.global.name.value}_missing_cover.png`
|
||||
: `/assets/romm/resources/${rom.path_cover_s}`
|
||||
"
|
||||
/>
|
||||
<cover :rom="rom" />
|
||||
<action-bar class="mt-2" :rom="rom" />
|
||||
<related-games class="mt-3 px-2" v-if="mdAndUp" :rom="rom" />
|
||||
</v-col>
|
||||
@@ -269,6 +254,15 @@ watch(
|
||||
</template>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<template v-if="noRomError">
|
||||
<v-empty-state
|
||||
headline="Whoops, 404"
|
||||
title="Game not found"
|
||||
text="The game you were looking for does not exist"
|
||||
icon="mdi-disc-alert"
|
||||
></v-empty-state>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -11,7 +11,7 @@ import storeRoms from "@/stores/roms";
|
||||
import storePlatforms from "@/stores/platforms";
|
||||
import type { Events } from "@/types/emitter";
|
||||
import type { RomSelectEvent } from "@/types/rom";
|
||||
import { normalizeString, toTop, views } from "@/utils";
|
||||
import { normalizeString, views } from "@/utils";
|
||||
import type { Emitter } from "mitt";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { inject, onBeforeUnmount, onMounted, ref } from "vue";
|
||||
@@ -31,10 +31,11 @@ const {
|
||||
filteredRoms,
|
||||
selectedRoms,
|
||||
searchRoms,
|
||||
cursor,
|
||||
searchCursor,
|
||||
platformID,
|
||||
itemsPerBatch,
|
||||
} = storeToRefs(romsStore);
|
||||
const itemsShown = ref(itemsPerBatch.value);
|
||||
const noPlatformError = ref(false);
|
||||
|
||||
// Event listeners bus
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
@@ -45,12 +46,7 @@ emitter?.on("openFabMenu", (open) => {
|
||||
|
||||
// Functions
|
||||
async function fetchRoms() {
|
||||
if (
|
||||
(searchCursor.value === null && galleryFilterStore.isFiltered()) ||
|
||||
(cursor.value === null && !galleryFilterStore.isFiltered()) ||
|
||||
gettingRoms.value
|
||||
)
|
||||
return;
|
||||
if (gettingRoms.value) return;
|
||||
|
||||
gettingRoms.value = true;
|
||||
emitter?.emit("showLoadingDialog", {
|
||||
@@ -61,25 +57,18 @@ async function fetchRoms() {
|
||||
await romApi
|
||||
.getRoms({
|
||||
platformId: platformID.value,
|
||||
cursor: galleryFilterStore.isFiltered()
|
||||
? searchCursor.value
|
||||
: cursor.value,
|
||||
searchTerm: normalizeString(galleryFilterStore.filterSearch),
|
||||
})
|
||||
.then(({ data }) => {
|
||||
// Add any new roms to the store
|
||||
const allRomsSet = [...allRoms.value, ...data.items];
|
||||
const allRomsSet = [...allRoms.value, ...data];
|
||||
romsStore.set(allRomsSet);
|
||||
romsStore.setFiltered(allRomsSet, galleryFilterStore);
|
||||
|
||||
if (galleryFilterStore.isFiltered()) {
|
||||
if (data.next_page !== undefined) searchCursor.value = data.next_page;
|
||||
|
||||
const serchedRomsSet = [...searchRoms.value, ...data.items];
|
||||
const serchedRomsSet = [...searchRoms.value, ...data];
|
||||
romsStore.setSearch(serchedRomsSet);
|
||||
romsStore.setFiltered(serchedRomsSet, galleryFilterStore);
|
||||
} else if (data.next_page !== undefined) {
|
||||
cursor.value = data.next_page;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -89,7 +78,9 @@ async function fetchRoms() {
|
||||
color: "red",
|
||||
timeout: 4000,
|
||||
});
|
||||
console.error(`Couldn't fetch roms for platform ID ${platformID.value}: ${error}`);
|
||||
console.error(
|
||||
`Couldn't fetch roms for platform ID ${platformID.value}: ${error}`
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
gettingRoms.value = false;
|
||||
@@ -101,13 +92,13 @@ async function fetchRoms() {
|
||||
}
|
||||
|
||||
async function onFilterChange() {
|
||||
searchCursor.value = "";
|
||||
romsStore.setSearch([]);
|
||||
if (!galleryFilterStore.isFiltered()) {
|
||||
romsStore.setFiltered(allRoms.value, galleryFilterStore);
|
||||
return;
|
||||
}
|
||||
await fetchRoms();
|
||||
emitter?.emit("updateDataTablePages", null);
|
||||
}
|
||||
|
||||
function selectRom({ event, index, selected }: RomSelectEvent) {
|
||||
@@ -163,23 +154,32 @@ function setFilters() {
|
||||
}
|
||||
|
||||
function resetGallery() {
|
||||
cursor.value = "";
|
||||
searchCursor.value = "";
|
||||
romsStore.reset();
|
||||
scrolledToTop.value = true;
|
||||
galleryFilterStore.reset();
|
||||
itemsShown.value = itemsPerBatch.value;
|
||||
}
|
||||
|
||||
function scrollToTop() {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: "smooth",
|
||||
});
|
||||
scrolledToTop.value = true;
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
window.setTimeout(async () => {
|
||||
const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
|
||||
scrolledToTop.value = scrollTop === 0;
|
||||
|
||||
if (!cursor.value && !searchCursor.value) return;
|
||||
|
||||
const scrollOffset = 60;
|
||||
if (scrollTop + clientHeight + scrollOffset >= scrollHeight) {
|
||||
await fetchRoms();
|
||||
const totalScrollableHeight = scrollHeight - clientHeight;
|
||||
const ninetyPercentPoint = totalScrollableHeight * 0.9;
|
||||
if (
|
||||
scrollTop >= ninetyPercentPoint &&
|
||||
itemsShown.value < filteredRoms.value.length
|
||||
) {
|
||||
itemsShown.value = itemsShown.value + itemsPerBatch.value;
|
||||
setFilters();
|
||||
}
|
||||
}, 100);
|
||||
@@ -188,13 +188,21 @@ function onScroll() {
|
||||
onMounted(async () => {
|
||||
const storedPlatformID = romsStore.platformID;
|
||||
const platformID = Number(route.params.platform);
|
||||
|
||||
|
||||
romsStore.setPlatformID(platformID);
|
||||
|
||||
const platform = platforms.get(platformID);
|
||||
if (!platform) {
|
||||
const { data } = await platformApi.getPlatform(platformID)
|
||||
platforms.add(data);
|
||||
// const { data } =
|
||||
await platformApi
|
||||
.getPlatform(platformID)
|
||||
.then((data) => {
|
||||
platforms.add(data.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
noPlatformError.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
// If platform is different, reset store and fetch roms
|
||||
@@ -210,10 +218,12 @@ onMounted(async () => {
|
||||
setFilters();
|
||||
|
||||
window.addEventListener("wheel", onScroll);
|
||||
window.addEventListener("touchstart", onScroll);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("wheel", onScroll);
|
||||
window.removeEventListener("touchstart", onScroll);
|
||||
});
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
@@ -227,13 +237,13 @@ onBeforeRouteUpdate(async (to, _) => {
|
||||
// Triggers when change query param of the same route
|
||||
// Reset store if switching to another platform
|
||||
resetGallery();
|
||||
|
||||
|
||||
const platformID = Number(to.params.platform);
|
||||
romsStore.setPlatformID(platformID);
|
||||
|
||||
const platform = platforms.get(platformID);
|
||||
if (!platform) {
|
||||
const { data } = await platformApi.getPlatform(platformID)
|
||||
const { data } = await platformApi.getPlatform(platformID);
|
||||
platforms.add(data);
|
||||
}
|
||||
|
||||
@@ -248,6 +258,7 @@ onBeforeRouteUpdate(async (to, _) => {
|
||||
<template v-if="filteredRoms.length > 0">
|
||||
<v-row class="pa-1" no-gutters>
|
||||
<!-- Gallery cards view -->
|
||||
<!-- v-show instead of v-if to avoid recalculate on view change -->
|
||||
<v-col
|
||||
class="pa-1"
|
||||
v-show="galleryViewStore.current != 2"
|
||||
@@ -257,7 +268,7 @@ onBeforeRouteUpdate(async (to, _) => {
|
||||
:md="views[galleryViewStore.current]['size-md']"
|
||||
:lg="views[galleryViewStore.current]['size-lg']"
|
||||
:xl="views[galleryViewStore.current]['size-xl']"
|
||||
v-for="rom in filteredRoms"
|
||||
v-for="rom in filteredRoms.slice(0, itemsShown)"
|
||||
:key="rom.id"
|
||||
>
|
||||
<game-card
|
||||
@@ -276,50 +287,71 @@ onBeforeRouteUpdate(async (to, _) => {
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<v-empty-state
|
||||
v-if="!gettingRoms && galleryFilterStore.isFiltered()"
|
||||
headline="No games to show"
|
||||
icon="mdi-disc-alert"
|
||||
></v-empty-state>
|
||||
</template>
|
||||
|
||||
<template v-if="noPlatformError">
|
||||
<v-empty-state
|
||||
headline="Whoops, 404"
|
||||
title="Platform not found"
|
||||
text="The platform you were looking for does not exist"
|
||||
icon="mdi-controller-off"
|
||||
></v-empty-state>
|
||||
</template>
|
||||
|
||||
<v-layout-item
|
||||
class="text-end"
|
||||
v-show="!scrolledToTop || romsStore._selectedIDs.length > 0"
|
||||
class="text-end pr-2"
|
||||
:model-value="true"
|
||||
position="bottom"
|
||||
size="88"
|
||||
size="65"
|
||||
>
|
||||
<div class="ma-4">
|
||||
<v-scroll-y-reverse-transition>
|
||||
<v-btn
|
||||
id="scrollToTop"
|
||||
v-show="!scrolledToTop"
|
||||
color="primary"
|
||||
elevation="8"
|
||||
icon
|
||||
class="mr-2"
|
||||
size="large"
|
||||
@click="toTop()"
|
||||
><v-icon color="romm-accent-1">mdi-chevron-up</v-icon></v-btn
|
||||
<v-row no-gutters>
|
||||
<v-col>
|
||||
<v-scroll-y-reverse-transition>
|
||||
<v-btn
|
||||
v-show="!scrolledToTop"
|
||||
id="scrollToTop"
|
||||
color="primary"
|
||||
elevation="8"
|
||||
icon
|
||||
class="ml-2"
|
||||
size="large"
|
||||
@click="scrollToTop()"
|
||||
><v-icon color="romm-accent-1">mdi-chevron-up</v-icon></v-btn
|
||||
>
|
||||
</v-scroll-y-reverse-transition>
|
||||
<v-menu
|
||||
location="top"
|
||||
v-model="fabMenu"
|
||||
:transition="
|
||||
fabMenu ? 'scroll-y-reverse-transition' : 'scroll-y-transition'
|
||||
"
|
||||
>
|
||||
</v-scroll-y-reverse-transition>
|
||||
<v-menu
|
||||
location="top"
|
||||
v-model="fabMenu"
|
||||
:transition="
|
||||
fabMenu ? 'scroll-y-reverse-transition' : 'scroll-y-transition'
|
||||
"
|
||||
>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-fab-transition>
|
||||
<v-btn
|
||||
v-show="romsStore._selectedIDs.length > 0"
|
||||
color="romm-accent-1"
|
||||
v-bind="props"
|
||||
elevation="8"
|
||||
icon
|
||||
size="large"
|
||||
>{{ romsStore._selectedIDs.length }}</v-btn
|
||||
>
|
||||
</v-fab-transition>
|
||||
</template>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-fab-transition>
|
||||
<v-btn
|
||||
v-show="romsStore._selectedIDs.length > 0"
|
||||
color="romm-accent-1"
|
||||
v-bind="props"
|
||||
elevation="8"
|
||||
class="ml-2"
|
||||
icon
|
||||
size="large"
|
||||
>{{ romsStore._selectedIDs.length }}</v-btn
|
||||
>
|
||||
</v-fab-transition>
|
||||
</template>
|
||||
|
||||
<fab-menu />
|
||||
</v-menu>
|
||||
</div>
|
||||
<fab-menu />
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-layout-item>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,20 +2,22 @@
|
||||
import { onMounted, ref } from "vue";
|
||||
import { isNull } from "lodash";
|
||||
import type { FirmwareSchema, SaveSchema, StateSchema } from "@/__generated__";
|
||||
import { formatBytes } from "@/utils";
|
||||
import { formatBytes, getSupportedCores } from "@/utils";
|
||||
import romApi from "@/services/api/rom";
|
||||
import firmwareApi from "@/services/api/firmware";
|
||||
import { useRoute } from "vue-router";
|
||||
import Player from "@/views/Play/Player.vue";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
const route = useRoute();
|
||||
const rom = ref<Rom | null>(null);
|
||||
const rom = ref<DetailedRom | null>(null);
|
||||
const firmwareOptions = ref<FirmwareSchema[]>([]);
|
||||
|
||||
const biosRef = ref<FirmwareSchema | null>(null);
|
||||
const saveRef = ref<SaveSchema | null>(null);
|
||||
const stateRef = ref<StateSchema | null>(null);
|
||||
const supportedCores = ref<string[]>([]);
|
||||
const coreRef = ref<string | null>(null);
|
||||
const gameRunning = ref(false);
|
||||
|
||||
const storedFSOP = localStorage.getItem("fullScreenOnPlay");
|
||||
@@ -30,6 +32,8 @@ onMounted(async () => {
|
||||
romId: parseInt(route.params.rom as string),
|
||||
});
|
||||
rom.value = romResponse.data;
|
||||
supportedCores.value = [...getSupportedCores(rom.value.platform_slug)];
|
||||
coreRef.value = supportedCores.value[0];
|
||||
|
||||
const firmwareResponse = await firmwareApi.getFirmware({
|
||||
platformId: romResponse.data.platform_id,
|
||||
@@ -56,6 +60,22 @@ function onFullScreenChange() {
|
||||
width="250"
|
||||
src="/assets/emulatorjs/powered_by_emulatorjs.png"
|
||||
/>
|
||||
<v-select
|
||||
v-if="supportedCores.length > 1"
|
||||
density="compact"
|
||||
class="my-2"
|
||||
hide-details
|
||||
variant="outlined"
|
||||
clearable
|
||||
label="Core"
|
||||
v-model="coreRef"
|
||||
:items="
|
||||
supportedCores.map((c) => ({
|
||||
title: c,
|
||||
value: c,
|
||||
}))
|
||||
"
|
||||
/>
|
||||
<v-select
|
||||
class="my-1"
|
||||
hide-details
|
||||
@@ -132,7 +152,13 @@ function onFullScreenChange() {
|
||||
</v-col>
|
||||
|
||||
<v-col class="bg-primary" rounded id="game-wrapper">
|
||||
<player :rom="rom" :state="stateRef" :save="saveRef" :bios="biosRef" />
|
||||
<player
|
||||
:rom="rom"
|
||||
:state="stateRef"
|
||||
:save="saveRef"
|
||||
:bios="biosRef"
|
||||
:core="coreRef"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
@@ -3,16 +3,16 @@ import { ref, onBeforeUnmount } from "vue";
|
||||
import stateApi from "@/services/api/state";
|
||||
import saveApi, { saveApi as api } from "@/services/api/save";
|
||||
import screenshotApi from "@/services/api/screenshot";
|
||||
import { platformSlugEJSCoreMap } from "@/utils";
|
||||
import { getSupportedCores } from "@/utils";
|
||||
import type { FirmwareSchema, SaveSchema, StateSchema } from "@/__generated__";
|
||||
import type { Rom } from "@/stores/roms";
|
||||
import type { ValueOf } from "@/types";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
|
||||
const props = defineProps<{
|
||||
rom: Rom;
|
||||
rom: DetailedRom;
|
||||
save: SaveSchema | null;
|
||||
state: StateSchema | null;
|
||||
bios: FirmwareSchema | null;
|
||||
core: string | null;
|
||||
}>();
|
||||
const saveRef = ref<SaveSchema | null>(props.save);
|
||||
const stateRef = ref<StateSchema | null>(props.state);
|
||||
@@ -21,13 +21,10 @@ onBeforeUnmount(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
type EJSPlatformSlug = keyof typeof platformSlugEJSCoreMap;
|
||||
type EJSCore = ValueOf<typeof platformSlugEJSCoreMap>;
|
||||
|
||||
// Declare global variables for EmulatorJS
|
||||
declare global {
|
||||
interface Window {
|
||||
EJS_core: EJSCore;
|
||||
EJS_core: string;
|
||||
EJS_biosUrl: string;
|
||||
EJS_player: string;
|
||||
EJS_pathtodata: string;
|
||||
@@ -53,10 +50,9 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
const supportedCores = getSupportedCores(props.rom.platform_slug);
|
||||
window.EJS_core =
|
||||
platformSlugEJSCoreMap[
|
||||
props.rom.platform_slug.toLowerCase() as EJSPlatformSlug
|
||||
];
|
||||
supportedCores.find((core) => core === props.core) ?? supportedCores[0];
|
||||
window.EJS_gameID = props.rom.id;
|
||||
window.EJS_gameUrl = `/api/roms/${props.rom.id}/content/${props.rom.file_name}`;
|
||||
window.EJS_biosUrl = props.bios
|
||||
@@ -200,7 +196,6 @@ window.EJS_onSaveState = function ({
|
||||
if (stateRef.value)
|
||||
stateRef.value.screenshot = data.screenshots[0];
|
||||
props.rom.user_screenshots = data.screenshots;
|
||||
props.rom.url_screenshots = data.url_screenshots;
|
||||
props.rom.merged_screenshots = data.merged_screenshots;
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
@@ -243,7 +238,6 @@ window.EJS_onSaveState = function ({
|
||||
})
|
||||
.then(({ data }) => {
|
||||
props.rom.user_screenshots = data.screenshots;
|
||||
props.rom.url_screenshots = data.url_screenshots;
|
||||
props.rom.merged_screenshots = data.merged_screenshots;
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
@@ -330,7 +324,6 @@ window.EJS_onSaveSave = function ({
|
||||
.then(({ data }) => {
|
||||
if (saveRef.value) saveRef.value.screenshot = data.screenshots[0];
|
||||
props.rom.user_screenshots = data.screenshots;
|
||||
props.rom.url_screenshots = data.url_screenshots;
|
||||
props.rom.merged_screenshots = data.merged_screenshots;
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
@@ -368,7 +361,6 @@ window.EJS_onSaveSave = function ({
|
||||
})
|
||||
.then(({ data }) => {
|
||||
props.rom.user_screenshots = data.screenshots;
|
||||
props.rom.url_screenshots = data.url_screenshots;
|
||||
props.rom.merged_screenshots = data.merged_screenshots;
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
@@ -400,6 +392,12 @@ window.EJS_onGameStart = async () => {
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
#game .ejs_cheat_code {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Other config options: https://emulatorjs.org/docs/Options.html -->
|
||||
|
||||
<!-- window.EJS_biosUrl; -->
|
||||
|
||||
@@ -41,20 +41,18 @@ const HEADERS = [
|
||||
},
|
||||
{ title: "", align: "end", key: "actions", sortable: false },
|
||||
] as const;
|
||||
|
||||
const PER_PAGE_OPTIONS = [
|
||||
{ value: 5, title: "5" },
|
||||
{ value: 10, title: "10" },
|
||||
{ value: 25, title: "25" },
|
||||
{ value: -1, title: "$vuetify.dataFooter.itemsPerPageAll" },
|
||||
];
|
||||
const PER_PAGE_OPTIONS = [10, 25, 50, 100];
|
||||
|
||||
// Props
|
||||
const emitter = inject<Emitter<Events>>("emitter");
|
||||
const auth = storeAuth();
|
||||
const usersStore = storeUsers();
|
||||
const usersPerPage = ref(5);
|
||||
const userSearch = ref("");
|
||||
const storedUsersPerPage = parseInt(localStorage.getItem("usersPerPage") ?? "");
|
||||
const usersPerPage = ref(isNaN(storedUsersPerPage) ? 25 : storedUsersPerPage);
|
||||
const page = ref(1);
|
||||
const pageCount = ref(0);
|
||||
emitter?.on("updateDataTablePages", updateDataTablePages);
|
||||
|
||||
function disableUser(user: User) {
|
||||
userApi.updateUser(user).catch(({ response, message }) => {
|
||||
@@ -69,6 +67,10 @@ function disableUser(user: User) {
|
||||
});
|
||||
}
|
||||
|
||||
function updateDataTablePages() {
|
||||
pageCount.value = Math.ceil(usersStore.all.length / usersPerPage.value);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
userApi
|
||||
.fetchUsers()
|
||||
@@ -116,6 +118,7 @@ onMounted(() => {
|
||||
:search="userSearch"
|
||||
:headers="HEADERS"
|
||||
:items="usersStore.all"
|
||||
v-model:page="page"
|
||||
:sort-by="[{ key: 'username', order: 'asc' }]"
|
||||
>
|
||||
<template v-slot:item.avatar_path="{ item }">
|
||||
@@ -160,6 +163,32 @@ onMounted(() => {
|
||||
><v-icon>mdi-delete</v-icon></v-btn
|
||||
>
|
||||
</template>
|
||||
|
||||
<template v-slot:bottom>
|
||||
<v-divider class="border-opacity-25" />
|
||||
<v-row no-gutters class="pt-2 align-center">
|
||||
<v-col cols="11" class="px-6">
|
||||
<v-pagination
|
||||
rounded="0"
|
||||
:show-first-last-page="true"
|
||||
active-color="romm-accent-1"
|
||||
v-model="page"
|
||||
:length="pageCount"
|
||||
></v-pagination>
|
||||
</v-col>
|
||||
<v-col cols="5" sm="2" xl="1">
|
||||
<v-select
|
||||
class="pa-2"
|
||||
label="Users per page"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
:items="PER_PAGE_OPTIONS"
|
||||
v-model="usersPerPage"
|
||||
hide-details
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
572
poetry.lock
generated
572
poetry.lock
generated
@@ -39,24 +39,24 @@ tz = ["backports.zoneinfo"]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
description = "Reusable constraint types to use with typing.Annotated"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
|
||||
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
|
||||
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
||||
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.3.0"
|
||||
version = "4.4.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
|
||||
{file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
|
||||
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
|
||||
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -99,38 +99,38 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "4.1.2"
|
||||
version = "4.1.3"
|
||||
description = "Modern password hashing for your software and your servers"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-win32.whl", hash = "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"},
|
||||
{file = "bcrypt-4.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-win32.whl", hash = "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f"},
|
||||
{file = "bcrypt-4.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42"},
|
||||
{file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946"},
|
||||
{file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d"},
|
||||
{file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab"},
|
||||
{file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb"},
|
||||
{file = "bcrypt-4.1.2.tar.gz", hash = "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:48429c83292b57bf4af6ab75809f8f4daf52aa5d480632e53707805cc1ce9b74"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a8bea4c152b91fd8319fef4c6a790da5c07840421c2b785084989bf8bbb7455"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d3b317050a9a711a5c7214bf04e28333cf528e0ed0ec9a4e55ba628d0f07c1a"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:094fd31e08c2b102a14880ee5b3d09913ecf334cd604af27e1013c76831f7b05"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4fb253d65da30d9269e0a6f4b0de32bd657a0208a6f4e43d3e645774fb5457f3"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:193bb49eeeb9c1e2db9ba65d09dc6384edd5608d9d672b4125e9320af9153a15"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:8cbb119267068c2581ae38790e0d1fbae65d0725247a930fc9900c285d95725d"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6cac78a8d42f9d120b3987f82252bdbeb7e6e900a5e1ba37f6be6fe4e3848286"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01746eb2c4299dd0ae1670234bf77704f581dd72cc180f444bfe74eb80495b64"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-win32.whl", hash = "sha256:037c5bf7c196a63dcce75545c8874610c600809d5d82c305dd327cd4969995bf"},
|
||||
{file = "bcrypt-4.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:8a893d192dfb7c8e883c4576813bf18bb9d59e2cfd88b68b725990f033f1b978"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d4cf6ef1525f79255ef048b3489602868c47aea61f375377f0d00514fe4a78c"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5698ce5292a4e4b9e5861f7e53b1d89242ad39d54c3da451a93cac17b61921a"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec3c2e1ca3e5c4b9edb94290b356d082b721f3f50758bce7cce11d8a7c89ce84"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3a5be252fef513363fe281bafc596c31b552cf81d04c5085bc5dac29670faa08"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5f7cd3399fbc4ec290378b541b0cf3d4398e4737a65d0f938c7c0f9d5e686611"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:c4c8d9b3e97209dd7111bf726e79f638ad9224b4691d1c7cfefa571a09b1b2d6"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:31adb9cbb8737a581a843e13df22ffb7c84638342de3708a98d5c986770f2834"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:551b320396e1d05e49cc18dd77d970accd52b322441628aca04801bbd1d52a73"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6717543d2c110a155e6821ce5670c1f512f602eabb77dba95717ca76af79867d"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-win32.whl", hash = "sha256:6004f5229b50f8493c49232b8e75726b568535fd300e5039e255d919fc3a07f2"},
|
||||
{file = "bcrypt-4.1.3-cp39-abi3-win_amd64.whl", hash = "sha256:2505b54afb074627111b5a8dc9b6ae69d0f01fea65c2fcaea403448c503d3991"},
|
||||
{file = "bcrypt-4.1.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:cb9c707c10bddaf9e5ba7cdb769f3e889e60b7d4fea22834b261f51ca2b89fed"},
|
||||
{file = "bcrypt-4.1.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9f8ea645eb94fb6e7bea0cf4ba121c07a3a182ac52876493870033141aa687bc"},
|
||||
{file = "bcrypt-4.1.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f44a97780677e7ac0ca393bd7982b19dbbd8d7228c1afe10b128fd9550eef5f1"},
|
||||
{file = "bcrypt-4.1.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d84702adb8f2798d813b17d8187d27076cca3cd52fe3686bb07a9083930ce650"},
|
||||
{file = "bcrypt-4.1.3.tar.gz", hash = "sha256:2ee15dd749f5952fe3f0430d0ff6b74082e159c50332a1413d51b5689cf06623"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -359,43 +359,43 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "42.0.5"
|
||||
version = "42.0.7"
|
||||
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.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"},
|
||||
{file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"},
|
||||
{file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"},
|
||||
{file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"},
|
||||
{file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"},
|
||||
{file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"},
|
||||
{file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"},
|
||||
{file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"},
|
||||
{file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"},
|
||||
{file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"},
|
||||
{file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"},
|
||||
{file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"},
|
||||
{file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -452,13 +452,13 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth
|
||||
|
||||
[[package]]
|
||||
name = "fakeredis"
|
||||
version = "2.21.3"
|
||||
version = "2.23.2"
|
||||
description = "Python implementation of redis API, can be used for testing purposes."
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
python-versions = "<4.0,>=3.7"
|
||||
files = [
|
||||
{file = "fakeredis-2.21.3-py3-none-any.whl", hash = "sha256:033fe5882a20ec308ed0cf67a86c1cd982a1bffa63deb0f52eaa625bd8ce305f"},
|
||||
{file = "fakeredis-2.21.3.tar.gz", hash = "sha256:e9e1c309d49d83c4ce1ab6f3ee2e56787f6a5573a305109017bf140334dd396d"},
|
||||
{file = "fakeredis-2.23.2-py3-none-any.whl", hash = "sha256:3721946b955930c065231befd24a9cdc68b339746e93848ef01a010d98e4eb4f"},
|
||||
{file = "fakeredis-2.23.2.tar.gz", hash = "sha256:d649c409abe46c63690b6c35d3c460e4ce64c69a52cea3f02daff2649378f878"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -469,7 +469,7 @@ sortedcontainers = ">=2,<3"
|
||||
bf = ["pyprobables (>=0.6,<0.7)"]
|
||||
cf = ["pyprobables (>=0.6,<0.7)"]
|
||||
json = ["jsonpath-ng (>=1.6,<2.0)"]
|
||||
lua = ["lupa (>=1.14,<3.0)"]
|
||||
lua = ["lupa (>=2.1,<3.0)"]
|
||||
probabilistic = ["pyprobables (>=0.6,<0.7)"]
|
||||
|
||||
[[package]]
|
||||
@@ -491,48 +491,15 @@ typing-extensions = ">=4.8.0"
|
||||
[package.extras]
|
||||
all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi-pagination"
|
||||
version = "0.12.21"
|
||||
description = "FastAPI pagination"
|
||||
optional = false
|
||||
python-versions = ">=3.8,<4.0"
|
||||
files = [
|
||||
{file = "fastapi_pagination-0.12.21-py3-none-any.whl", hash = "sha256:5715b3dec31f9f9a0df6e08a53d7efe8c185d1fc8b392438d60e15349d7478d1"},
|
||||
{file = "fastapi_pagination-0.12.21.tar.gz", hash = "sha256:ba0bd1023ae37cb32946e91b1356f2454809e15393911d68e318f5c7aa6887c4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
fastapi = ">=0.93.0"
|
||||
pydantic = ">=1.9.1"
|
||||
typing-extensions = ">=4.8.0,<5.0.0"
|
||||
|
||||
[package.extras]
|
||||
all = ["SQLAlchemy (>=1.3.20)", "asyncpg (>=0.24.0)", "beanie (>=1.25.0)", "bunnet (>=1.1.0,<2.0.0)", "databases (>=0.6.0)", "django (<5.0.0)", "mongoengine (>=0.23.1,<0.29.0)", "motor (>=2.5.1,<4.0.0)", "orm (>=0.3.1)", "ormar (>=0.11.2)", "piccolo (>=0.89,<0.122)", "pony (>=0.7.16,<0.8.0)", "scylla-driver (>=3.25.6,<4.0.0)", "sqlakeyset (>=2.0.1680321678,<3.0.0)", "sqlmodel (>=0.0.8,<0.0.15)", "tortoise-orm (>=0.16.18,<0.21.0)"]
|
||||
asyncpg = ["SQLAlchemy (>=1.3.20)", "asyncpg (>=0.24.0)"]
|
||||
beanie = ["beanie (>=1.25.0)"]
|
||||
bunnet = ["bunnet (>=1.1.0,<2.0.0)"]
|
||||
databases = ["databases (>=0.6.0)"]
|
||||
django = ["databases (>=0.6.0)", "django (<5.0.0)"]
|
||||
mongoengine = ["mongoengine (>=0.23.1,<0.29.0)"]
|
||||
motor = ["motor (>=2.5.1,<4.0.0)"]
|
||||
orm = ["databases (>=0.6.0)", "orm (>=0.3.1)"]
|
||||
ormar = ["ormar (>=0.11.2)"]
|
||||
piccolo = ["piccolo (>=0.89,<0.122)"]
|
||||
scylla-driver = ["scylla-driver (>=3.25.6,<4.0.0)"]
|
||||
sqlalchemy = ["SQLAlchemy (>=1.3.20)", "sqlakeyset (>=2.0.1680321678,<3.0.0)"]
|
||||
sqlmodel = ["sqlakeyset (>=2.0.1680321678,<3.0.0)", "sqlmodel (>=0.0.8,<0.0.15)"]
|
||||
tortoise = ["tortoise-orm (>=0.16.18,<0.21.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "freezegun"
|
||||
version = "1.4.0"
|
||||
version = "1.5.1"
|
||||
description = "Let your Python tests travel through time"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "freezegun-1.4.0-py3-none-any.whl", hash = "sha256:55e0fc3c84ebf0a96a5aa23ff8b53d70246479e9a68863f1fcac5a3e52f19dd6"},
|
||||
{file = "freezegun-1.4.0.tar.gz", hash = "sha256:10939b0ba0ff5adaecf3b06a5c2f73071d9678e507c5eaedb23c761d56ac774b"},
|
||||
{file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"},
|
||||
{file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -643,13 +610,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
description = "A minimal low-level HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
|
||||
{file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
|
||||
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
|
||||
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -660,7 +627,7 @@ h11 = ">=0.13,<0.15"
|
||||
asyncio = ["anyio (>=4.0,<5.0)"]
|
||||
http2 = ["h2 (>=3,<5)"]
|
||||
socks = ["socksio (==1.*)"]
|
||||
trio = ["trio (>=0.22.0,<0.25.0)"]
|
||||
trio = ["trio (>=0.22.0,<0.26.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
@@ -725,13 +692,13 @@ ipython = {version = ">=7.31.1", markers = "python_version >= \"3.11\""}
|
||||
|
||||
[[package]]
|
||||
name = "ipython"
|
||||
version = "8.24.0"
|
||||
version = "8.25.0"
|
||||
description = "IPython: Productive Interactive Computing"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
files = [
|
||||
{file = "ipython-8.24.0-py3-none-any.whl", hash = "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3"},
|
||||
{file = "ipython-8.24.0.tar.gz", hash = "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501"},
|
||||
{file = "ipython-8.25.0-py3-none-any.whl", hash = "sha256:53eee7ad44df903a06655871cbab66d156a051fd86f3ec6750470ac9604ac1ab"},
|
||||
{file = "ipython-8.25.0.tar.gz", hash = "sha256:c6ed726a140b6e725b911528f80439c534fac915246af3efc39440a6b0f9d716"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -749,7 +716,7 @@ typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""}
|
||||
[package.extras]
|
||||
all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"]
|
||||
black = ["black"]
|
||||
doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"]
|
||||
doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"]
|
||||
kernel = ["ipykernel"]
|
||||
matplotlib = ["matplotlib"]
|
||||
nbconvert = ["nbconvert"]
|
||||
@@ -762,13 +729,13 @@ test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "num
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.1.2"
|
||||
version = "2.2.0"
|
||||
description = "Safely pass data to untrusted environments and back."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
|
||||
{file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
|
||||
{file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"},
|
||||
{file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -809,13 +776,13 @@ drafts = ["pycryptodome"]
|
||||
|
||||
[[package]]
|
||||
name = "mako"
|
||||
version = "1.3.2"
|
||||
version = "1.3.5"
|
||||
description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"},
|
||||
{file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"},
|
||||
{file = "Mako-1.3.5-py3-none-any.whl", hash = "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a"},
|
||||
{file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1236,13 +1203,13 @@ xmp = ["defusedxml"]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
|
||||
{file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
|
||||
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
||||
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -1251,13 +1218,13 @@ testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.43"
|
||||
version = "3.0.45"
|
||||
description = "Library for building powerful interactive command lines in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"},
|
||||
{file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"},
|
||||
{file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"},
|
||||
{file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1290,13 +1257,13 @@ tests = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.21"
|
||||
version = "2.22"
|
||||
description = "C parser in Python"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
|
||||
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
|
||||
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
|
||||
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1342,18 +1309,18 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.6.4"
|
||||
version = "2.7.2"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"},
|
||||
{file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"},
|
||||
{file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"},
|
||||
{file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
annotated-types = ">=0.4.0"
|
||||
pydantic-core = "2.16.3"
|
||||
pydantic-core = "2.18.3"
|
||||
typing-extensions = ">=4.6.1"
|
||||
|
||||
[package.extras]
|
||||
@@ -1361,90 +1328,90 @@ email = ["email-validator (>=2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.16.3"
|
||||
description = ""
|
||||
version = "2.18.3"
|
||||
description = "Core functionality for Pydantic validation and serialization"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
|
||||
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
|
||||
{file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
|
||||
{file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
|
||||
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
|
||||
{file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
|
||||
{file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
|
||||
{file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
|
||||
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
|
||||
{file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
|
||||
{file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
|
||||
{file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
|
||||
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
|
||||
{file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
|
||||
{file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
|
||||
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
|
||||
{file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
|
||||
{file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
|
||||
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
|
||||
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
|
||||
{file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"},
|
||||
{file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"},
|
||||
{file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"},
|
||||
{file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"},
|
||||
{file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"},
|
||||
{file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"},
|
||||
{file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"},
|
||||
{file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1483,33 +1450,33 @@ windows-terminal = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.1.1"
|
||||
version = "8.2.1"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
|
||||
{file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
|
||||
{file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"},
|
||||
{file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=1.4,<2.0"
|
||||
pluggy = ">=1.5,<2.0"
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.23.6"
|
||||
version = "0.23.7"
|
||||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-asyncio-0.23.6.tar.gz", hash = "sha256:ffe523a89c1c222598c76856e76852b787504ddb72dd5d9b6617ffa8aa2cde5f"},
|
||||
{file = "pytest_asyncio-0.23.6-py3-none-any.whl", hash = "sha256:68516fdd1018ac57b846c9846b954f0393b26f094764a28c955eabb0536a4e8a"},
|
||||
{file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"},
|
||||
{file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1598,13 +1565,13 @@ cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "python-engineio"
|
||||
version = "4.9.0"
|
||||
version = "4.9.1"
|
||||
description = "Engine.IO server and client for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "python-engineio-4.9.0.tar.gz", hash = "sha256:e87459c15638e567711fd156e6f9c4a402668871bed79523f0ecfec744729ec7"},
|
||||
{file = "python_engineio-4.9.0-py3-none-any.whl", hash = "sha256:979859bff770725b75e60353d7ae53b397e8b517d05ba76733b404a3dcca3e4c"},
|
||||
{file = "python_engineio-4.9.1-py3-none-any.whl", hash = "sha256:f995e702b21f6b9ebde4e2000cd2ad0112ba0e5116ec8d22fe3515e76ba9dddd"},
|
||||
{file = "python_engineio-4.9.1.tar.gz", hash = "sha256:7631cf5563086076611e494c643b3fa93dd3a854634b5488be0bba0ef9b99709"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1711,13 +1678,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "5.0.3"
|
||||
version = "5.0.4"
|
||||
description = "Python client for Redis database and key-value store"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "redis-5.0.3-py3-none-any.whl", hash = "sha256:5da9b8fe9e1254293756c16c008e8620b3d15fcc6dde6babde9541850e72a32d"},
|
||||
{file = "redis-5.0.3.tar.gz", hash = "sha256:4973bae7444c0fbed64a06b87446f79361cb7e4ec1538c022d696ed7a5015580"},
|
||||
{file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"},
|
||||
{file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1729,13 +1696,13 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.2"
|
||||
version = "2.32.3"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"},
|
||||
{file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"},
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1750,13 +1717,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "rq"
|
||||
version = "1.16.1"
|
||||
version = "1.16.2"
|
||||
description = "RQ is a simple, lightweight, library for creating background jobs, and processing them."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "rq-1.16.1-py3-none-any.whl", hash = "sha256:273de33f10bb9f18cd1e8ccc0a4e8dba2b8eb86a6ab2a91ae674f99bd68025f1"},
|
||||
{file = "rq-1.16.1.tar.gz", hash = "sha256:d9a6314bc759a743b4a5d89aa467eaa3a31dbbc0a34bcd0ee82e8852d9ec166d"},
|
||||
{file = "rq-1.16.2-py3-none-any.whl", hash = "sha256:52e619f6cb469b00e04da74305045d244b75fecb2ecaa4f26422add57d3c5f09"},
|
||||
{file = "rq-1.16.2.tar.gz", hash = "sha256:5c5b9ad5fbaf792b8fada25cc7627f4d206a9a4455aced371d4f501cc3f13b34"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1832,13 +1799,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlakeyset"
|
||||
version = "2.0.1708907391"
|
||||
version = "2.0.1716332987"
|
||||
description = "offset-free paging for sqlalchemy"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
python-versions = "<4.0,>=3.7"
|
||||
files = [
|
||||
{file = "sqlakeyset-2.0.1708907391-py3-none-any.whl", hash = "sha256:3eb6bd0ccd599ab44aa5c0b0f9a710d5c4d24813c7053adc9398bf539b68859e"},
|
||||
{file = "sqlakeyset-2.0.1708907391.tar.gz", hash = "sha256:376af65f0faecea6e19b16dd5dd047439d4314c5ae1d85d8a46bbb1ee44f32e3"},
|
||||
{file = "sqlakeyset-2.0.1716332987-py3-none-any.whl", hash = "sha256:e28916828cdaaaaaee3905ba55722959ad2808d47b0bb3235e1d15c5480c17fa"},
|
||||
{file = "sqlakeyset-2.0.1716332987.tar.gz", hash = "sha256:504c20747c3f05484fa67b16dcc7c7b0d5367f7e5d3f335a8845184e61425d94"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2019,30 +1986,45 @@ files = [
|
||||
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
|
||||
test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"]
|
||||
|
||||
[[package]]
|
||||
name = "types-cffi"
|
||||
version = "1.16.0.20240331"
|
||||
description = "Typing stubs for cffi"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-cffi-1.16.0.20240331.tar.gz", hash = "sha256:b8b20d23a2b89cfed5f8c5bc53b0cb8677c3aac6d970dbc771e28b9c698f5dee"},
|
||||
{file = "types_cffi-1.16.0.20240331-py3-none-any.whl", hash = "sha256:a363e5ea54a4eb6a4a105d800685fde596bc318089b025b27dee09849fe41ff0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
types-setuptools = "*"
|
||||
|
||||
[[package]]
|
||||
name = "types-passlib"
|
||||
version = "1.7.7.20240311"
|
||||
version = "1.7.7.20240327"
|
||||
description = "Typing stubs for passlib"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-passlib-1.7.7.20240311.tar.gz", hash = "sha256:287dd27cec5421daf6be5c295f681baf343c146038c8bde4db783bcac1beccb7"},
|
||||
{file = "types_passlib-1.7.7.20240311-py3-none-any.whl", hash = "sha256:cd44166e9347ae516f4830046cd1673c1ef90a5cc7ddd1356cf8a14892f29249"},
|
||||
{file = "types-passlib-1.7.7.20240327.tar.gz", hash = "sha256:4cce6a1a3a6afee9fc4728b4d9784300764ac2be747f5bcc01646d904b85f4bb"},
|
||||
{file = "types_passlib-1.7.7.20240327-py3-none-any.whl", hash = "sha256:3a3b7f4258b71034d2e2f4f307d6810f9904f906cdf375514c8bdbdb28a4ad23"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-pyopenssl"
|
||||
version = "24.0.0.20240311"
|
||||
version = "24.1.0.20240425"
|
||||
description = "Typing stubs for pyOpenSSL"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-pyOpenSSL-24.0.0.20240311.tar.gz", hash = "sha256:7bca00cfc4e7ef9c5d2663c6a1c068c35798e59670595439f6296e7ba3d58083"},
|
||||
{file = "types_pyOpenSSL-24.0.0.20240311-py3-none-any.whl", hash = "sha256:6e8e8bfad34924067333232c93f7fc4b369856d8bea0d5c9d1808cb290ab1972"},
|
||||
{file = "types-pyOpenSSL-24.1.0.20240425.tar.gz", hash = "sha256:0a7e82626c1983dc8dc59292bf20654a51c3c3881bcbb9b337c1da6e32f0204e"},
|
||||
{file = "types_pyOpenSSL-24.1.0.20240425-py3-none-any.whl", hash = "sha256:f51a156835555dd2a1f025621e8c4fbe7493470331afeef96884d1d29bf3a473"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cryptography = ">=35.0.0"
|
||||
types-cffi = "*"
|
||||
|
||||
[[package]]
|
||||
name = "types-pyyaml"
|
||||
@@ -2057,13 +2039,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "types-redis"
|
||||
version = "4.6.0.20240311"
|
||||
version = "4.6.0.20240425"
|
||||
description = "Typing stubs for redis"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-redis-4.6.0.20240311.tar.gz", hash = "sha256:e049bbdff0e0a1f8e701b64636811291d21bff79bf1e7850850a44055224a85f"},
|
||||
{file = "types_redis-4.6.0.20240311-py3-none-any.whl", hash = "sha256:6b9d68a29aba1ee400c823d8e5fe88675282eb69d7211e72fe65dbe54b33daca"},
|
||||
{file = "types-redis-4.6.0.20240425.tar.gz", hash = "sha256:9402a10ee931d241fdfcc04592ebf7a661d7bb92a8dea631279f0d8acbcf3a22"},
|
||||
{file = "types_redis-4.6.0.20240425-py3-none-any.whl", hash = "sha256:ac5bc19e8f5997b9e76ad5d9cf15d0392d9f28cf5fc7746ea4a64b989c45c6a8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2072,27 +2054,38 @@ types-pyOpenSSL = "*"
|
||||
|
||||
[[package]]
|
||||
name = "types-requests"
|
||||
version = "2.31.0.20240311"
|
||||
version = "2.32.0.20240523"
|
||||
description = "Typing stubs for requests"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-requests-2.31.0.20240311.tar.gz", hash = "sha256:b1c1b66abfb7fa79aae09097a811c4aa97130eb8831c60e47aee4ca344731ca5"},
|
||||
{file = "types_requests-2.31.0.20240311-py3-none-any.whl", hash = "sha256:47872893d65a38e282ee9f277a4ee50d1b28bd592040df7d1fdaffdf3779937d"},
|
||||
{file = "types-requests-2.32.0.20240523.tar.gz", hash = "sha256:26b8a6de32d9f561192b9942b41c0ab2d8010df5677ca8aa146289d11d505f57"},
|
||||
{file = "types_requests-2.32.0.20240523-py3-none-any.whl", hash = "sha256:f19ed0e2daa74302069bbbbf9e82902854ffa780bc790742a810a9aaa52f65ec"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
urllib3 = ">=2"
|
||||
|
||||
[[package]]
|
||||
name = "types-setuptools"
|
||||
version = "70.0.0.20240524"
|
||||
description = "Typing stubs for setuptools"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-setuptools-70.0.0.20240524.tar.gz", hash = "sha256:e31fee7b9d15ef53980526579ac6089b3ae51a005a281acf97178e90ac71aff6"},
|
||||
{file = "types_setuptools-70.0.0.20240524-py3-none-any.whl", hash = "sha256:8f5379b9948682d72a9ab531fbe52932e84c4f38deda570255f9bae3edd766bc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.10.0"
|
||||
version = "4.12.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
|
||||
{file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
|
||||
{file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"},
|
||||
{file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2159,40 +2152,43 @@ yarl = "*"
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
version = "4.0.0"
|
||||
version = "4.0.1"
|
||||
description = "Filesystem events monitoring"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"},
|
||||
{file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"},
|
||||
{file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"},
|
||||
{file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"},
|
||||
{file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"},
|
||||
{file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"},
|
||||
{file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"},
|
||||
{file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"},
|
||||
{file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"},
|
||||
{file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"},
|
||||
{file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"},
|
||||
{file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"},
|
||||
{file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"},
|
||||
{file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"},
|
||||
{file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"},
|
||||
{file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"},
|
||||
{file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"},
|
||||
{file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"},
|
||||
{file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"},
|
||||
{file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"},
|
||||
{file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"},
|
||||
{file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"},
|
||||
{file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"},
|
||||
{file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"},
|
||||
{file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"},
|
||||
{file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"},
|
||||
{file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"},
|
||||
{file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"},
|
||||
{file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"},
|
||||
{file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"},
|
||||
{file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"},
|
||||
{file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"},
|
||||
{file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"},
|
||||
{file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"},
|
||||
{file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"},
|
||||
{file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"},
|
||||
{file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"},
|
||||
{file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"},
|
||||
{file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"},
|
||||
{file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"},
|
||||
{file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"},
|
||||
{file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"},
|
||||
{file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"},
|
||||
{file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"},
|
||||
{file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"},
|
||||
{file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"},
|
||||
{file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"},
|
||||
{file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"},
|
||||
{file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -2489,4 +2485,4 @@ multidict = ">=4.0"
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "0ff8ecf16515c8921e1bef2e6be3a9b2d26d505d7d561f134e1b4a0458a90a47"
|
||||
content-hash = "74e7f44309266b2588cfd1bea95274d0298f0615bbc012537d0918eb86d80200"
|
||||
|
||||
@@ -21,7 +21,6 @@ PyYAML = "6.0.1"
|
||||
Unidecode = "1.3.8"
|
||||
emoji = "2.10.1"
|
||||
python-dotenv = "1.0.1"
|
||||
fastapi-pagination = "^0.12.19"
|
||||
sqlakeyset = "^2.0.1708907391"
|
||||
pydash = "^7.0.7"
|
||||
mariadb = "1.1.10"
|
||||
|
||||
Reference in New Issue
Block a user