refactor(docs): restructure navigation as state machine

Replaced linear flow diagram with explicit state definitions and
transition table. Removes MIGRATION_GUIDE.md (merged into main docs).
This commit is contained in:
2026-06-07 20:02:51 +02:00
parent 4e0c66ea9e
commit b800158648
2 changed files with 111 additions and 195 deletions

View File

@@ -1,111 +0,0 @@
# Migration Guide: File-Based to Database Storage
## Overview
This guide covers the transition from file-based series metadata storage to the new database-backed system introduced in v2.0.
## What Changed
**Before v2.0**: Series metadata stored in `key` and `data` files alongside anime folders.
**After v2.0**: All metadata stored in SQLite database (`aniworld.db`). Files are deprecated but still supported for backward compatibility during migration.
## Automated Migration
The application automatically migrates on first startup:
1. Scans anime directory for `key` and `data` files
2. Parses legacy files into `AnimeSeries` and `Episode` records
3. Loads series into in-memory cache
4. Logs migration results
**No manual action required.**
## Manual Verification
After first startup with the new version:
1. **Check logs** for: `"Migrated X series from files to DB"`
2. **Verify series count**: UI shows same number of series as before
3. **Confirm episodes**: Episode counts match expected totals
```bash
# Check migration log
grep "Migrated" logs/app.log
# Verify series via API
curl http://localhost:8000/api/anime | jq '.total'
```
## After Migration
### Safe to Delete
Once verified, these files can be removed:
```
<anime_folder>/
├── Attack on Titan (2013)/
│ ├── key # ❌ Can delete
│ ├── data # ❌ Can delete
│ └── Season 1/
│ └── ...
```
**Deleting these files does not affect the database.** The metadata now lives in `aniworld.db`.
### Backup (Recommended)
Before deleting, backup the files:
```bash
# Create backup directory
mkdir -p backup/legacy_series_files
# Copy all key and data files
find /path/to/anime -name "key" -o -name "data" | while read f; do
cp "$f" "backup/legacy_series_files/"
done
```
## Reverting (Not Recommended)
If you must revert to file-based storage:
1. **Restore from database backup** (if available)
2. **Export manually** (no export script exists)
**Warning**: File-based storage is deprecated and will be removed in v3.0.0.
## Troubleshooting
### Series Not Appearing After Migration
1. Check logs for migration errors: `grep -i error logs/app.log`
2. Verify `key` and `data` files exist and are readable
3. Manually trigger rescan: `POST /api/scheduler/trigger-rescan`
### Duplicate Series
1. Check for duplicate `key` files (same series in multiple folders)
2. Verify series key uniqueness in database:
```bash
sqlite3 aniworld.db "SELECT key, COUNT(*) FROM anime_series GROUP BY key HAVING COUNT(*) > 1;"
```
### Missing Episodes
1. Trigger targeted scan for affected series
2. Check episode sync logs
3. Verify file permissions on anime directory
## Deprecation Timeline
| Version | Status |
|---------|--------|
| v2.0.x | Legacy files supported, migration automated |
| v2.1.x | Legacy files still supported, warnings in logs |
| v3.0.0 | **Legacy files removed** - database only |
Upgrade to v3.0.0 before legacy file support ends.

View File

