Files
subtracks/app/src/main/kotlin/com/subtracks/di/AppModule.kt
T

169 lines
7.2 KiB
Kotlin

package com.subtracks.di
import android.content.Context
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import com.subtracks.R
import com.subtracks.UiMessage
import com.subtracks.data.db.createAndroidDatabase
import com.subtracks.data.download.ArtworkFetcher
import com.subtracks.data.download.ArtworkStore
import com.subtracks.data.download.DownloadEngine
import com.subtracks.data.download.DownloadNotifier
import com.subtracks.data.download.OkHttpArtworkFetcher
import com.subtracks.data.download.SystemDownloadEngine
import com.subtracks.data.net.networkAvailable
import com.subtracks.data.net.networkMode
import com.subtracks.data.prefs.UserPreferences
import com.subtracks.data.prefs.createUserPreferences
import com.subtracks.data.repo.ArtworkSeedRepository
import com.subtracks.data.repo.ArtworkSeedStore
import com.subtracks.data.repo.DownloadRepository
import com.subtracks.data.repo.LibraryRepository
import com.subtracks.data.repo.NetworkServerActionSink
import com.subtracks.data.repo.PendingServerActionSink
import com.subtracks.data.repo.QueueRepository
import com.subtracks.data.repo.SourceRepository
import com.subtracks.data.source.ServerActionSink
import com.subtracks.data.sync.AutoSync
import com.subtracks.data.sync.SyncManager
import com.subtracks.data.sync.SyncNotifier
import com.subtracks.log.Log
import com.subtracks.playback.MediaSessionConnection
import com.subtracks.playback.PlaybackController
import com.subtracks.playback.PlayerConnection
import com.subtracks.playback.Scrobbler
import com.subtracks.ui.NowPlayingLauncher
import com.subtracks.ui.RootViewModel
import com.subtracks.ui.downloads.DownloadsViewModel
import com.subtracks.ui.home.HomeListViewModel
import com.subtracks.ui.home.HomeViewModel
import com.subtracks.ui.library.AlbumDetailViewModel
import com.subtracks.ui.library.ArtistDetailViewModel
import com.subtracks.ui.library.LibraryViewModel
import com.subtracks.ui.library.PlaylistDetailViewModel
import com.subtracks.ui.playback.QueueViewModel
import com.subtracks.ui.search.SearchViewModel
import com.subtracks.ui.settings.AddSourceViewModel
import com.subtracks.ui.settings.SettingsViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import okhttp3.OkHttpClient
import org.koin.core.module.dsl.viewModel
import org.koin.core.qualifier.named
import org.koin.dsl.module
import java.io.File
fun appModule(
context: Context,
http: OkHttpClient,
) = module {
val mainHandler = Handler(Looper.getMainLooper())
val toast: (UiMessage) -> Unit = { message ->
mainHandler.post { Toast.makeText(context, message.resolve(context), Toast.LENGTH_SHORT).show() }
}
single { createAndroidDatabase(context) }
single { http }
single { createUserPreferences(context) }
single { CoroutineScope(SupervisorJob() + Dispatchers.Default) }
single(named("io")) { CoroutineScope(SupervisorJob() + Dispatchers.IO) }
single(named("playback")) { CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) }
single(createdAtStart = true) { get<UserPreferences>().verboseLogging().onEach(Log::setVerbose).launchIn(get()) }
single {
SourceRepository(
get(),
get(),
get(),
get(),
networkMode = networkMode(context.applicationContext),
showMessage = toast,
scope = get(),
)
}
single<ServerActionSink> {
PendingServerActionSink(
delegate = NetworkServerActionSink(get()),
db = get(),
activeSourceId = get<SourceRepository>()::activeSourceIdOnce,
offline = get<SourceRepository>().offline,
offlinePreferences = get<UserPreferences>().offlineMode(),
networkAvailable = networkAvailable(context.applicationContext),
scope = get(),
)
}
single { LibraryRepository(get(), get(), get(), get(), get(), toast, scope = get(named("io"))) }
single<ArtworkSeedStore> { ArtworkSeedRepository(get()) }
single { SyncManager(get(), get(), get(), get(), preferences = get(), showMessage = toast, scope = get()) }
single {
AutoSync(
preferences = get(),
networkMode = networkMode(context.applicationContext),
hasSource = { get<SourceRepository>().activeSourceIdOnce() != null },
requestSync = { get<SyncManager>().requestSync(silent = true) },
scope = get(),
)
}
single { QueueRepository(get()) }
single { ArtworkStore(downloadsRoot(context)) }
single<ArtworkFetcher> { OkHttpArtworkFetcher(get()) }
single<DownloadEngine> { SystemDownloadEngine(context.applicationContext) }
single {
DownloadRepository(
db = get(),
sourceRepository = get(),
engine = get(),
downloadsDir = downloadsRoot(context),
artworkStore = get(),
artworkFetcher = get(),
queueRepository = get(),
showMessage = toast,
dispatcher = Dispatchers.IO,
scope = get(named("io")),
).also { it.start() }
}
single(createdAtStart = true) { DownloadNotifier(context.applicationContext, get(), scope = get()).also { it.start() } }
single(createdAtStart = true) { SyncNotifier(context.applicationContext, get<SyncManager>().status, scope = get()).also { it.start() } }
single<PlayerConnection> { MediaSessionConnection(context.applicationContext, get(), get()) }
single { PlaybackController(get(), get(), get(), get(), get(), showMessage = toast, scope = get(named("playback"))) }
single(createdAtStart = true) {
val playback = get<PlaybackController>()
Scrobbler(
sink = get(),
enabled = get<UserPreferences>().scrobbling(),
scope = get(),
recordPlay = get<LibraryRepository>()::recordPlay,
).also {
it.attach(playback.state, playback.positionMs)
}
}
single { NowPlayingLauncher() }
viewModel { RootViewModel(get()) }
viewModel { LibraryViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { HomeViewModel(get(), get(), get(), get()) }
viewModel { params -> HomeListViewModel(get(), get(), get(), params.get()) }
viewModel { SearchViewModel(get(), get(), get()) }
viewModel { SettingsViewModel(get(), get()) }
viewModel {
DownloadsViewModel(
get(),
get(),
get(),
context.getString(R.string.unknown_artist),
context.getString(R.string.unknown_album),
)
}
viewModel { params -> AddSourceViewModel(get(), get(), get(), params.getOrNull(), context.resources) }
viewModel { params -> AlbumDetailViewModel(get(), get(), get(), get(), params.get()) }
viewModel { params -> ArtistDetailViewModel(get(), get(), get(), get(), params.get()) }
viewModel { params -> PlaylistDetailViewModel(get(), get(), get(), get(), params.get()) }
viewModel { QueueViewModel(get(), get(), get(), get()) }
}
private fun downloadsRoot(context: Context): File =
File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) ?: context.filesDir, "downloads")