# Application Architecture **Referenced Files in This Document** - [SuvMusicApplication.kt](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt) - [AppModule.kt](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt) - [RepositoryModule.kt](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/di/RepositoryModule.kt) - [LibraryRepository.kt](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt) - [LibraryRepositoryImpl.kt](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt) - [YouTubeRepository.kt](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt) - [MainViewModel.kt](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt) - [HomeScreen.kt](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt) - [Theme.kt](file://app/src/main/java/com/suvojeet/suvmusic/ui/theme/Theme.kt) - [Song.kt](file://core/model/src/main/java/com/suvojeet/suvmusic/core/model/Song.kt) - [AppLog.kt](file://app/src/main/java/com/suvojeet/suvmusic/util/AppLog.kt) - [AppDatabase.kt](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/local/AppDatabase.kt) - [build.gradle.kts](file://app/build.gradle.kts) - [settings.gradle.kts](file://settings.gradle.kts) ## Table of Contents 1. [Introduction](#introduction) 2. [Project Structure](#project-structure) 3. [Core Components](#core-components) 4. [Architecture Overview](#architecture-overview) 5. [Detailed Component Analysis](#detailed-component-analysis) 6. [Dependency Analysis](#dependency-analysis) 7. [Performance Considerations](#performance-considerations) 8. [Troubleshooting Guide](#troubleshooting-guide) 9. [Conclusion](#conclusion) 10. [Appendices](#appendices) ## Introduction This document describes the clean architecture implementation of SuvMusic, focusing on MVVM with Jetpack Compose, the repository pattern for data access, and dependency injection with Hilt. It explains how the application separates presentation, domain, and data layers, how modules integrate, and how cross-cutting concerns such as logging, error handling, and performance are addressed. The goal is to provide a clear understanding of the system’s design, data flows, and integration points for both technical and non-technical readers. ## Project Structure SuvMusic follows a multi-module Gradle structure with a clear separation of concerns: - app: The Android application module containing UI (Jetpack Compose), ViewModels, services, workers, and DI configuration. - core modules: - core:model: Shared domain models and enums. - core:domain: Domain interfaces and abstractions (e.g., repositories). - core:data: Data implementations, Room database, DAOs, and repository implementations. - Feature modules: - scrobbler: Last.fm scrobbling integration. - updater: Update checking and downloading. - media-source: Shared lyrics provider interfaces. - lyric-*: Concrete lyrics providers. - extractor: NewPipe extraction integration. ```mermaid graph TB subgraph "App Module" APP_UI["UI (Compose)
ViewModels"] APP_DI["DI Modules
AppModule.kt"] end subgraph "Core Domain" CORE_DOMAIN["Interfaces
LibraryRepository.kt"] end subgraph "Core Data" CORE_DATA_IMPL["Repository Implementation
LibraryRepositoryImpl.kt"] ROOM_DB["Room Database
AppDatabase.kt"] end subgraph "Feature Modules" YT_REPO["YouTubeRepository.kt"] SCROBBLER["scrobbler"] UPDATER["updater"] LYRIC_SIMP["lyric-simpmusic"] LYRIC_LRCLIB["lyric-lrclib"] LYRIC_KUGOU["lyric-kugou"] MEDIA_SOURCE["media-source"] EXTRACTOR["extractor"] end APP_UI --> APP_DI APP_DI --> CORE_DOMAIN CORE_DOMAIN --> CORE_DATA_IMPL CORE_DATA_IMPL --> ROOM_DB APP_UI --> YT_REPO APP_UI --> SCROBBLER APP_UI --> UPDATER APP_UI --> LYRIC_SIMP APP_UI --> LYRIC_LRCLIB APP_UI --> LYRIC_KUGOU APP_UI --> MEDIA_SOURCE APP_UI --> EXTRACTOR ``` **Diagram sources** - [settings.gradle.kts:18-30](file://settings.gradle.kts#L18-L30) - [build.gradle.kts:254-265](file://app/build.gradle.kts#L254-L265) - [AppModule.kt:21-167](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt#L21-L167) - [RepositoryModule.kt:10-18](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/di/RepositoryModule.kt#L10-L18) - [LibraryRepository.kt:11-36](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt#L11-L36) - [LibraryRepositoryImpl.kt:19-252](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt#L19-L252) - [AppDatabase.kt:16-36](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/local/AppDatabase.kt#L16-L36) - [YouTubeRepository.kt:47-90](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L47-L90) **Section sources** - [settings.gradle.kts:18-30](file://settings.gradle.kts#L18-L30) - [build.gradle.kts:14-110](file://app/build.gradle.kts#L14-L110) ## Core Components - Presentation Layer (MVVM with Jetpack Compose): - ViewModels manage UI state and orchestrate interactions with repositories and services. - Composables consume StateFlow/SharedFlow from ViewModels and render UI. - Domain Layer: - Defines repository interfaces and domain models. - Data Layer: - Implements repositories and provides data sources (network, local Room DB, external libraries). - DI with Hilt: - Centralized provision of singletons and scoped instances across modules. - Cross-Cutting Concerns: - Logging via AppLog, crash reporting via ACRA, caching and image loading via Coil, and WorkManager for background tasks. **Section sources** - [MainViewModel.kt:35-149](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt#L35-L149) - [HomeScreen.kt:84-637](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L84-L637) - [LibraryRepository.kt:11-36](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt#L11-L36) - [LibraryRepositoryImpl.kt:19-252](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt#L19-L252) - [YouTubeRepository.kt:47-90](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L47-L90) - [AppLog.kt:17-113](file://app/src/main/java/com/suvojeet/suvmusic/util/AppLog.kt#L17-L113) - [SuvMusicApplication.kt:31-129](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt#L31-L129) ## Architecture Overview SuvMusic implements a layered clean architecture: - Presentation: Composables and ViewModels expose StateFlow/SharedFlow to UI and react to events. - Domain: Interfaces define capabilities (e.g., LibraryRepository). - Data: Implementations provide concrete behavior (e.g., LibraryRepositoryImpl) and coordinate network/local sources. - Infrastructure: Hilt provides DI, Room persists data, OkHttp handles networking, Coil manages images, WorkManager schedules tasks. ```mermaid graph TB UI["Composable UI
HomeScreen.kt"] --> VM["ViewModel
MainViewModel.kt"] VM --> REPO["Domain Repository Interface
LibraryRepository.kt"] REPO --> IMPL["Data Repository Implementation
LibraryRepositoryImpl.kt"] IMPL --> DB["Room Database
AppDatabase.kt"] VM --> YT["YouTubeRepository.kt"] VM --> LOG["AppLog.kt"] APP["SuvMusicApplication.kt"] --> DI["Hilt DI
AppModule.kt"] ``` **Diagram sources** - [HomeScreen.kt:84-150](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L84-L150) - [MainViewModel.kt:35-77](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt#L35-L77) - [LibraryRepository.kt:11-36](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt#L11-L36) - [LibraryRepositoryImpl.kt:19-252](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt#L19-L252) - [AppDatabase.kt:16-36](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/local/AppDatabase.kt#L16-L36) - [YouTubeRepository.kt:47-90](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L47-L90) - [AppLog.kt:17-113](file://app/src/main/java/com/suvojeet/suvmusic/util/AppLog.kt#L17-L113) - [SuvMusicApplication.kt:31-129](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt#L31-L129) - [AppModule.kt:21-167](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt#L21-L167) ## Detailed Component Analysis ### MVVM with Jetpack Compose - ViewModels encapsulate UI state and side effects, exposing StateFlow and SharedFlow to Compose. - Composables observe state and collect events, reacting to user actions and repository updates. - Example: MainViewModel initializes cache cleanup and exposes events for deep links and audio intents. ```mermaid sequenceDiagram participant UI as "Composable
HomeScreen.kt" participant VM as "ViewModel
MainViewModel.kt" participant REPO as "Repository
YouTubeRepository.kt" participant LOG as "AppLog.kt" UI->>VM : "Collect uiState/events" VM->>LOG : "Initialize logging" VM->>REPO : "Fetch data / handle events" REPO-->>VM : "Result / Flow emissions" VM-->>UI : "State updates" ``` **Diagram sources** - [HomeScreen.kt:84-150](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L84-L150) - [MainViewModel.kt:35-149](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt#L35-L149) - [YouTubeRepository.kt:239-242](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L239-L242) - [AppLog.kt:28-41](file://app/src/main/java/com/suvojeet/suvmusic/util/AppLog.kt#L28-L41) **Section sources** - [MainViewModel.kt:35-149](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt#L35-L149) - [HomeScreen.kt:84-150](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L84-L150) ### Repository Pattern - Domain interface defines library operations (e.g., playlist CRUD, saved items). - Data implementation performs mapping between domain models and entities, coordinates DAOs, and applies transformations. - Example: LibraryRepositoryImpl maps PlaylistSongEntity to Song and vice versa, exposes Flow-based queries, and persists data via Room. ```mermaid classDiagram class LibraryRepository { +savePlaylist(playlist) +getCachedPlaylistSongs(playlistId) +getCachedPlaylistSongsFlow(playlistId) +getSavedPlaylists() +getSavedAlbums() +getSavedArtists() } class LibraryRepositoryImpl { -libraryDao : LibraryDao +savePlaylist(playlist) +getCachedPlaylistSongs(playlistId) +getCachedPlaylistSongsFlow(playlistId) +getSavedPlaylists() +getSavedAlbums() +getSavedArtists() } LibraryRepository <|.. LibraryRepositoryImpl : "implements" ``` **Diagram sources** - [LibraryRepository.kt:11-36](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt#L11-L36) - [LibraryRepositoryImpl.kt:19-252](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt#L19-L252) **Section sources** - [LibraryRepository.kt:11-36](file://core/domain/src/main/java/com/suvojeet/suvmusic/core/domain/repository/LibraryRepository.kt#L11-L36) - [LibraryRepositoryImpl.kt:19-252](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/repository/LibraryRepositoryImpl.kt#L19-L252) ### Dependency Injection with Hilt - Hilt provides singletons and scoped instances across modules. - AppModule wires repositories, OkHttp clients, Gson, MusicPlayer, and other services. - RepositoryModule binds the concrete implementation to the domain interface. ```mermaid classDiagram class AppModule { +provideSessionManager() +provideYouTubeRepository(...) +provideLocalAudioRepository() +provideOkHttpClient() +provideGson() +provideJioSaavnRepository(...) +provideMusicPlayer(...) +provideLyricsRepository(...) +provideListenTogetherClient() +provideListenTogetherManager(...) +provideWorkManager() } class RepositoryModule { +bindLibraryRepository(impl) } AppModule --> YouTubeRepository : "provides" AppModule --> LibraryRepositoryImpl : "provides" RepositoryModule --> LibraryRepository : "binds" ``` **Diagram sources** - [AppModule.kt:21-167](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt#L21-L167) - [RepositoryModule.kt:10-18](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/di/RepositoryModule.kt#L10-L18) **Section sources** - [AppModule.kt:21-167](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt#L21-L167) - [RepositoryModule.kt:10-18](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/di/RepositoryModule.kt#L10-L18) ### Data Access and Domain Models - Domain model Song encapsulates fields for YouTube, local, and JioSaavn sources. - YouTubeRepository orchestrates search, streaming, and browsing using NewPipe and internal APIs. - AppDatabase defines Room entities and DAOs for library, history, genres, and dislikes. ```mermaid flowchart TD Start(["Repository Call"]) --> CheckNet["Check Network Connectivity"] CheckNet --> |Connected| UseRemote["Use Remote API / Extractor"] CheckNet --> |Offline| UseLocal["Use Local Cache / Room"] UseRemote --> Transform["Map to Domain Model"] UseLocal --> Transform Transform --> Persist["Persist via DAO / Cache"] Persist --> Return(["Return Result"]) ``` **Diagram sources** - [YouTubeRepository.kt:239-242](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L239-L242) - [Song.kt:9-117](file://core/model/src/main/java/com/suvojeet/suvmusic/core/model/Song.kt#L9-L117) - [AppDatabase.kt:16-36](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/local/AppDatabase.kt#L16-L36) **Section sources** - [Song.kt:9-117](file://core/model/src/main/java/com/suvojeet/suvmusic/core/model/Song.kt#L9-L117) - [YouTubeRepository.kt:239-242](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L239-L242) - [AppDatabase.kt:16-36](file://core/data/src/main/java/com/suvojeet/suvmusic/core/data/local/AppDatabase.kt#L16-L36) ### UI Theming and Composition - Theme.kt defines color schemes, animations, and dynamic color integration. - Composables observe session-managed flows to adapt UI behavior (e.g., animated backgrounds). ```mermaid sequenceDiagram participant UI as "HomeScreen.kt" participant THEME as "Theme.kt" participant SESSION as "SessionManager" UI->>SESSION : "Read dynamic colors flag" UI->>THEME : "Render SuvMusicTheme(...)" THEME-->>UI : "Apply color scheme / animations" ``` **Diagram sources** - [HomeScreen.kt:151-167](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L151-L167) - [Theme.kt:207-306](file://app/src/main/java/com/suvojeet/suvmusic/ui/theme/Theme.kt#L207-L306) **Section sources** - [Theme.kt:207-306](file://app/src/main/java/com/suvojeet/suvmusic/ui/theme/Theme.kt#L207-L306) - [HomeScreen.kt:151-167](file://app/src/main/java/com/suvojeet/suvmusic/ui/screens/HomeScreen.kt#L151-L167) ## Dependency Analysis - Module dependencies: - app depends on core modules and feature modules via implementation(project(...)). - DI modules are centralized in app and bind core interfaces to implementations. - External dependencies: - Compose, Media3, Room, Hilt, Coil, WorkManager, OkHttp, Retrofit, Ktor, Jsoup, Protobuf, and more. ```mermaid graph LR APP["app"] --> CORE_MODEL["core:model"] APP --> CORE_DOMAIN["core:domain"] APP --> CORE_DATA["core:data"] APP --> SCROBBLER["scrobbler"] APP --> UPDATER["updater"] APP --> LYRIC_SIMP["lyric-simpmusic"] APP --> LYRIC_LRCLIB["lyric-lrclib"] APP --> LYRIC_KUGOU["lyric-kugou"] APP --> MEDIA_SOURCE["media-source"] APP --> EXTRACTOR["extractor"] ``` **Diagram sources** - [build.gradle.kts:254-265](file://app/build.gradle.kts#L254-L265) - [settings.gradle.kts:18-30](file://settings.gradle.kts#L18-L30) **Section sources** - [build.gradle.kts:140-265](file://app/build.gradle.kts#L140-L265) - [settings.gradle.kts:18-30](file://settings.gradle.kts#L18-L30) ## Performance Considerations - Image caching and memory tuning: - Coil configured with memory and disk caches, crossfade, and debug logging in debug builds. - Network timeouts and connection pooling: - OkHttp clients configured with explicit timeouts and pooled connections. - Background scheduling: - WorkManager periodic work with constraints for connectivity. - UI responsiveness: - Compose animations and state hoisting minimize recompositions. - Resource optimization: - ABI filters and resource configurations limit APK size. **Section sources** - [SuvMusicApplication.kt:89-109](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt#L89-L109) - [AppModule.kt:59-66](file://app/src/main/java/com/suvojeet/suvmusic/di/AppModule.kt#L59-L66) - [SuvMusicApplication.kt:111-127](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt#L111-L127) - [build.gradle.kts:27-34](file://app/build.gradle.kts#L27-L34) ## Troubleshooting Guide - Logging: - AppLog supports runtime toggling and writes to a persistent file when enabled. - Crash reporting: - ACRA initialized in Application with notification and logcat capture. - Error handling patterns: - ViewModels collect events and emit UI-visible messages. - Repository methods return empty lists or null when offline or on exceptions. **Section sources** - [AppLog.kt:28-113](file://app/src/main/java/com/suvojeet/suvmusic/util/AppLog.kt#L28-L113) - [SuvMusicApplication.kt:40-61](file://app/src/main/java/com/suvojeet/suvmusic/SuvMusicApplication.kt#L40-L61) - [MainViewModel.kt:79-118](file://app/src/main/java/com/suvojeet/suvmusic/ui/viewmodel/MainViewModel.kt#L79-L118) - [YouTubeRepository.kt:133-175](file://app/src/main/java/com/suvojeet/suvmusic/data/repository/YouTubeRepository.kt#L133-L175) ## Conclusion SuvMusic’s architecture cleanly separates concerns across presentation, domain, and data layers, with DI via Hilt ensuring modularity and testability. The MVVM + Jetpack Compose UI is reactive and efficient, while the repository pattern centralizes data access and enables pluggable providers. Cross-cutting concerns like logging, crash reporting, and caching are integrated thoughtfully. The modular Gradle setup and Room persistence provide scalability and maintainability. ## Appendices ### System Context and Module Relationships - System boundary: app module orchestrates UI, DI, and integrations; core modules define shared contracts and implementations; feature modules encapsulate domain-specific integrations. - Integration patterns: - YouTubeRepository integrates NewPipe and internal APIs. - Lyric providers are pluggable modules. - Scrobbler and Updater are separate modules wired via DI. ```mermaid graph TB subgraph "External Systems" YT_API["YouTube Internal API"] NEWPIPE["NewPipe Extractor"] LYRIC_PROVIDERS["Lyric Providers"] LASTFM["Last.fm API"] end APP["app"] --> YT_API APP --> NEWPIPE APP --> LYRIC_PROVIDERS APP --> LASTFM ``` [No sources needed since this diagram shows conceptual relationships]