6.8 KiB
6.8 KiB
Architecture Overview
This document describes the high-level architecture of the Immich mobile application.
Architecture Pattern
The app follows a layered architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────┐
│ UI Layer (Pages/Widgets) │
├─────────────────────────────────────────────────────────┤
│ State Management (Providers) │
├─────────────────────────────────────────────────────────┤
│ Services (Business Logic) │
├─────────────────────────────────────────────────────────┤
│ Repositories (Data Access) │
├─────────────────────────────────────────────────────────┤
│ Infrastructure (Database, API, Platform) │
└─────────────────────────────────────────────────────────┘
Layer Descriptions
1. UI Layer
- Pages: Full-screen views/routes (e.g., LoginPage, PhotosPage)
- Widgets: Reusable UI components (e.g., AssetGrid, AlbumCard)
- Responsible for rendering and user interaction
- Should contain minimal logic
2. State Management Layer
- Uses reactive state management pattern
- Providers: Expose state and actions to the UI
- Handle state changes and notify listeners
- Examples:
authProvider,assetProvider,albumProvider
3. Services Layer
- Contains business logic
- Orchestrates operations between repositories
- Examples:
AuthService: Login, logout, session managementBackupService: Photo upload logicAlbumService: Album CRUD operationsSearchService: Search functionality
4. Repository Layer
- Data access abstraction
- Two types:
- API Repositories: Server communication
- Local Repositories: Database access
- Examples:
AssetRepository,AlbumRepository,AuthApiRepository
5. Infrastructure Layer
- Database: Local data persistence (relational database)
- API Client: HTTP communication with server
- Platform APIs: Native device features (camera, gallery, notifications)
Data Flow
Read Operation Example (Loading Albums)
UI (AlbumsPage)
│
▼
Provider (albumProvider)
│
▼
Service (AlbumService.refreshRemoteAlbums)
│
├──► API Repository (fetch from server)
│
└──► Local Repository (cache to database)
│
▼
Provider updates state
│
▼
UI rebuilds with new data
Write Operation Example (Creating Album)
UI (CreateAlbumPage)
│
▼
Provider (albumProvider.createAlbum)
│
▼
Service (AlbumService.createAlbum)
│
├──► API Repository (POST to server)
│
└──► Local Repository (save to database)
│
▼
Provider updates state
│
▼
UI navigates to new album
Key Architectural Decisions
1. Offline-First Approach
- Assets are cached locally in the database
- App works offline with cached data
- Syncs with server when connection is available
2. Dual Asset States
Assets can exist in three states:
- Local Only: On device, not uploaded
- Remote Only: On server, not downloaded
- Merged: Exists both locally and on server
3. Background Processing
- Background backup runs independently
- Uses platform-specific background task APIs
- Maintains separate execution context
4. Reactive Updates
- WebSocket connection for real-time server updates
- Local changes propagate through state management
- UI automatically updates on state changes
Component Relationships
┌──────────────────────────────────────────────────────────────┐
│ App Entry │
│ - Initialize databases │
│ - Set up dependency injection │
│ - Configure routing │
└──────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Router/Navigation │
│ - Route definitions │
│ - Auth guards │
│ - Deep link handling │
└──────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Photos │ │ Search │ │ Library │
│ Tab │ │ Tab │ │ Tab │
└──────────┘ └──────────┘ └──────────┘
Dependency Injection
The app uses a dependency injection container to manage:
- Service instances
- Repository instances
- Database connections
- API client configuration
All dependencies are:
- Lazily initialized
- Scoped appropriately (singleton vs per-use)
- Easily mockable for testing
Error Handling Strategy
- API Errors: Caught at repository level, wrapped in custom exceptions
- Service Errors: Logged and propagated to UI
- UI Errors: Display user-friendly messages via toasts/dialogs
- Fatal Errors: Show error screen with recovery options