Aniworld/docs/instructions.md

891 lines
27 KiB
Markdown

# Aniworld Web Application Development Instructions
This document provides detailed tasks for AI agents to implement a modern web application for the Aniworld anime download manager. All tasks should follow the coding guidelines specified in the project's copilot instructions.
## Project Overview
The goal is to create a FastAPI-based web application that provides a modern interface for the existing Aniworld anime download functionality. The core anime logic should remain in `SeriesApp.py` while the web layer provides REST API endpoints and a responsive UI.
## Architecture Principles
- **Single Responsibility**: Each file/class has one clear purpose
- **Dependency Injection**: Use FastAPI's dependency system
- **Clean Separation**: Web layer calls core logic, never the reverse
- **File Size Limit**: Maximum 500 lines per file
- **Type Hints**: Use comprehensive type annotations
- **Error Handling**: Proper exception handling and logging
## Additional Implementation Guidelines
### Code Style and Standards
- **Type Hints**: Use comprehensive type annotations throughout all modules
- **Docstrings**: Follow PEP 257 for function and class documentation
- **Error Handling**: Implement custom exception classes with meaningful messages
- **Logging**: Use structured logging with appropriate log levels
- **Security**: Validate all inputs and sanitize outputs
- **Performance**: Use async/await patterns for I/O operations
## 📞 Escalation
If you encounter:
- Architecture issues requiring design decisions
- Tests that conflict with documented requirements
- Breaking changes needed
- Unclear requirements or expectations
**Document the issue and escalate rather than guessing.**
---
## 📚 Helpful Commands
```bash
# Run all tests
conda run -n AniWorld python -m pytest tests/ -v --tb=short
# Run specific test file
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py -v
# Run specific test class
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService -v
# Run specific test
conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService::test_broadcast_download_progress -v
# Run with extra verbosity
conda run -n AniWorld python -m pytest tests/ -vv
# Run with full traceback
conda run -n AniWorld python -m pytest tests/ -v --tb=long
# Run and stop at first failure
conda run -n AniWorld python -m pytest tests/ -v -x
# Run tests matching pattern
conda run -n AniWorld python -m pytest tests/ -v -k "auth"
# Show all print statements
conda run -n AniWorld python -m pytest tests/ -v -s
#Run app
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload
```
---
## Implementation Notes
1. **Incremental Development**: Implement features incrementally, testing each component thoroughly before moving to the next
2. **Code Review**: Review all generated code for adherence to project standards
3. **Documentation**: Document all public APIs and complex logic
4. **Testing**: Maintain test coverage above 80% for all new code
5. **Performance**: Profile and optimize critical paths, especially download and streaming operations
6. **Security**: Regular security audits and dependency updates
7. **Monitoring**: Implement comprehensive monitoring and alerting
8. **Maintenance**: Plan for regular maintenance and updates
## Task Completion Checklist
For each task completed:
- [ ] Implementation follows coding standards
- [ ] Unit tests written and passing
- [ ] Integration tests passing
- [ ] Documentation updated
- [ ] Error handling implemented
- [ ] Logging added
- [ ] Security considerations addressed
- [ ] Performance validated
- [ ] Code reviewed
- [ ] Task marked as complete in instructions.md
- [ ] Infrastructure.md updated and other docs
- [ ] Changes committed to git; keep your messages in git short and clear
- [ ] Take the next task
---
## Task: Refactor CSS & JavaScript Files (Single Responsibility Principle) ✅ COMPLETED
### Status: COMPLETED
The CSS and JavaScript files have been successfully refactored into modular structures.
### Summary of Changes
**CSS Refactoring:**
- Created 17 modular CSS files organized into `base/`, `components/`, `pages/`, and `utilities/` directories
- `styles.css` now serves as an entry point with @import statements
- All CSS files under 500 lines (largest: helpers.css at 368 lines)
- Total: 3,146 lines across 17 files
**JavaScript Refactoring:**
- Created 6 shared utility modules in `js/shared/`
- Created 11 index page modules in `js/index/`
- Created 5 queue page modules in `js/queue/`
- Uses IIFE pattern with `AniWorld` namespace for browser compatibility
- All JS files under 500 lines (largest: scan-manager.js at 439 lines)
- Total: 4,795 lines across 22 modules
**Updated Files:**
- `index.html` - Updated script tags for modular JS
- `queue.html` - Updated script tags for modular JS
- `test_static_files.py` - Updated tests for modular architecture
- `test_template_integration.py` - Updated tests for new JS structure
- `ARCHITECTURE.md` - Added frontend architecture documentation
**Old Files (kept for reference):**
- `app.js` - Original monolithic file (can be deleted)
- `queue.js` - Original monolithic file (can be deleted)
### Original Overview
Split monolithic `styles.css` (~2,135 lines), `app.js` (~2,305 lines), and `queue.js` (~993 lines) into smaller, focused files following the Single Responsibility Principle. Maximum 500 lines per file. All changes must maintain full backward compatibility with existing templates.
### Prerequisites
- Server is running and functional before starting
- All existing functionality works (login, index, queue pages)
- Backup current files before making changes
---
### Task 1: Analyze Current File Structure
**Objective**: Understand the current codebase before making changes.
**Steps**:
1. Open and read `src/server/web/static/css/styles.css`
2. Open and read `src/server/web/static/js/app.js`
3. Open and read `src/server/web/static/js/queue.js`
4. Open and read `src/server/web/templates/index.html`
5. Open and read `src/server/web/templates/queue.html`
6. Open and read `src/server/web/templates/login.html`
7. Document all CSS sections (look for comment headers)
8. Document all JavaScript functions and their dependencies
9. Identify shared utilities vs page-specific code
**Deliverable**: A mental map of all functions, styles, and their relationships.
---
### Task 2: Create CSS Directory Structure
**Objective**: Set up the new CSS file organization.
**Steps**:
1. Create directory: `src/server/web/static/css/base/`
2. Create directory: `src/server/web/static/css/components/`
3. Create directory: `src/server/web/static/css/pages/`
4. Create directory: `src/server/web/static/css/utilities/`
**File Structure to Create**:
```
src/server/web/static/css/
├── styles.css # Main entry point with @import statements
├── base/
│ ├── variables.css # CSS custom properties (colors, fonts, spacing)
│ ├── reset.css # CSS reset and normalize styles
│ └── typography.css # Font styles, headings, text utilities
├── components/
│ ├── buttons.css # All button styles
│ ├── cards.css # Card and panel components
│ ├── forms.css # Form inputs, labels, validation styles
│ ├── modals.css # Modal and overlay styles
│ ├── navigation.css # Header, nav, sidebar styles
│ ├── progress.css # Progress bars, loading indicators
│ ├── notifications.css # Toast, alerts, messages
│ └── tables.css # Table and list styles
├── pages/
│ ├── login.css # Login page specific styles
│ ├── index.css # Index/library page specific styles
│ └── queue.css # Queue page specific styles
└── utilities/
├── animations.css # Keyframes and animation classes
├── responsive.css # Media queries and breakpoints
└── helpers.css # Utility classes (hidden, flex, spacing)
```
---
### Task 3: Split styles.css into Modular Files
**Objective**: Extract styles from `styles.css` into appropriate module files.
**Steps**:
1. **Extract variables.css**:
- Find all `:root` CSS custom properties
- Extract color variables, font variables, spacing variables
- Include dark mode variables (`.dark-mode` or `[data-theme="dark"]`)
2. **Extract reset.css**:
- Extract `*`, `body`, `html` base resets
- Extract box-sizing rules
- Extract default margin/padding resets
3. **Extract typography.css**:
- Extract `h1-h6` styles
- Extract paragraph, link, text styles
- Extract font-related utility classes
4. **Extract buttons.css**:
- Find all `.btn`, `button`, `.button` related styles
- Include hover, active, disabled states
- Include button variants (primary, secondary, danger, etc.)
5. **Extract cards.css**:
- Extract `.card`, `.panel`, `.box` related styles
- Include card headers, bodies, footers
6. **Extract forms.css**:
- Extract `input`, `select`, `textarea` styles
- Extract `.form-group`, `.form-control` styles
- Extract validation states (error, success)
7. **Extract modals.css**:
- Extract `.modal`, `.overlay`, `.dialog` styles
- Include backdrop styles
- Include modal animations
8. **Extract navigation.css**:
- Extract `header`, `nav`, `.navbar` styles
- Extract menu and navigation link styles
9. **Extract progress.css**:
- Extract `.progress`, `.progress-bar` styles
- Extract loading spinners and indicators
10. **Extract notifications.css**:
- Extract `.toast`, `.alert`, `.notification` styles
- Include success, error, warning, info variants
11. **Extract tables.css**:
- Extract `table`, `.table` styles
- Extract list styles if table-like
12. **Extract page-specific styles**:
- `login.css`: Styles only used on login page
- `index.css`: Styles only used on index/library page (series cards, search)
- `queue.css`: Styles only used on queue page (queue items, download status)
13. **Extract animations.css**:
- Extract all `@keyframes` rules
- Extract animation utility classes
14. **Extract responsive.css**:
- Extract all `@media` queries
- Organize by breakpoint
15. **Extract helpers.css**:
- Extract utility classes (.hidden, .flex, .text-center, etc.)
- Extract spacing utilities
16. **Update main styles.css**:
- Replace all content with `@import` statements
- Order imports correctly (variables first, then reset, then components)
**Import Order in styles.css**:
```css
/* Base */
@import "base/variables.css";
@import "base/reset.css";
@import "base/typography.css";
/* Components */
@import "components/buttons.css";
@import "components/cards.css";
@import "components/forms.css";
@import "components/modals.css";
@import "components/navigation.css";
@import "components/progress.css";
@import "components/notifications.css";
@import "components/tables.css";
/* Pages */
@import "pages/login.css";
@import "pages/index.css";
@import "pages/queue.css";
/* Utilities (load last to allow overrides) */
@import "utilities/animations.css";
@import "utilities/responsive.css";
@import "utilities/helpers.css";
```
**Verification**:
- Start the server
- Check login page styling
- Check index page styling
- Check queue page styling
- Verify dark mode toggle works
- Verify responsive design works
---
### Task 4: Create JavaScript Directory Structure
**Objective**: Set up the new JavaScript file organization.
**Steps**:
1. Create directory: `src/server/web/static/js/shared/`
2. Create directory: `src/server/web/static/js/index/`
3. Create directory: `src/server/web/static/js/queue/`
**File Structure to Create**:
```
src/server/web/static/js/
├── app.js # Main entry point for index page
├── queue.js # Main entry point for queue page
├── shared/
│ ├── auth.js # Authentication utilities
│ ├── api-client.js # HTTP request wrapper with auth
│ ├── websocket-client.js # WebSocket connection management
│ ├── theme.js # Dark/light mode management
│ ├── ui-utils.js # Toast, loading overlay, formatters
│ └── constants.js # Shared constants and config
├── index/
│ ├── series-manager.js # Series loading, filtering, rendering
│ ├── search.js # Search functionality
│ ├── scan-manager.js # Library scan operations
│ ├── config-manager.js # Configuration modal handling
│ └── selection.js # Series/episode selection logic
└── queue/
├── queue-api.js # Queue API operations
├── queue-renderer.js # Render queue items (pending, active, etc.)
└── progress-handler.js # Real-time progress updates
```
---
### Task 5: Extract Shared JavaScript Utilities
**Objective**: Create reusable utility modules used by both index and queue pages.
**Steps**:
1. **Create constants.js**:
- Extract API endpoint URLs
- Extract localStorage keys
- Extract any magic strings or numbers
2. **Create auth.js**:
- Extract `checkAuth()` function
- Extract `logout()` function
- Extract `getAuthHeaders()` or token retrieval logic
- Extract token storage/retrieval from localStorage
3. **Create api-client.js**:
- Extract `fetchWithAuth()` wrapper function
- Handle automatic token injection
- Handle 401 redirect to login
- Handle common error responses
4. **Create websocket-client.js**:
- Extract WebSocket connection setup
- Extract message handling dispatcher
- Extract reconnection logic
- Extract connection state management
5. **Create theme.js**:
- Extract `initTheme()` function
- Extract `toggleTheme()` function
- Extract `setTheme()` function
- Extract theme persistence to localStorage
6. **Create ui-utils.js**:
- Extract `showToast()` function
- Extract `showLoadingOverlay()` / `hideLoadingOverlay()`
- Extract `formatBytes()` function
- Extract `formatDuration()` function
- Extract `formatDate()` function
- Extract any other shared UI helpers
**Pattern to Use (IIFE with Global Namespace)**:
```javascript
// Example: shared/auth.js
var AniWorld = window.AniWorld || {};
AniWorld.Auth = (function () {
"use strict";
const TOKEN_KEY = "auth_token";
function getToken() {
return localStorage.getItem(TOKEN_KEY);
}
function setToken(token) {
localStorage.setItem(TOKEN_KEY, token);
}
function removeToken() {
localStorage.removeItem(TOKEN_KEY);
}
function getAuthHeaders() {
const token = getToken();
return token ? { Authorization: "Bearer " + token } : {};
}
async function checkAuth() {
// Implementation
}
function logout() {
removeToken();
window.location.href = "/login";
}
// Public API
return {
getToken: getToken,
setToken: setToken,
getAuthHeaders: getAuthHeaders,
checkAuth: checkAuth,
logout: logout,
};
})();
```
---
### Task 6: Split app.js into Index Page Modules
**Objective**: Break down `app.js` into focused modules for the index/library page.
**Steps**:
1. **Create series-manager.js**:
- Extract series loading from API
- Extract series filtering logic
- Extract series rendering/DOM updates
- Extract series card click handlers
2. **Create search.js**:
- Extract search input handling
- Extract search API calls
- Extract search results rendering
- Extract search result selection
3. **Create scan-manager.js**:
- Extract scan initiation logic
- Extract scan progress overlay
- Extract scan progress updates (WebSocket)
- Extract scan completion handling
4. **Create config-manager.js**:
- Extract config modal open/close
- Extract config loading from API
- Extract config form handling
- Extract config save logic
- Extract scheduler configuration
- Extract backup management
5. **Create selection.js**:
- Extract episode selection logic
- Extract "select all" functionality
- Extract selection state management
- Extract "add to queue" from selection
6. **Update main app.js**:
- Import all modules via script tags
- Initialize all modules on DOMContentLoaded
- Wire up event listeners to module functions
- Keep this file as thin as possible (orchestration only)
**Example main app.js structure**:
```javascript
// filepath: src/server/web/static/js/app.js
document.addEventListener("DOMContentLoaded", async function () {
"use strict";
// Initialize shared modules
AniWorld.Theme.init();
// Check authentication
const isAuth = await AniWorld.Auth.checkAuth();
if (!isAuth) return;
// Initialize page-specific modules
AniWorld.SeriesManager.init();
AniWorld.Search.init();
AniWorld.ScanManager.init();
AniWorld.ConfigManager.init();
AniWorld.Selection.init();
// Initialize WebSocket for real-time updates
AniWorld.WebSocketClient.init();
// Load initial data
AniWorld.SeriesManager.loadSeries();
});
```
---
### Task 7: Split queue.js into Queue Page Modules
**Objective**: Break down `queue.js` into focused modules for the queue page.
**Steps**:
1. **Create queue-api.js**:
- Extract `loadQueueStatus()` API call
- Extract `startDownload()` API call
- Extract `stopDownload()` API call
- Extract `removeFromQueue()` API call
- Extract `clearCompleted()` API call
- Extract `clearFailed()` API call
- Extract `retryFailed()` API call
2. **Create queue-renderer.js**:
- Extract `renderActiveDownload()` function
- Extract `renderPendingQueue()` function
- Extract `renderCompletedList()` function
- Extract `renderFailedList()` function
- Extract `updateQueueCounts()` function
- Extract queue item template generation
3. **Create progress-handler.js**:
- Extract WebSocket message handling for queue
- Extract progress bar updates
- Extract status text updates
- Extract ETA calculations
- Extract speed display formatting
4. **Update main queue.js**:
- Import all modules via script tags
- Initialize all modules on DOMContentLoaded
- Wire up button click handlers to API functions
- Set up WebSocket handlers for progress
- Keep this file as thin as possible
**Example main queue.js structure**:
```javascript
// filepath: src/server/web/static/js/queue.js
document.addEventListener("DOMContentLoaded", async function () {
"use strict";
// Initialize shared modules
AniWorld.Theme.init();
// Check authentication
const isAuth = await AniWorld.Auth.checkAuth();
if (!isAuth) return;
// Initialize queue modules
AniWorld.QueueApi.init();
AniWorld.QueueRenderer.init();
AniWorld.ProgressHandler.init();
// Initialize WebSocket with queue-specific handlers
AniWorld.WebSocketClient.init({
onProgress: AniWorld.ProgressHandler.handleProgress,
onQueueUpdate: AniWorld.QueueRenderer.refresh,
});
// Load initial queue status
await AniWorld.QueueApi.loadStatus();
AniWorld.QueueRenderer.refresh();
// Wire up UI buttons
document
.getElementById("start-btn")
?.addEventListener("click", AniWorld.QueueApi.startDownload);
document
.getElementById("stop-btn")
?.addEventListener("click", AniWorld.QueueApi.stopDownload);
document
.getElementById("clear-completed-btn")
?.addEventListener("click", AniWorld.QueueApi.clearCompleted);
document
.getElementById("clear-failed-btn")
?.addEventListener("click", AniWorld.QueueApi.clearFailed);
});
```
---
### Task 8: Update HTML Templates
**Objective**: Update templates to load the new modular JavaScript files.
**Steps**:
1. **Update index.html**:
- Add script tags for shared modules (in order)
- Add script tags for index-specific modules (in order)
- Keep main app.js as the last script
- Ensure correct load order (dependencies first)
```html
<!-- Shared Modules -->
<script src="/static/js/shared/constants.js"></script>
<script src="/static/js/shared/auth.js"></script>
<script src="/static/js/shared/api-client.js"></script>
<script src="/static/js/shared/websocket-client.js"></script>
<script src="/static/js/shared/theme.js"></script>
<script src="/static/js/shared/ui-utils.js"></script>
<!-- Index Page Modules -->
<script src="/static/js/index/series-manager.js"></script>
<script src="/static/js/index/search.js"></script>
<script src="/static/js/index/scan-manager.js"></script>
<script src="/static/js/index/config-manager.js"></script>
<script src="/static/js/index/selection.js"></script>
<!-- Main Entry Point -->
<script src="/static/js/app.js"></script>
```
2. **Update queue.html**:
- Add script tags for shared modules (in order)
- Add script tags for queue-specific modules (in order)
- Keep main queue.js as the last script
```html
<!-- Shared Modules -->
<script src="/static/js/shared/constants.js"></script>
<script src="/static/js/shared/auth.js"></script>
<script src="/static/js/shared/api-client.js"></script>
<script src="/static/js/shared/websocket-client.js"></script>
<script src="/static/js/shared/theme.js"></script>
<script src="/static/js/shared/ui-utils.js"></script>
<!-- Queue Page Modules -->
<script src="/static/js/queue/queue-api.js"></script>
<script src="/static/js/queue/queue-renderer.js"></script>
<script src="/static/js/queue/progress-handler.js"></script>
<!-- Main Entry Point -->
<script src="/static/js/queue.js"></script>
```
3. **Update login.html** (if applicable):
- Only include shared modules needed for login
- Likely just theme.js and minimal utilities
---
### Task 9: Verification and Testing
**Objective**: Ensure all functionality works after refactoring.
**Steps**:
1. **Start the server**:
```bash
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload
```
2. **Test Login Page**:
- [ ] Page loads with correct styling
- [ ] Dark/light mode toggle works
- [ ] Login form submits correctly
- [ ] Error messages display correctly
- [ ] Successful login redirects to index
3. **Test Index Page**:
- [ ] Page loads with correct styling
- [ ] Series list loads and displays
- [ ] Series filtering works
- [ ] Search functionality works
- [ ] Series selection works
- [ ] Episode selection works
- [ ] Add to queue works
- [ ] Scan library works
- [ ] Scan progress displays
- [ ] Config modal opens/closes
- [ ] Config saves correctly
- [ ] Dark/light mode toggle works
- [ ] Logout works
- [ ] WebSocket connection established
4. **Test Queue Page**:
- [ ] Page loads with correct styling
- [ ] Queue status loads
- [ ] Pending items display
- [ ] Active download displays
- [ ] Completed items display
- [ ] Failed items display
- [ ] Start download works
- [ ] Stop download works
- [ ] Remove from queue works
- [ ] Clear completed works
- [ ] Clear failed works
- [ ] Retry failed works
- [ ] Progress updates in real-time
- [ ] Dark/light mode toggle works
- [ ] WebSocket connection established
5. **Test Responsive Design**:
- [ ] All pages work on mobile viewport
- [ ] All pages work on tablet viewport
- [ ] All pages work on desktop viewport
6. **Browser Console Check**:
- [ ] No JavaScript errors in console
- [ ] No 404 errors for static files
- [ ] No CSS loading errors
---
### Task 10: Cleanup and Documentation
**Objective**: Finalize the refactoring with cleanup and documentation.
**Steps**:
1. **Remove backup files** (if any were created)
2. **Verify file sizes**:
- No file should exceed 500 lines
- If any file exceeds, split further
3. **Add file headers**:
- Add comment header to each new file explaining its purpose
```javascript
/**
* AniWorld - Series Manager Module
*
* Handles loading, filtering, and rendering of anime series
* on the index/library page.
*
* Dependencies: auth.js, api-client.js, ui-utils.js
*/
```
```css
/**
* AniWorld - Button Styles
*
* All button-related styles including variants,
* states, and sizes.
*/
```
4. **Update infrastructure.md** (if exists):
- Document new file structure
- Document module dependencies
5. **Commit changes**:
```bash
git add .
git commit -m "refactor: split CSS and JS into modular files (SRP)"
```
---
### Summary of New Files
**CSS Files (14 files)**:
- `css/styles.css` (entry point with imports)
- `css/base/variables.css`
- `css/base/reset.css`
- `css/base/typography.css`
- `css/components/buttons.css`
- `css/components/cards.css`
- `css/components/forms.css`
- `css/components/modals.css`
- `css/components/navigation.css`
- `css/components/progress.css`
- `css/components/notifications.css`
- `css/components/tables.css`
- `css/pages/login.css`
- `css/pages/index.css`
- `css/pages/queue.css`
- `css/utilities/animations.css`
- `css/utilities/responsive.css`
- `css/utilities/helpers.css`
**JavaScript Files (15 files)**:
- `js/app.js` (entry point for index)
- `js/queue.js` (entry point for queue)
- `js/shared/constants.js`
- `js/shared/auth.js`
- `js/shared/api-client.js`
- `js/shared/websocket-client.js`
- `js/shared/theme.js`
- `js/shared/ui-utils.js`
- `js/index/series-manager.js`
- `js/index/search.js`
- `js/index/scan-manager.js`
- `js/index/config-manager.js`
- `js/index/selection.js`
- `js/queue/queue-api.js`
- `js/queue/queue-renderer.js`
- `js/queue/progress-handler.js`
---
### Important Notes
1. **IIFE Pattern**: Use the IIFE (Immediately Invoked Function Expression) pattern with a global namespace (`AniWorld`) for browser compatibility without requiring a build step.
2. **No Build Tools Required**: This approach uses native CSS `@import` and multiple `<script>` tags, avoiding the need for bundlers like Webpack or Vite.
3. **Load Order Matters**: Scripts must be loaded in dependency order. Shared modules first, then page-specific modules, then the main entry point.
4. **Backward Compatibility**: All existing HTML element IDs and class names must be preserved. Only the JavaScript and CSS organization changes, not the API.
5. **Incremental Approach**: Complete one task fully before moving to the next. Verify functionality after each major step.
6. **Rollback Plan**: Keep the original files until all verification is complete. Only delete originals after confirming everything works.