You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
8.3 KiB

# App Boilerplate
A modular, offline-first Flutter boilerplate for apps that store, sync, and share media and metadata across centralized (Immich, Firebase) and decentralized (Nostr) systems.
## Phase 5 - Relay Management UI
- User interface for managing Nostr relays
- View, add, remove, and monitor relay health
- Manual sync trigger integration
- Modular controller-based architecture
- Comprehensive UI tests
## Phase 4 - Sync Engine
- Coordinates data synchronization between local storage, Immich, and Nostr
- Conflict resolution strategies (useLocal, useRemote, useLatest, merge)
- Offline queue with automatic retry
- Priority-based operation processing
- Comprehensive unit and integration tests
## Phase 3 - Nostr Integration
- Nostr protocol service for decentralized metadata synchronization
- Keypair generation and event publishing
- Multi-relay support for metadata syncing
- Comprehensive unit tests
## Phase 2 - Immich Integration
- Immich API service for uploading and fetching images
- Automatic metadata storage in local database
- Offline-first behavior with local caching
- Comprehensive unit tests
## Phase 1 - Local Storage & Caching
- Local storage service with SQLite database
- CRUD operations for items
- Image caching functionality
- Comprehensive unit tests
## Quick Start
```bash
# Install dependencies
flutter pub get
# Run tests
flutter test
# Run app
flutter run
```
## Local Storage & Caching
Service for local storage and caching operations. Provides CRUD operations for items stored in SQLite, image caching with automatic download/storage, and cache hit/miss handling. Modular design with no UI dependencies.
**Files:**
- `lib/data/local/local_storage_service.dart` - Main service class
- `lib/data/local/models/item.dart` - Item data model
- `test/data/local/local_storage_service_test.dart` - Unit tests
**Key Methods:** `initialize()`, `insertItem()`, `getItem()`, `getAllItems()`, `updateItem()`, `deleteItem()`, `getCachedImage()`, `clearImageCache()`, `close()`
## Immich Integration
Service for interacting with Immich API. Uploads images, fetches asset lists, and automatically stores metadata in local database. Offline-first design allows access to cached metadata without network.
**Configuration:** Edit `lib/config/config_loader.dart` to set `immichBaseUrl` and `immichApiKey` for dev/prod environments (lines 40-41 for dev, lines 47-48 for prod).
**Files:**
- `lib/data/immich/immich_service.dart` - Main service class
- `lib/data/immich/models/immich_asset.dart` - Asset model
- `lib/data/immich/models/upload_response.dart` - Upload response model
- `test/data/immich/immich_service_test.dart` - Unit tests
**Key Methods:** `uploadImage()`, `fetchAssets()`, `getCachedAsset()`, `getCachedAssets()`
## Nostr Integration
Service for decentralized metadata synchronization using Nostr protocol. Generates keypairs, publishes events, and syncs metadata across multiple relays. Modular design allows testing without real relay connections.
**Files:**
- `lib/data/nostr/nostr_service.dart` - Main service class
- `lib/data/nostr/models/nostr_keypair.dart` - Keypair model
- `lib/data/nostr/models/nostr_event.dart` - Event model
- `lib/data/nostr/models/nostr_relay.dart` - Relay model
- `test/data/nostr/nostr_service_test.dart` - Unit tests
**Key Methods:** `generateKeyPair()`, `addRelay()`, `connectRelay()`, `publishEvent()`, `syncMetadata()`, `dispose()`
## Sync Engine
Engine for coordinating data synchronization between local storage, Immich, and Nostr. Handles conflict resolution, offline queuing, and automatic retries. Processes operations by priority with configurable conflict resolution strategies.
**Files:**
- `lib/data/sync/sync_engine.dart` - Main sync engine class
- `lib/data/sync/models/sync_status.dart` - Status and priority enums
- `lib/data/sync/models/sync_operation.dart` - Operation model
- `test/data/sync/sync_engine_test.dart` - Unit and integration tests
**Key Methods:** `syncToImmich()`, `syncFromImmich()`, `syncToNostr()`, `syncAll()`, `queueOperation()`, `resolveConflict()`, `getPendingOperations()`
**Conflict Resolution:** `useLocal`, `useRemote`, `useLatest`, `merge` - set via `setConflictResolution()`
## Relay Management UI
User interface for managing Nostr relays. View configured relays, add/remove relays, monitor connection health, and trigger manual syncs. Modular design with controller-based state management for testability.
**Files:**
- `lib/ui/relay_management/relay_management_screen.dart` - Main UI screen
- `lib/ui/relay_management/relay_management_controller.dart` - State management controller
- `test/ui/relay_management/relay_management_screen_test.dart` - UI tests
- `test/ui/relay_management/relay_management_controller_test.dart` - Controller tests
**Key Features:** Add/remove relays, connect/disconnect, health monitoring, manual sync trigger, error handling
**Usage:** Navigate to "Manage Relays" from the main screen after initialization.
## Configuration
**Configuration uses `.env` files for sensitive values (API keys, URLs) with fallback defaults in `lib/config/config_loader.dart`.**
### Setup .env File
1. Copy `.env.example` to `.env` in the project root:
```bash
cp .env.example .env
```
2. Edit `.env` and fill in your actual values:
- `IMMICH_BASE_URL` - Your Immich server URL
- `IMMICH_API_KEY_DEV` - Your development Immich API key
- `IMMICH_API_KEY_PROD` - Your production Immich API key
- `NOSTR_RELAYS_DEV` - Comma-separated Nostr relay URLs for dev
- `NOSTR_RELAYS_PROD` - Comma-separated Nostr relay URLs for prod
- Other configuration values as needed
**Important:** The `.env` file is in `.gitignore` and should never be committed to version control. Only commit `.env.example` as a template.
### Environment Variables
The app uses:
- **`.env` file** (recommended) - Loaded at runtime, falls back to defaults if not found
- **`--dart-define`** - For environment selection:
```bash
# Set environment at runtime
flutter run --dart-define=ENV=prod
```
If `.env` file is not found or variables are missing, the app uses default values from `lib/config/config_loader.dart`.
### Available Environments
- `dev` - Development (default): Logging enabled, dev API URL
- `prod` - Production: Logging disabled, production API URL
## Running the App
### Android Emulator
**Important:** Wait for emulator to fully boot (30-60 seconds on cold boot).
1. Start emulator from Android Studio AVD Manager
2. Wait for boot animation to complete and home screen appears
3. Run: `flutter run`
### iOS Simulator (macOS)
```bash
open -a Simulator
flutter run
```
## Running Tests
```bash
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
```
**Important:** Tests must be run separately - `flutter run` does not execute tests.
## Project Structure
```
lib/
├── config/
│ ├── app_config.dart
│ └── config_loader.dart
├── data/
│ ├── local/
│ │ ├── local_storage_service.dart
│ │ └── models/
│ │ └── item.dart
│ ├── immich/
│ │ ├── immich_service.dart
│ │ └── models/
│ │ ├── immich_asset.dart
│ │ └── upload_response.dart
│ ├── nostr/
│ │ ├── nostr_service.dart
│ │ └── models/
│ │ ├── nostr_keypair.dart
│ │ ├── nostr_event.dart
│ │ └── nostr_relay.dart
│ └── sync/
│ ├── sync_engine.dart
│ └── models/
│ ├── sync_status.dart
│ └── sync_operation.dart
├── ui/
│ └── relay_management/
│ ├── relay_management_screen.dart
│ └── relay_management_controller.dart
└── main.dart
test/
├── config/
│ └── config_loader_test.dart
└── data/
├── local/
│ └── local_storage_service_test.dart
├── immich/
│ └── immich_service_test.dart
├── nostr/
│ └── nostr_service_test.dart
├── sync/
│ └── sync_engine_test.dart
└── ui/
└── relay_management/
├── relay_management_screen_test.dart
└── relay_management_controller_test.dart
```

Powered by TurnKey Linux.