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.
 
 
 
 
gitea 120a04c69f
nostr login fetch details and nip05
2 months ago
android phase 0 2 months ago
coverage Phase 5 - Relay Management UI complete 2 months ago
lib nostr login fetch details and nip05 2 months ago
macos some fixes 2 months ago
test nostr login fetch details and nip05 2 months ago
.env.example Phase 7 - Added Firebase layer 2 months ago
.gitignore Phase 4 - synch engine complete 2 months ago
.metadata phase 0 2 months ago
README.md nostr images fetching from API 2 months ago
pubspec.lock nostr tools added 2 months ago
pubspec.yaml nostr tools added 2 months ago

README.md

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 8 - Navigation & UI Scaffold

  • Complete navigation structure connecting all main modules
  • Bottom navigation bar with 5 main screens: Home, Immich, Nostr Events, Session, Settings
  • Route guards requiring authentication for protected screens
  • Placeholder screens for all modules ready for custom UI implementation
  • Modular navigation architecture with testable components
  • Comprehensive UI tests for navigation and route guards

Phase 7 - Firebase Layer

  • Optional Firebase integration for cloud sync, storage, auth, push notifications, and analytics
  • Modular design - can be enabled or disabled without affecting other modules
  • Offline-first behavior maintained when Firebase is disabled
  • Integration with session management and local storage
  • Comprehensive unit tests

Phase 6 - User Session Management

  • User login, logout, and session switching
  • Per-user data isolation with separate storage paths
  • Cache clearing on logout
  • Integration with local storage and sync engine
  • Comprehensive unit tests

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

# 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.

User Session Management

Service for managing user sessions, login, logout, and session isolation. Provides per-user data isolation with separate storage paths and cache directories. Clears cached data on logout and integrates with local storage and sync engine.

Files:

  • lib/data/session/session_service.dart - Main session management service
  • lib/data/session/models/user.dart - User model
  • test/data/session/session_service_test.dart - Unit tests

Key Methods: login(), logout(), switchSession(), getCurrentUserDbPath(), getCurrentUserCacheDir()

Features: Per-user storage isolation, cache clearing on logout, session switching with data preservation, integration with local storage

Usage: Initialize SessionService with LocalStorageService and optional SyncEngine. Call login() to start a session, logout() to end it, and switchSession() to change users.

Firebase Layer

Optional Firebase integration providing cloud sync, storage, authentication, push notifications, and analytics. Fully modular - can be enabled or disabled without affecting offline-first functionality. Integrates with local storage and session management to maintain offline-first behavior.

Files:

  • lib/data/firebase/firebase_service.dart - Main Firebase service
  • lib/data/firebase/models/firebase_config.dart - Firebase configuration model
  • test/data/firebase/firebase_service_test.dart - Unit tests

Key Methods: initialize(), loginWithEmailPassword(), logout(), syncItemsToFirestore(), syncItemsFromFirestore(), uploadFile(), getFcmToken(), logEvent()

Features: Firestore cloud sync, Firebase Storage for media, Firebase Auth for authentication, Firebase Cloud Messaging for push notifications, Firebase Analytics for analytics, all optional and modular

Usage: Create FirebaseService with FirebaseConfig (disabled by default). Pass to SessionService for automatic sync on login/logout. Initialize Firebase with initialize() before use. All services gracefully handle being disabled.

Note: Firebase requires actual Firebase project setup with google-services.json (Android) and GoogleService-Info.plist (iOS) configuration files. The service handles missing configuration gracefully and maintains offline-first behavior.

Navigation & UI Scaffold

Complete navigation structure connecting all main modules with bottom navigation bar. Includes route guards for protected screens and placeholder screens ready for custom UI implementation.

Files:

  • lib/ui/navigation/main_navigation_scaffold.dart - Main navigation scaffold with bottom nav
  • lib/ui/navigation/app_router.dart - Router with route guards and route generation
  • lib/ui/home/home_screen.dart - Home screen (local storage items)
  • lib/ui/immich/immich_screen.dart - Immich media screen (placeholder)
  • lib/ui/nostr_events/nostr_events_screen.dart - Nostr events screen (placeholder)
  • lib/ui/session/session_screen.dart - Session management (login/logout)
  • lib/ui/settings/settings_screen.dart - Settings screen
  • test/ui/navigation/main_navigation_scaffold_test.dart - Navigation tests

Navigation Structure:

  • Home - Local storage and cached content (no auth required)
  • Immich - Immich media integration (requires login)
  • Nostr Events - Nostr events display (requires login)
  • Session - User login/logout (no auth required)
  • Settings - App settings and Relay Management access (no auth required)

Route Guards: Immich and Nostr Events screens require authentication. Unauthenticated users see a login prompt with option to navigate to Session screen.

Usage: The app automatically uses MainNavigationScaffold after initialization. All services are passed to the scaffold for dependency injection. Customize placeholder screens by editing the respective screen files in lib/ui/.

Running UI Tests:

flutter test test/ui/navigation/main_navigation_scaffold_test.dart

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:

    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:
# 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)

open -a Simulator
flutter run

Running Tests

# 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
 │    ├── session/
 │    │    ├── session_service.dart
 │    │    └── models/
 │    │         └── user.dart
 │    ├── firebase/
 │    │    ├── firebase_service.dart
 │    │    └── models/
 │    │         └── firebase_config.dart
 │    └── sync/
 │         ├── sync_engine.dart
 │         └── models/
 │              ├── sync_status.dart
 │              └── sync_operation.dart
 ├── ui/
 │    ├── navigation/
 │    │    ├── main_navigation_scaffold.dart
 │    │    └── app_router.dart
 │    ├── home/
 │    │    └── home_screen.dart
 │    ├── immich/
 │    │    └── immich_screen.dart
 │    ├── nostr_events/
 │    │    └── nostr_events_screen.dart
 │    ├── session/
 │    │    └── session_screen.dart
 │    ├── settings/
 │    │    └── settings_screen.dart
 │    └── 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
      ├── session/
      │    └── session_service_test.dart
      ├── firebase/
      │    └── firebase_service_test.dart
      ├── sync/
      │    └── sync_engine_test.dart
      └── ui/
           ├── navigation/
           │    └── main_navigation_scaffold_test.dart
           └── relay_management/
                ├── relay_management_screen_test.dart
                └── relay_management_controller_test.dart

Powered by TurnKey Linux.