@@ -4,54 +4,56 @@ This document describes the setup flow navigation, covering how users progress f
## Overview
The application uses a middleware-based redirect system to ensure users complete setup before accessing the main app. The flow involves multiple pages handling setup completion, unresolved folder detection, and initialization.
The application uses a middleware-based redirect system to enforce a strict state machine. Users must complete each phase before accessing the next. Attempting to bypass the current phase redirects to the appropriate page.
## Setup Flow
## State Machine
```
┌─────────────────────────────────────────────────────────────────────┐
SETUP FLOW
├─────────────────────────────────────────────────────────────────────┤
│ │
/setup ──► /loading ──► /setup/unresolved ──► /loading ──► /login
(first (Series Scan + (has folders) (all resolved)
time) NFO Scan)
│ │
[Done button] ──► marks complete
│ │
/loading (NFO phase runs again)
└────────┴─────────────────────────────────────┘
│ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────
NAVIGATION STATES
├─────────────────────────────────────────────────────────────────────────
NO_SETUP ──────────► SETUP_COMPLETE ──────────► UNRESOLVED_PENDING
│ │ │
│ │ │
│ ▼ ▼
/setup /loading /setup/unresolved │
(series scan) (resolve folders)
UNRESOLVED_DONE ───────┐
NFO_SCAN_PENDING
/loading
(NFO scan) │
│ ▼ │
│ COMPLETE │
│ │ │
│ ▼ │
│ /login │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
**New Navigation Order:**
1. `/setup` → Initial configuration
2. `/loading` → Series scan + NFO scan
3. `/setup/unresolved` → Resolve folders (if any)
4. `/loading` → NFO scan runs again
5. `/login` → Authentication
## State Definitions
**Key Changes:**
- After `/setup/unresolved`, the "Done" button marks the phase as complete
- Revisiting `/setup/unresolved` after completion → redirects to `/loading`
- `/loading` always goes to `/setup/unresolved` if unresolved folders exist
- NFO scan runs as a separate phase after series sync during initialization
| State | Condition | Target Page |
|-------|-----------|-------------|
| `NO_SETUP` | No master password configured | `/setup` |
| `SETUP_COMPLETE` | Initial config passed, loading not started | `/loading` |
| `UNRESOLVED_PENDING` | Setup done, unresolved exist, not marked done | `/setup/unresolved` |
| `UNRESOLVED_DONE` | Unresolved phase marked complete, NFO scan pending | `/loading` |
| `NFO_SCAN_PENDING` | Unresolved done, NFO scan incomplete | `/loading` |
| `COMPLETE` | All phases finished | `/login` |
## Middleware: SetupRedirectMiddleware
**File:** `src/server/middleware/setup_redirect.py`
The middleware intercepts all requests and redirects to `/setup` if:
- No master password is configured
- Configuration file is missing or invalid
The middleware intercepts all requests and enforces the state machine.
### Exempt Paths (always accessible)
@@ -68,13 +70,47 @@ The middleware intercepts all requests and redirects to `/setup` if:
### Middleware Logic
1. **Setup incomplete** → Redirect to `/setup`
2. **Setup complete, accessing `/setup`** → Redirect to `/login`
3. **Setup complete, accessing `/loading`** → Allow access (page handles its own redirect)
4. **Setup complete, accessing `/setup/unresolved`**:
- If `unresolved_completed` flag is set → Redirect to `/loading`
- Otherwise → Allow access
5. **API requests during setup** → Return 503 with `setup_url`
The middleware checks the current state and redirects accordingly:
```
1. NO_SETUP state:
→ Redirect ALL requests to /setup
→ Exception: /setup itself is accessible
2. SETUP_COMPLETE state:
→ Redirect /setup to /loading
→ Redirect any other page to /loading
3. UNRESOLVED_PENDING state (unresolved folders exist, not marked done):
→ Redirect /setup to /setup/unresolved
→ Redirect /loading to /setup/unresolved
→ Allow access to /setup/unresolved
→ Redirect any other page to /setup/unresolved
4. UNRESOLVED_DONE state (unresolved marked done, NFO scan pending):
→ Redirect /setup to /loading
→ Redirect /setup/unresolved to /loading
→ Redirect any other page to /loading
5. NFO_SCAN_PENDING state:
→ Redirect /setup to /loading
→ Redirect /setup/unresolved to /loading
→ Allow access to /loading (NFO phase runs)
→ Redirect any other page to /loading
6. COMPLETE state (loading finished):
→ Redirect /setup, /loading, /setup/unresolved to /login
→ Allow access to /login and main app
```
### Phase Tracking Flags
| Flag | Purpose |
|------|---------|
| `setup_complete` | Initial configuration was saved |
| `unresolved_completed` | User clicked "Done" on unresolved page |
| `loading_complete` | Series scan + initial loading finished |
| `nfo_scan_complete` | Final NFO scan finished |
## Pages
@@ -87,8 +123,11 @@ Handles initial configuration:
- Anime directory selection
- Database initialization
**Post-completion flow:**
- Redirects to `/loading` to begin initialization
**Allowed in states:** `NO_SETUP`
**Post-completion:**
- Sets `setup_complete` flag
- Redirects to `/loading`
### 2. Loading Page (`/loading`)
@@ -99,25 +138,28 @@ Shows initialization progress via WebSocket:
- Database population
- Logo/image loading
**Post-initialization flow:**
**Allowed in states:** `SETUP_COMPLETE`, `UNRESOLVED_DONE`, `NFO_SCAN_PENDING`
**Post-initialization (series scan complete):**
```javascript
async function checkUnresolvedAndProceed() {
// Fetch unresolved folders via API
const res = await fetch('/api/setup/unresolved', {
headers: { 'Authorization': `Bearer ${token}` }
});
const folders = await res.json();
if (folders.length > 0) {
// Has unresolved folders → go to resolution page
window.location.href = '/setup/unresolved';
} else {
// No unresolved folders → go to login
window.location.href = '/login';
}
}
```
**Post-NFO scan:**
- Sets `nfo_scan_complete` flag
- Redirects to `/login`
### 3. Unresolved Folders Page (`/setup/unresolved`)
**File:** `src/server/web/templates/unresolved.html`
@@ -127,24 +169,16 @@ Allows manual resolution of folders that couldn't be auto-matched:
- Provides search suggestions
- Input field for entering provider key
- Resolve/delete actions
- **Done button** at top to complete the phase without resolving all folders
- **Done button** to complete the phase without resolving all folders
**Post-resolution flow:**
```javascript
// After clicking "Done" button
async function handleDone() {
// Call API to mark phase as complete
await fetch('/api/setup/unresolved/done', { method: 'POST' });
// Redirect to loading for final NFO scan
window.location.href = '/loading';
}
```
**Allowed in states:** `UNRESOLVED_PENDING`
**Done button behavior:**
- Marks all remaining folders as handled
- Sets `unresolved_completed` flag in config
- Redirects to `/loading` to run final NFO scan
- After completion, `/setup/unresolved` becomes inaccessible (redirects to `/loading`)
- Sets `unresolved_completed` flag
- Redirects to `/loading` for final NFO scan
**After completion:**
- Any access redirects to `/loading`
### 4. Login Page (`/login`)
@@ -152,6 +186,8 @@ async function handleDone() {
Authentication page. After successful login → redirect to `/` (main app).
**Allowed in states:** `COMPLETE`
## API Endpoints
### Unresolved Folders API
@@ -177,7 +213,7 @@ Authentication page. After successful login → redirect to `/` (main app).
| File | Purpose |
|------|---------|
| `src/server/middleware/setup_redirect.py` | Redirect middleware |
| `src/server/middleware/setup_redirect.py` | Redirect middleware (state machine) |
| `src/server/controllers/page_controller.py` | Page route handlers |
| `src/server/web/templates/setup.html` | Setup template |
| `src/server/web/templates/loading.html` | Loading template |
@@ -185,22 +221,13 @@ Authentication page. After successful login → redirect to `/` (main app).
| `src/server/api/setup_endpoints.py` | Unresolved folders API |
| `src/server/database/service.py` | UnresolvedFolderService |
## Common Issues
## Navigation Summary
### Redirect Loop
**Symptom:** Browser keeps redirecting between pages.
**Causes:**
1. `loading.html` always redirected to `/setup/unresolved` without checking if any exist
2. `unresolved.html` redirected to `/` which middleware redirected back to `/login`
**Fix:** See the navigation logic updates in loading.html and unresolved.html.
### Can't Access Unresolved Page After Setup
**Symptom:** Middleware redirects to `/login` instead of allowing access to `/setup/unresolved`.
**Cause:** `/setup/unresolved` is in the exempt paths but the request may not be reaching it due to completion check timing.
**Fix:** The middleware allows access to `/loading` which handles the redirect to `/setup/unresolved` after initialization.
| Current State | Access `/setup` | Access `/loading` | Access `/setup/unresolved` |
|--------------|-----------------|-------------------|---------------------------|
| NO_SETUP | ✅ Allowed | ❌ → `/setup` | ❌ → `/setup` |
| SETUP_COMPLETE | ❌ → `/loading` | ✅ Allowed | ❌ → `/loading` |
| UNRESOLVED_PENDING | ❌ → `/setup/unresolved` | ❌ → `/setup/unresolved` | ✅ Allowed |
| UNRESOLVED_DONE | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
| NFO_SCAN_PENDING | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
| COMPLETE | ❌ → `/login` | ❌ → `/login` | ❌ → `/login` |