-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture
T0mii edited this page Dec 30, 2025
·
3 revisions
Nebula adopts a Clean Architecture Lite approach to ensure scalability, testability, and separation of concerns.
We enforce a strict unidirectional flow of dependency: presentation -> domain <- data.
-
domain/(The Core)- Role: Defines what the app does (Business Logic).
- Rules: Pure Dart code. NO Flutter, NO external implementation frameworks (Supabase, Firebase, Audio plugins).
-
Contents:
-
Entities: Pure models (e.g.,
Track). -
Repositories (Interfaces): Contracts defining data operations (e.g.,
PlayerRepository).
-
Entities: Pure models (e.g.,
-
data/(The Implementation)- Role: Defines how things are done.
- Rules: Implements Domain interfaces. Handles external libraries (APIs, Databases, Device Hardware).
-
Contents:
-
Repositories (Impl): Implementations of domain contracts (e.g.,
PlayerRepositoryImpl). -
Data Sources: Direct API connectors or Service Wrappers (e.g.,
NebulaAudioHandler).
-
Repositories (Impl): Implementations of domain contracts (e.g.,
-
presentation/(The UI)- Role: Displays state and captures user input.
- Rules: Depends ONLY on Domain. Never talks directly to Data sources.
-
Contents:
-
Controllers/Blocs: State management (e.g.,
PlayerController). - Screens/Widgets: Flutter UI components.
-
Controllers/Blocs: State management (e.g.,
The music player is the heart of Nebula, designed to work flawlessly in the background.
-
Architecture Flow:
UI (Buttons)->PlayerController->PlayerRepository->NebulaAudioHandler->AudioService->JustAudio->OS System APIs -
Key Components:
-
NebulaAudioHandler(data):- Extends
BaseAudioHandlerfromaudio_service. - It is a Singleton service that runs in a separate isolate (conceptually) to keep the OS informed about playback.
- Manages the notification (MediaStyle) and lock-screen controls.
- Wraps
just_audiofor actual playback.
- Extends
-
PlayerRepository(domain):- The clean interface that the App uses.
- Abstracts away the complex
AudioServicestreams into simple domain streams (currentTrack,isPlaying,position). -
Queue Management: Handles logical queue operations like
setQueue(ordered playback) andshuffleQueue(randomized).
-
To enable background playback on modern Android (14+), we utilize:
-
FOREGROUND_SERVICE&FOREGROUND_SERVICE_MEDIA_PLAYBACK. -
WAKE_LOCKto keep the CPU running while screen is off. -
AudioServiceActivity in
AndroidManifest.xmlto correctly bind the Flutter Engine to the media service.
Nebula is designed to work offline.
- Hive: Used for storing local data like Playlists, Favorites, and Search History. It's fast, NoSQL, and minimal.
- Dio: Handles file downloads with resilience (pausing/resuming support).
- Offline Mode: The repository layer automatically switches between Remote sources (YouTube) and Local files based on availability.
We follow a feature-first organization inside lib/features/:
-
auth: Supabase authentication logic. -
player: Playback logic and audio handler. -
downloads: Management of offline content. -
library: User's local music collection. -
settings: App configuration.