feat: add loading page with real-time initialization progress

- Create loading.html template with WebSocket-based progress updates
- Update initialization_service to emit progress events via ProgressService
- Modify setup endpoint to run initialization in background and redirect to loading page
- Add /loading route in page_controller
- Show real-time progress for series sync, NFO scan, and media scan steps
- Display completion message with button to continue to app
- Handle errors with visual feedback
This commit is contained in:
2026-01-23 14:54:56 +01:00
parent 77ffdac84b
commit 48a2fd0f2a
5 changed files with 714 additions and 21 deletions

View File

@@ -30,7 +30,8 @@ async def setup_auth(req: SetupRequest):
"""Initial setup endpoint to configure the master password.
This endpoint also initializes the configuration with all provided values
and saves them to config.json.
and saves them to config.json. It triggers background initialization
and redirects to a loading page that shows real-time progress.
"""
if auth_service.is_configured():
raise HTTPException(
@@ -117,17 +118,9 @@ async def setup_auth(req: SetupRequest):
# Save the config with all updates
config_service.save_config(config, create_backup=False)
# Perform initial setup (series sync, NFO scan, media scan)
# This ensures everything is initialized immediately after setup
# without requiring an application restart
from src.config.settings import settings
from src.server.services.initialization_service import (
perform_initial_setup,
perform_nfo_scan_if_needed,
)
# Sync config.json values to settings object
# (mirroring the logic in fastapi_app.py lifespan)
from src.config.settings import settings
other_settings = dict(config.other) if config.other else {}
if other_settings.get("anime_directory"):
settings.anime_directory = str(other_settings["anime_directory"])
@@ -142,12 +135,53 @@ async def setup_auth(req: SetupRequest):
settings.nfo_download_fanart = config.nfo.download_fanart
settings.nfo_image_size = config.nfo.image_size
# Perform the initial series sync and mark as completed
await perform_initial_setup()
# Trigger initialization in background task
import asyncio
from src.server.services.initialization_service import (
perform_initial_setup,
perform_nfo_scan_if_needed,
)
from src.server.utils.dependencies import get_progress_service
# Perform NFO scan if configured
await perform_nfo_scan_if_needed()
progress_service = get_progress_service()
async def run_initialization():
"""Run initialization steps with progress updates."""
try:
# Perform the initial series sync and mark as completed
await perform_initial_setup(progress_service)
# Perform NFO scan if configured
await perform_nfo_scan_if_needed(progress_service)
# Send completion event
progress_service.emit_progress(
progress_id="initialization_complete",
progress_type="system",
status="completed",
title="Initialization Complete",
message="All initialization tasks completed successfully",
percent=100,
metadata={"initialization_complete": True}
)
except Exception as e:
# Send error event
progress_service.emit_progress(
progress_id="initialization_error",
progress_type="error",
status="failed",
title="Initialization Failed",
message=str(e),
percent=0,
metadata={"initialization_complete": True, "error": str(e)}
)
# Start initialization in background
asyncio.create_task(run_initialization())
# Return redirect to loading page
return {"status": "ok", "redirect": "/loading"}
# Note: Media scan is skipped during setup as it requires
# background_loader service which is only available during
# application lifespan. It will run on first application startup.