From c010916953a8d7d93e1eab9e9dbf2676ca1301ff Mon Sep 17 00:00:00 2001 From: shabinder Date: Wed, 23 Jun 2021 16:43:26 +0530 Subject: [PATCH] Preference Screen & Preference Manager (WIP) --- .../com/shabinder/spotiflyer/MainActivity.kt | 29 ++++---- build.gradle.kts | 9 ++- buildSrc/buildSrc/src/main/kotlin/Versions.kt | 4 ++ .../common/models/SpotiFlyerException.kt | 5 ++ common/dependency-injection/build.gradle.kts | 2 +- .../com/shabinder/common/di/AndroidDir.kt | 7 +- .../requests}/saavn/decryptURL.kt | 5 +- .../kotlin/com/shabinder/common/di/DI.kt | 24 +++---- .../kotlin/com/shabinder/common/di/Dir.kt | 26 +------ .../common/di/FetchPlatformQueryResult.kt | 4 +- .../com/shabinder/common/di/TokenStore.kt | 2 +- .../common/di/preference/PreferenceManager.kt | 35 ++++++++++ .../common/di/providers/GaanaProvider.kt | 2 +- .../common/di/providers/ProvidersModule.kt | 16 +++++ .../common/di/providers/SaavnProvider.kt | 4 +- .../common/di/providers/SpotifyProvider.kt | 4 +- .../common/di/providers/YoutubeMp3.kt | 2 +- .../common/di/providers/YoutubeMusic.kt | 2 +- .../requests}/audioToMp3/AudioToMp3.kt | 2 +- .../requests}/gaana/GaanaRequests.kt | 2 +- .../requests}/saavn/JioSaavnRequests.kt | 4 +- .../requests}/saavn/JioSaavnUtils.kt | 4 +- .../requests}/spotify/SpotifyAuth.kt | 2 +- .../requests}/spotify/SpotifyRequests.kt | 2 +- .../requests}/youtubeMp3/Yt1sMp3.kt | 2 +- .../common/di/{saavn => utils}/JsonUtils.kt | 2 +- .../com/shabinder/common/di/DesktopActual.kt | 67 ++++++++++--------- .../com/shabinder/common/di/DesktopDir.kt | 7 +- .../requests}/saavn/decryptURL.kt | 5 +- .../kotlin/com.shabinder.common.di/IOSDir.kt | 7 +- .../saavn/decryptURL.kt | 0 .../com/shabinder/common/di/WebActual.kt | 41 ++++++------ .../kotlin/com/shabinder/common/di/WebDir.kt | 7 +- .../requests}/saavn/decryptURL.kt | 2 +- .../shabinder/common/list/SpotiFlyerList.kt | 2 + .../list/integration/SpotiFlyerListImpl.kt | 4 +- .../list/store/SpotiFlyerListStoreProvider.kt | 5 +- .../shabinder/common/main/SpotiFlyerMain.kt | 2 + .../main/integration/SpotiFlyerMainImpl.kt | 6 +- .../main/store/SpotiFlyerMainStoreProvider.kt | 8 +-- .../shabinder/common/root/SpotiFlyerRoot.kt | 8 ++- .../root/integration/SpotiFlyerRootImpl.kt | 15 ++--- desktop/src/jvmMain/kotlin/Main.kt | 30 ++++++--- settings.gradle.kts | 1 + web-app/src/main/kotlin/App.kt | 10 +-- web-app/src/main/kotlin/client.kt | 5 +- 46 files changed, 249 insertions(+), 185 deletions(-) rename common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/{ => providers/requests}/saavn/decryptURL.kt (87%) create mode 100644 common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/preference/PreferenceManager.kt create mode 100644 common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/ProvidersModule.kt rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/audioToMp3/AudioToMp3.kt (98%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/gaana/GaanaRequests.kt (98%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/saavn/JioSaavnRequests.kt (98%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/saavn/JioSaavnUtils.kt (70%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/spotify/SpotifyAuth.kt (97%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/spotify/SpotifyRequests.kt (97%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{ => providers/requests}/youtubeMp3/Yt1sMp3.kt (97%) rename common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/{saavn => utils}/JsonUtils.kt (98%) rename common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/{ => providers/requests}/saavn/decryptURL.kt (86%) rename common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/{ => providers.requests}/saavn/decryptURL.kt (100%) rename common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/{ => providers/requests}/saavn/decryptURL.kt (60%) diff --git a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt index 0bd21b8d..3acd9f81 100644 --- a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt +++ b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt @@ -52,6 +52,7 @@ import com.google.accompanist.insets.navigationBarsPadding import com.google.accompanist.insets.statusBarsHeight import com.google.accompanist.insets.statusBarsPadding import com.shabinder.common.di.* +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.Actions import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.PlatformActions @@ -78,6 +79,7 @@ class MainActivity : ComponentActivity() { private val fetcher: FetchPlatformQueryResult by inject() private val dir: Dir by inject() + private val preferenceManager: PreferenceManager by inject() private lateinit var root: SpotiFlyerRoot private val callBacks: SpotiFlyerRootCallBacks get() = root.callBacks private val trackStatusFlow = MutableSharedFlow>(1) @@ -129,18 +131,18 @@ class MainActivity : ComponentActivity() { AnalyticsDialog( askForAnalyticsPermission, enableAnalytics = { - dir.toggleAnalytics(true) - dir.firstLaunchDone() + preferenceManager.toggleAnalytics(true) + preferenceManager.firstLaunchDone() }, dismissDialog = { askForAnalyticsPermission = false - dir.firstLaunchDone() + preferenceManager.firstLaunchDone() } ) LaunchedEffect(view) { permissionGranted.value = checkPermissions() - if(dir.isFirstLaunch) { + if(preferenceManager.isFirstLaunch) { delay(2500) // Ask For Analytics Permission on first Dialog askForAnalyticsPermission = true @@ -161,7 +163,7 @@ class MainActivity : ComponentActivity() { * for `Github Downloads` we will track Downloads using : https://tooomm.github.io/github-release-stats/?username=Shabinder&repository=SpotiFlyer * */ if(isGithubRelease) { checkIfLatestVersion() } - if(dir.isAnalyticsEnabled && !isGithubRelease) { + if(preferenceManager.isAnalyticsEnabled && !isGithubRelease) { // Download/App Install Event for F-Droid builds TrackHelper.track().download().with(tracker) } @@ -246,9 +248,10 @@ class MainActivity : ComponentActivity() { dependencies = object : SpotiFlyerRoot.Dependencies{ override val storeFactory = LoggingStoreFactory(DefaultStoreFactory) override val database = this@MainActivity.dir.db - override val fetchPlatformQueryResult = this@MainActivity.fetcher - override val directories: Dir = this@MainActivity.dir - override val downloadProgressReport: MutableSharedFlow> = trackStatusFlow + override val fetchQuery = this@MainActivity.fetcher + override val dir: Dir = this@MainActivity.dir + override val preferenceManager = this@MainActivity.preferenceManager + override val downloadProgressFlow: MutableSharedFlow> = trackStatusFlow override val actions = object: Actions { override val platformActions = object : PlatformActions { @@ -316,7 +319,7 @@ class MainActivity : ComponentActivity() { * */ override val analytics = object: Analytics { override fun appLaunchEvent() { - if(dir.isAnalyticsEnabled){ + if(preferenceManager.isAnalyticsEnabled){ TrackHelper.track() .event("events","App_Launch") .name("App Launch").with(tracker) @@ -324,7 +327,7 @@ class MainActivity : ComponentActivity() { } override fun homeScreenVisit() { - if(dir.isAnalyticsEnabled){ + if(preferenceManager.isAnalyticsEnabled){ // HomeScreen Visit Event TrackHelper.track().screen("/main_activity/home_screen") .title("HomeScreen").with(tracker) @@ -332,7 +335,7 @@ class MainActivity : ComponentActivity() { } override fun listScreenVisit() { - if(dir.isAnalyticsEnabled){ + if(preferenceManager.isAnalyticsEnabled){ // ListScreen Visit Event TrackHelper.track().screen("/main_activity/list_screen") .title("ListScreen").with(tracker) @@ -340,7 +343,7 @@ class MainActivity : ComponentActivity() { } override fun donationDialogVisit() { - if (dir.isAnalyticsEnabled) { + if (preferenceManager.isAnalyticsEnabled) { // Donation Dialog Open Event TrackHelper.track().screen("/main_activity/donation_dialog") .title("DonationDialog").with(tracker) @@ -384,7 +387,7 @@ class MainActivity : ComponentActivity() { val f = File(path) if (f.canWrite()) { // hell yeah :) - dir.setDownloadDirectory(path) + preferenceManager.setDownloadDirectory(path) showPopUpMessage( "Download Directory Set to:\n${dir.defaultDir()} " ) diff --git a/build.gradle.kts b/build.gradle.kts index c73376d8..c4f0b7fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,12 +33,17 @@ allprojects { tasks.withType().configureEach { kotlinOptions { jvmTarget = "1.8" - useIR = true + freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" } } afterEvaluate { project.extensions.findByType()?.let { kmpExt -> - kmpExt.sourceSets.removeAll { it.name == "androidAndroidTestRelease" } + kmpExt.sourceSets.run { + all { + languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") + } + removeAll { it.name == "androidAndroidTestRelease" } + } } } } diff --git a/buildSrc/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/buildSrc/src/main/kotlin/Versions.kt index 280ebe5a..fbb3f1b9 100644 --- a/buildSrc/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/buildSrc/src/main/kotlin/Versions.kt @@ -60,6 +60,10 @@ object HostOS { val isLinux = hostOs.startsWith("Linux",true) } +object MultiPlatformSettings { + const val dep = "com.russhwolf:multiplatform-settings-no-arg:0.7.7" +} + object Koin { val core = "io.insert-koin:koin-core:${Versions.koin}" val test = "io.insert-koin:koin-test:${Versions.koin}" diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt index a5ecd0e1..0374c95b 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/SpotiFlyerException.kt @@ -10,6 +10,11 @@ sealed class SpotiFlyerException(override val message: String): Exception(messag override val message: String = "MP3 Converter unreachable, probably BUSY ! \nCAUSE:$extraInfo" ): SpotiFlyerException(message) + data class UnknownReason( + val exception: Throwable? = null, + override val message: String = "Unknown Error" + ): SpotiFlyerException(message) + data class NoMatchFound( val trackName: String? = null, override val message: String = "$trackName : NO Match Found!" diff --git a/common/dependency-injection/build.gradle.kts b/common/dependency-injection/build.gradle.kts index 2a63e0fd..6852ae09 100644 --- a/common/dependency-injection/build.gradle.kts +++ b/common/dependency-injection/build.gradle.kts @@ -32,7 +32,7 @@ kotlin { implementation(project(":common:database")) implementation("org.jetbrains.kotlinx:atomicfu:0.16.1") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.2.1") - implementation("com.russhwolf:multiplatform-settings-no-arg:0.7.7") + api(MultiPlatformSettings.dep) implementation(Extras.youtubeDownloader) implementation(Extras.fuzzyWuzzy) implementation(MVIKotlin.rx) diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/AndroidDir.kt b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/AndroidDir.kt index 27bc641b..f6b44eee 100644 --- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/AndroidDir.kt +++ b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/AndroidDir.kt @@ -22,8 +22,8 @@ import android.os.Environment import androidx.compose.ui.graphics.asImageBitmap import co.touchlab.kermit.Kermit import com.mpatric.mp3agic.Mp3File -import com.russhwolf.settings.Settings import com.shabinder.common.database.SpotiFlyerDatabase +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.di.utils.ParallelExecutor import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.methods @@ -43,7 +43,7 @@ import java.net.URL @Suppress("DEPRECATION") actual class Dir actual constructor( private val logger: Kermit, - settingsPref: Settings, + private val preferenceManager: PreferenceManager, spotiFlyerDatabase: SpotiFlyerDatabase, ) { @Suppress("DEPRECATION") @@ -54,7 +54,7 @@ actual class Dir actual constructor( actual fun imageCacheDir(): String = methods.value.platformActions.imageCacheDir // fun call in order to always access Updated Value - actual fun defaultDir(): String = (settings.getStringOrNull(DirKey) ?: defaultBaseDir) + + actual fun defaultDir(): String = (preferenceManager.downloadDir ?: defaultBaseDir) + File.separator + "SpotiFlyer" + File.separator actual fun isPresent(path: String): Boolean = File(path).exists() @@ -202,5 +202,4 @@ actual class Dir actual constructor( private val parallelExecutor = ParallelExecutor(Dispatchers.IO) actual val db: Database? = spotiFlyerDatabase.instance - actual val settings: Settings = settingsPref } diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt similarity index 87% rename from common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt rename to common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt index 65d67107..2a523118 100644 --- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt +++ b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt @@ -1,8 +1,7 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.providers.requests.saavn import android.annotation.SuppressLint -import io.ktor.util.InternalAPI -import io.ktor.util.decodeBase64Bytes +import io.ktor.util.* import java.security.SecureRandom import javax.crypto.Cipher import javax.crypto.SecretKey diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/DI.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/DI.kt index 0d23dcc0..27f30a37 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/DI.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/DI.kt @@ -20,13 +20,8 @@ import co.touchlab.kermit.Kermit import com.russhwolf.settings.Settings import com.shabinder.common.database.databaseModule import com.shabinder.common.database.getLogger -import com.shabinder.common.di.audioToMp3.AudioToMp3 -import com.shabinder.common.di.providers.GaanaProvider -import com.shabinder.common.di.providers.SaavnProvider -import com.shabinder.common.di.providers.SpotifyProvider -import com.shabinder.common.di.providers.YoutubeMp3 -import com.shabinder.common.di.providers.YoutubeMusic -import com.shabinder.common.di.providers.YoutubeProvider +import com.shabinder.common.di.preference.PreferenceManager +import com.shabinder.common.di.providers.providersModule import io.ktor.client.* import io.ktor.client.features.* import io.ktor.client.features.json.* @@ -42,7 +37,11 @@ import kotlin.native.concurrent.ThreadLocal fun initKoin(enableNetworkLogs: Boolean = false, appDeclaration: KoinAppDeclaration = {}) = startKoin { appDeclaration() - modules(commonModule(enableNetworkLogs = enableNetworkLogs), databaseModule()) + modules( + commonModule(enableNetworkLogs = enableNetworkLogs), + providersModule(), + databaseModule() + ) } // Called by IOS @@ -52,16 +51,9 @@ fun commonModule(enableNetworkLogs: Boolean) = module { single { createHttpClient(enableNetworkLogs = enableNetworkLogs) } single { Dir(get(), get(), get()) } single { Settings() } + single { PreferenceManager(get()) } single { Kermit(getLogger()) } single { TokenStore(get(), get()) } - single { AudioToMp3(get(), get()) } - single { SpotifyProvider(get(), get(), get()) } - single { GaanaProvider(get(), get(), get()) } - single { SaavnProvider(get(), get(), get(), get()) } - single { YoutubeProvider(get(), get(), get()) } - single { YoutubeMp3(get(), get()) } - single { YoutubeMusic(get(), get(), get(), get(), get()) } - single { FetchPlatformQueryResult(get(), get(), get(), get(), get(), get(), get(), get(), get()) } } @ThreadLocal diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Dir.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Dir.kt index 7820eb92..ee877010 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Dir.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Dir.kt @@ -17,8 +17,8 @@ package com.shabinder.common.di import co.touchlab.kermit.Kermit -import com.russhwolf.settings.Settings import com.shabinder.common.database.SpotiFlyerDatabase +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.di.utils.removeIllegalChars import com.shabinder.common.models.DownloadResult import com.shabinder.common.models.TrackDetails @@ -30,18 +30,12 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlin.math.roundToInt -const val DirKey = "downloadDir" -const val AnalyticsKey = "analytics" -const val FirstLaunch = "firstLaunch" -const val DonationInterval = "donationInterval" - expect class Dir( logger: Kermit, - settingsPref: Settings, + preferenceManager: PreferenceManager, spotiFlyerDatabase: SpotiFlyerDatabase, ) { val db: Database? - val settings: Settings fun isPresent(path: String): Boolean fun fileSeparator(): String fun defaultDir(): String @@ -54,22 +48,6 @@ expect class Dir( fun addToLibrary(path: String) } -val Dir.isAnalyticsEnabled get() = settings.getBooleanOrNull(AnalyticsKey) ?: false -fun Dir.toggleAnalytics(enabled: Boolean) = settings.putBoolean(AnalyticsKey, enabled) - -fun Dir.setDownloadDirectory(newBasePath: String) = settings.putString(DirKey, newBasePath) - -val Dir.getDonationOffset: Int get() = (settings.getIntOrNull(DonationInterval) ?: 3).also { - // Min. Donation Asking Interval is `3` - if (it < 3) setDonationOffset(3) else setDonationOffset(it - 1) -} -fun Dir.setDonationOffset(offset: Int = 5) = settings.putInt(DonationInterval, offset) - -val Dir.isFirstLaunch get() = settings.getBooleanOrNull(FirstLaunch) ?: true -fun Dir.firstLaunchDone() { - settings.putBoolean(FirstLaunch, false) -} - /* * Call this function at startup! * */ diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt index 9a476f0f..b7eabb08 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/FetchPlatformQueryResult.kt @@ -18,7 +18,6 @@ package com.shabinder.common.di import co.touchlab.kermit.Kermit import com.shabinder.common.database.DownloadRecordDatabaseQueries -import com.shabinder.common.di.audioToMp3.AudioToMp3 import com.shabinder.common.di.providers.GaanaProvider import com.shabinder.common.di.providers.SaavnProvider import com.shabinder.common.di.providers.SpotifyProvider @@ -26,6 +25,7 @@ import com.shabinder.common.di.providers.YoutubeMp3 import com.shabinder.common.di.providers.YoutubeMusic import com.shabinder.common.di.providers.YoutubeProvider import com.shabinder.common.di.providers.get +import com.shabinder.common.di.providers.requests.audioToMp3.AudioToMp3 import com.shabinder.common.models.PlatformQueryResult import com.shabinder.common.models.SpotiFlyerException import com.shabinder.common.models.TrackDetails @@ -35,6 +35,7 @@ import com.shabinder.common.models.event.coroutines.flatMapError import com.shabinder.common.models.event.coroutines.success import com.shabinder.common.models.spotify.Source import com.shabinder.common.requireNotNull +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -137,6 +138,7 @@ class FetchPlatformQueryResult( } } + @OptIn(DelicateCoroutinesApi::class) private fun addToDatabaseAsync(link: String, result: PlatformQueryResult) { GlobalScope.launch(dispatcherIO) { db?.add( diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/TokenStore.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/TokenStore.kt index 041fb9a3..0526e306 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/TokenStore.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/TokenStore.kt @@ -18,7 +18,7 @@ package com.shabinder.common.di import co.touchlab.kermit.Kermit import com.shabinder.common.database.TokenDBQueries -import com.shabinder.common.di.spotify.authenticateSpotify +import com.shabinder.common.di.providers.requests.spotify.authenticateSpotify import com.shabinder.common.models.spotify.TokenData import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/preference/PreferenceManager.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/preference/PreferenceManager.kt new file mode 100644 index 00000000..3e44ba91 --- /dev/null +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/preference/PreferenceManager.kt @@ -0,0 +1,35 @@ +package com.shabinder.common.di.preference + +import com.russhwolf.settings.Settings + +class PreferenceManager(settings: Settings): Settings by settings { + + companion object { + const val DirKey = "downloadDir" + const val AnalyticsKey = "analytics" + const val FirstLaunch = "firstLaunch" + const val DonationInterval = "donationInterval" + } + + /* ANALYTICS */ + val isAnalyticsEnabled get() = getBooleanOrNull(AnalyticsKey) ?: false + fun toggleAnalytics(enabled: Boolean) = putBoolean(AnalyticsKey, enabled) + + + /* DOWNLOAD DIRECTORY */ + val downloadDir get() = getStringOrNull(DirKey) + fun setDownloadDirectory(newBasePath: String) = putString(DirKey, newBasePath) + + + /* OFFSET FOR WHEN TO ASK FOR SUPPORT */ + val getDonationOffset: Int get() = (getIntOrNull(DonationInterval) ?: 3).also { + // Min. Donation Asking Interval is `3` + if (it < 3) setDonationOffset(3) else setDonationOffset(it - 1) + } + fun setDonationOffset(offset: Int = 5) = putInt(DonationInterval, offset) + + + /* TO CHECK IF THIS IS APP's FIRST LAUNCH */ + val isFirstLaunch get() = getBooleanOrNull(FirstLaunch) ?: true + fun firstLaunchDone() = putBoolean(FirstLaunch, false) +} \ No newline at end of file diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/GaanaProvider.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/GaanaProvider.kt index 5fdfda90..37d27c87 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/GaanaProvider.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/GaanaProvider.kt @@ -19,7 +19,7 @@ package com.shabinder.common.di.providers import co.touchlab.kermit.Kermit import com.shabinder.common.di.Dir import com.shabinder.common.di.finalOutputDir -import com.shabinder.common.di.gaana.GaanaRequests +import com.shabinder.common.di.providers.requests.gaana.GaanaRequests import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.PlatformQueryResult import com.shabinder.common.models.SpotiFlyerException diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/ProvidersModule.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/ProvidersModule.kt new file mode 100644 index 00000000..b4d46549 --- /dev/null +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/ProvidersModule.kt @@ -0,0 +1,16 @@ +package com.shabinder.common.di.providers + +import com.shabinder.common.di.FetchPlatformQueryResult +import com.shabinder.common.di.providers.requests.audioToMp3.AudioToMp3 +import org.koin.dsl.module + +fun providersModule() = module { + single { AudioToMp3(get(), get()) } + single { SpotifyProvider(get(), get(), get()) } + single { GaanaProvider(get(), get(), get()) } + single { SaavnProvider(get(), get(), get(), get()) } + single { YoutubeProvider(get(), get(), get()) } + single { YoutubeMp3(get(), get()) } + single { YoutubeMusic(get(), get(), get(), get(), get()) } + single { FetchPlatformQueryResult(get(), get(), get(), get(), get(), get(), get(), get(), get()) } +} \ No newline at end of file diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SaavnProvider.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SaavnProvider.kt index b062f4cf..7188ada4 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SaavnProvider.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SaavnProvider.kt @@ -2,9 +2,9 @@ package com.shabinder.common.di.providers import co.touchlab.kermit.Kermit import com.shabinder.common.di.Dir -import com.shabinder.common.di.audioToMp3.AudioToMp3 import com.shabinder.common.di.finalOutputDir -import com.shabinder.common.di.saavn.JioSaavnRequests +import com.shabinder.common.di.providers.requests.audioToMp3.AudioToMp3 +import com.shabinder.common.di.providers.requests.saavn.JioSaavnRequests import com.shabinder.common.di.utils.removeIllegalChars import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.PlatformQueryResult diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SpotifyProvider.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SpotifyProvider.kt index b6796258..0d446611 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SpotifyProvider.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/SpotifyProvider.kt @@ -22,8 +22,8 @@ import com.shabinder.common.di.TokenStore import com.shabinder.common.di.createHttpClient import com.shabinder.common.di.finalOutputDir import com.shabinder.common.di.globalJson -import com.shabinder.common.di.spotify.SpotifyRequests -import com.shabinder.common.di.spotify.authenticateSpotify +import com.shabinder.common.di.providers.requests.spotify.SpotifyRequests +import com.shabinder.common.di.providers.requests.spotify.authenticateSpotify import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.NativeAtomicReference import com.shabinder.common.models.PlatformQueryResult diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMp3.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMp3.kt index 03d0c758..5ba98a5c 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMp3.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMp3.kt @@ -17,7 +17,7 @@ package com.shabinder.common.di.providers import co.touchlab.kermit.Kermit -import com.shabinder.common.di.youtubeMp3.Yt1sMp3 +import com.shabinder.common.di.providers.requests.youtubeMp3.Yt1sMp3 import com.shabinder.common.models.corsApi import com.shabinder.common.models.event.coroutines.SuspendableEvent import com.shabinder.common.models.event.coroutines.map diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt index ec68f6bc..0949226e 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/YoutubeMusic.kt @@ -17,7 +17,7 @@ package com.shabinder.common.di.providers import co.touchlab.kermit.Kermit -import com.shabinder.common.di.audioToMp3.AudioToMp3 +import com.shabinder.common.di.providers.requests.audioToMp3.AudioToMp3 import com.shabinder.common.models.SpotiFlyerException import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.YoutubeTrack diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/audioToMp3/AudioToMp3.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/audioToMp3/AudioToMp3.kt similarity index 98% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/audioToMp3/AudioToMp3.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/audioToMp3/AudioToMp3.kt index 14d6e9f8..6e4f4261 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/audioToMp3/AudioToMp3.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/audioToMp3/AudioToMp3.kt @@ -1,4 +1,4 @@ -package com.shabinder.common.di.audioToMp3 +package com.shabinder.common.di.providers.requests.audioToMp3 import co.touchlab.kermit.Kermit import com.shabinder.common.models.AudioQuality diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/gaana/GaanaRequests.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/gaana/GaanaRequests.kt similarity index 98% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/gaana/GaanaRequests.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/gaana/GaanaRequests.kt index 11f36a52..373945ae 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/gaana/GaanaRequests.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/gaana/GaanaRequests.kt @@ -14,7 +14,7 @@ * * along with this program. If not, see . */ -package com.shabinder.common.di.gaana +package com.shabinder.common.di.providers.requests.gaana import com.shabinder.common.models.corsApi import com.shabinder.common.models.gaana.GaanaAlbum diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnRequests.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt similarity index 98% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnRequests.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt index 79c6188c..b3b59ecf 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnRequests.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnRequests.kt @@ -1,8 +1,8 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.providers.requests.saavn import co.touchlab.kermit.Kermit -import com.shabinder.common.di.audioToMp3.AudioToMp3 import com.shabinder.common.di.globalJson +import com.shabinder.common.di.providers.requests.audioToMp3.AudioToMp3 import com.shabinder.common.models.corsApi import com.shabinder.common.models.event.coroutines.SuspendableEvent import com.shabinder.common.models.event.coroutines.map diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnUtils.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnUtils.kt similarity index 70% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnUtils.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnUtils.kt index d9e38f2d..4ff3e563 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JioSaavnUtils.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/saavn/JioSaavnUtils.kt @@ -1,4 +1,6 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.providers.requests.saavn + +import com.shabinder.common.di.utils.unescape expect suspend fun decryptURL(url: String): String diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyAuth.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyAuth.kt similarity index 97% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyAuth.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyAuth.kt index 33d24a0d..4bb67403 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyAuth.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyAuth.kt @@ -14,7 +14,7 @@ * * along with this program. If not, see . */ -package com.shabinder.common.di.spotify +package com.shabinder.common.di.providers.requests.spotify import com.shabinder.common.di.globalJson import com.shabinder.common.models.SpotiFlyerException diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyRequests.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyRequests.kt similarity index 97% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyRequests.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyRequests.kt index 22acff05..7e31a4f6 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/spotify/SpotifyRequests.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/spotify/SpotifyRequests.kt @@ -14,7 +14,7 @@ * * along with this program. If not, see . */ -package com.shabinder.common.di.spotify +package com.shabinder.common.di.providers.requests.spotify import com.shabinder.common.models.NativeAtomicReference import com.shabinder.common.models.corsApi diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/youtubeMp3/Yt1sMp3.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/youtubeMp3/Yt1sMp3.kt similarity index 97% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/youtubeMp3/Yt1sMp3.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/youtubeMp3/Yt1sMp3.kt index 5bac8eff..3e7feff2 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/youtubeMp3/Yt1sMp3.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/providers/requests/youtubeMp3/Yt1sMp3.kt @@ -14,7 +14,7 @@ * * along with this program. If not, see . */ -package com.shabinder.common.di.youtubeMp3 +package com.shabinder.common.di.providers.requests.youtubeMp3 import co.touchlab.kermit.Kermit import com.shabinder.common.models.corsApi diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JsonUtils.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/utils/JsonUtils.kt similarity index 98% rename from common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JsonUtils.kt rename to common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/utils/JsonUtils.kt index 367f39a1..3e06f0b5 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/saavn/JsonUtils.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/utils/JsonUtils.kt @@ -1,4 +1,4 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.utils /* * JSON UTILS diff --git a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopActual.kt b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopActual.kt index cbc449d7..4e9cda1e 100644 --- a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopActual.kt +++ b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopActual.kt @@ -19,6 +19,7 @@ package com.shabinder.common.di import com.shabinder.common.di.utils.ParallelExecutor import com.shabinder.common.models.DownloadResult import com.shabinder.common.models.DownloadStatus +import com.shabinder.common.models.SpotiFlyerException import com.shabinder.common.models.TrackDetails import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -40,41 +41,43 @@ actual suspend fun downloadTracks( ) { list.forEach { trackDetails -> DownloadScope.execute { // Send Download to Pool. - val url = fetcher.findMp3DownloadLink(trackDetails) - if (!url.isNullOrBlank()) { // Successfully Grabbed Mp3 URL - downloadFile(url).collect { - when (it) { - is DownloadResult.Error -> { - DownloadProgressFlow.emit( - DownloadProgressFlow.replayCache.getOrElse( - 0 - ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed) } - ) - } - is DownloadResult.Progress -> { - DownloadProgressFlow.emit( - DownloadProgressFlow.replayCache.getOrElse( - 0 - ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloading(it.progress)) } - ) - } - is DownloadResult.Success -> { // Todo clear map - dir.saveFileWithMetadata(it.byteArray, trackDetails) {} - DownloadProgressFlow.emit( - DownloadProgressFlow.replayCache.getOrElse( - 0 - ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) } - ) + fetcher.findMp3DownloadLink(trackDetails).fold( + success = { url -> + downloadFile(url).collect { + when (it) { + is DownloadResult.Error -> { + DownloadProgressFlow.emit( + DownloadProgressFlow.replayCache.getOrElse( + 0 + ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed(it.cause ?: SpotiFlyerException.UnknownReason(it.cause))) } + ) + } + is DownloadResult.Progress -> { + DownloadProgressFlow.emit( + DownloadProgressFlow.replayCache.getOrElse( + 0 + ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloading(it.progress)) } + ) + } + is DownloadResult.Success -> { // Todo clear map + dir.saveFileWithMetadata(it.byteArray, trackDetails) {} + DownloadProgressFlow.emit( + DownloadProgressFlow.replayCache.getOrElse( + 0 + ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) } + ) + } } } + }, + failure = { error -> + DownloadProgressFlow.emit( + DownloadProgressFlow.replayCache.getOrElse( + 0 + ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed(error)) } + ) } - } else { - DownloadProgressFlow.emit( - DownloadProgressFlow.replayCache.getOrElse( - 0 - ) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed) } - ) - } + ) } } } diff --git a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopDir.kt b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopDir.kt index ae393df9..efff1f9a 100644 --- a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopDir.kt +++ b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/DesktopDir.kt @@ -20,8 +20,8 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import co.touchlab.kermit.Kermit import com.mpatric.mp3agic.Mp3File -import com.russhwolf.settings.Settings import com.shabinder.common.database.SpotiFlyerDatabase +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.TrackDetails import com.shabinder.database.Database import kotlinx.coroutines.Dispatchers @@ -40,7 +40,7 @@ import javax.imageio.ImageIO actual class Dir actual constructor( private val logger: Kermit, - settingsPref: Settings, + private val preferenceManager: PreferenceManager, spotiFlyerDatabase: SpotiFlyerDatabase, ) { @@ -55,7 +55,7 @@ actual class Dir actual constructor( private val defaultBaseDir = System.getProperty("user.home") - actual fun defaultDir(): String = (settings.getStringOrNull(DirKey) ?: defaultBaseDir) + fileSeparator() + + actual fun defaultDir(): String = (preferenceManager.downloadDir ?: defaultBaseDir) + fileSeparator() + "SpotiFlyer" + fileSeparator() actual fun isPresent(path: String): Boolean = File(path).exists() @@ -199,7 +199,6 @@ actual class Dir actual constructor( } actual val db: Database? = spotiFlyerDatabase.instance - actual val settings: Settings = settingsPref } fun BufferedImage.toImageBitmap() = Image.makeFromEncoded( diff --git a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt similarity index 86% rename from common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt rename to common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt index 80153b91..e77b3045 100644 --- a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt +++ b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt @@ -1,7 +1,6 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.providers.requests.saavn -import io.ktor.util.InternalAPI -import io.ktor.util.decodeBase64Bytes +import io.ktor.util.* import java.security.SecureRandom import javax.crypto.Cipher import javax.crypto.SecretKey diff --git a/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/IOSDir.kt b/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/IOSDir.kt index 10dae478..5ea6efaa 100644 --- a/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/IOSDir.kt +++ b/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/IOSDir.kt @@ -1,8 +1,8 @@ package com.shabinder.common.di import co.touchlab.kermit.Kermit -import com.russhwolf.settings.Settings import com.shabinder.common.database.SpotiFlyerDatabase +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.TrackDetails import com.shabinder.database.Database import kotlinx.coroutines.GlobalScope @@ -24,7 +24,7 @@ import platform.UIKit.UIImageJPEGRepresentation actual class Dir actual constructor( val logger: Kermit, - settingsPref: Settings, + private val preferenceManager: PreferenceManager, spotiFlyerDatabase: SpotiFlyerDatabase, ) { @@ -35,7 +35,7 @@ actual class Dir actual constructor( private val defaultBaseDir = NSFileManager.defaultManager.URLForDirectory(NSMusicDirectory, NSUserDomainMask, null, true, null)!!.path!! // TODO Error Handling - actual fun defaultDir(): String = (settings.getStringOrNull(DirKey) ?: defaultBaseDir) + + actual fun defaultDir(): String = (preferenceManager.downloadDir ?: defaultBaseDir) + fileSeparator() + "SpotiFlyer" + fileSeparator() private val defaultDirURL: NSURL by lazy { @@ -176,6 +176,5 @@ actual class Dir actual constructor( // TODO } - actual val settings: Settings = settingsPref actual val db: Database? = spotiFlyerDatabase.instance } diff --git a/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/saavn/decryptURL.kt b/common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/providers.requests/saavn/decryptURL.kt similarity index 100% rename from common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/saavn/decryptURL.kt rename to common/dependency-injection/src/iosMain/kotlin/com.shabinder.common.di/providers.requests/saavn/decryptURL.kt diff --git a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt index 5c0740a1..0682cc22 100644 --- a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt +++ b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt @@ -18,6 +18,7 @@ package com.shabinder.common.di import com.shabinder.common.models.DownloadResult import com.shabinder.common.models.DownloadStatus +import com.shabinder.common.models.SpotiFlyerException import com.shabinder.common.models.TrackDetails import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -41,29 +42,31 @@ actual suspend fun downloadTracks( list.forEach { track -> withContext(dispatcherIO) { allTracksStatus[track.title] = DownloadStatus.Queued - val url = fetcher.findMp3DownloadLink(track) - if (!url.isNullOrBlank()) { // Successfully Grabbed Mp3 URL - downloadFile(url).collect { - when (it) { - is DownloadResult.Success -> { - println("Download Completed") - dir.saveFileWithMetadata(it.byteArray, track) {} - } - is DownloadResult.Error -> { - allTracksStatus[track.title] = DownloadStatus.Failed - println("Download Error: ${track.title}") - } - is DownloadResult.Progress -> { - allTracksStatus[track.title] = DownloadStatus.Downloading(it.progress) - println("Download Progress: ${it.progress} : ${track.title}") + fetcher.findMp3DownloadLink(track).fold( + success = { url -> + downloadFile(url).collect { + when (it) { + is DownloadResult.Success -> { + println("Download Completed") + dir.saveFileWithMetadata(it.byteArray, track) {} + } + is DownloadResult.Error -> { + allTracksStatus[track.title] = DownloadStatus.Failed(it.cause ?: SpotiFlyerException.UnknownReason(it.cause)) + println("Download Error: ${track.title}") + } + is DownloadResult.Progress -> { + allTracksStatus[track.title] = DownloadStatus.Downloading(it.progress) + println("Download Progress: ${it.progress} : ${track.title}") + } } + DownloadProgressFlow.emit(allTracksStatus) } + }, + failure = { error -> + allTracksStatus[track.title] = DownloadStatus.Failed(error) DownloadProgressFlow.emit(allTracksStatus) } - } else { - allTracksStatus[track.title] = DownloadStatus.Failed - DownloadProgressFlow.emit(allTracksStatus) - } + ) } } } diff --git a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt index c909d10e..cc18e5d2 100644 --- a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt +++ b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt @@ -17,13 +17,13 @@ package com.shabinder.common.di import co.touchlab.kermit.Kermit -import com.russhwolf.settings.Settings import com.shabinder.common.database.SpotiFlyerDatabase -import com.shabinder.common.di.gaana.corsApi +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.di.utils.removeIllegalChars import com.shabinder.common.models.DownloadResult import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.TrackDetails +import com.shabinder.common.models.corsApi import com.shabinder.database.Database import kotlinext.js.Object import kotlinext.js.js @@ -34,7 +34,7 @@ import org.w3c.dom.ImageBitmap actual class Dir actual constructor( private val logger: Kermit, - settingsPref: Settings, + private val preferenceManager: PreferenceManager, spotiFlyerDatabase: SpotiFlyerDatabase, ) { /*init { @@ -116,7 +116,6 @@ actual class Dir actual constructor( private suspend fun freshImage(url: String): ImageBitmap? = null actual val db: Database? = spotiFlyerDatabase.instance - actual val settings: Settings = settingsPref } fun ByteArray.toArrayBuffer(): ArrayBuffer { diff --git a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt similarity index 60% rename from common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt rename to common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt index e5264bbb..540525fe 100644 --- a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/saavn/decryptURL.kt +++ b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/providers/requests/saavn/decryptURL.kt @@ -1,4 +1,4 @@ -package com.shabinder.common.di.saavn +package com.shabinder.common.di.providers.requests.saavn actual suspend fun decryptURL(url: String): String { TODO("Not yet implemented") diff --git a/common/list/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt b/common/list/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt index 1503b3d7..d2feb248 100644 --- a/common/list/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt +++ b/common/list/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt @@ -22,6 +22,7 @@ import com.arkivanov.mvikotlin.core.store.StoreFactory import com.shabinder.common.di.Dir import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.Picture +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.list.integration.SpotiFlyerListImpl import com.shabinder.common.models.Consumer import com.shabinder.common.models.DownloadStatus @@ -67,6 +68,7 @@ interface SpotiFlyerList { val storeFactory: StoreFactory val fetchQuery: FetchPlatformQueryResult val dir: Dir + val preferenceManager: PreferenceManager val link: String val listOutput: Consumer val downloadProgressFlow: MutableSharedFlow> diff --git a/common/list/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt b/common/list/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt index ede4efee..0b4a38d7 100644 --- a/common/list/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt +++ b/common/list/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt @@ -22,7 +22,6 @@ import com.arkivanov.decompose.lifecycle.doOnResume import com.arkivanov.decompose.value.Value import com.shabinder.common.caching.Cache import com.shabinder.common.di.Picture -import com.shabinder.common.di.setDonationOffset import com.shabinder.common.di.utils.asValue import com.shabinder.common.list.SpotiFlyerList import com.shabinder.common.list.SpotiFlyerList.Dependencies @@ -48,6 +47,7 @@ internal class SpotiFlyerListImpl( instanceKeeper.getStore { SpotiFlyerListStoreProvider( dir = this.dir, + preferenceManager = preferenceManager, storeFactory = storeFactory, fetchQuery = fetchQuery, downloadProgressFlow = downloadProgressFlow, @@ -79,7 +79,7 @@ internal class SpotiFlyerListImpl( } override fun snoozeDonationDialog() { - dir.setDonationOffset(offset = 10) + preferenceManager.setDonationOffset(offset = 10) } override suspend fun loadImage(url: String, isCover: Boolean): Picture { diff --git a/common/list/src/commonMain/kotlin/com/shabinder/common/list/store/SpotiFlyerListStoreProvider.kt b/common/list/src/commonMain/kotlin/com/shabinder/common/list/store/SpotiFlyerListStoreProvider.kt index a2f17aa9..fa71554d 100644 --- a/common/list/src/commonMain/kotlin/com/shabinder/common/list/store/SpotiFlyerListStoreProvider.kt +++ b/common/list/src/commonMain/kotlin/com/shabinder/common/list/store/SpotiFlyerListStoreProvider.kt @@ -24,7 +24,7 @@ import com.arkivanov.mvikotlin.extensions.coroutines.SuspendExecutor import com.shabinder.common.di.Dir import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.downloadTracks -import com.shabinder.common.di.getDonationOffset +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.list.SpotiFlyerList.State import com.shabinder.common.list.store.SpotiFlyerListStore.Intent import com.shabinder.common.models.DownloadStatus @@ -36,6 +36,7 @@ import kotlinx.coroutines.flow.collect internal class SpotiFlyerListStoreProvider( private val dir: Dir, + private val preferenceManager: PreferenceManager, private val storeFactory: StoreFactory, private val fetchQuery: FetchPlatformQueryResult, private val link: String, @@ -68,7 +69,7 @@ internal class SpotiFlyerListStoreProvider( dir.db?.downloadRecordDatabaseQueries?.getLastInsertId()?.executeAsOneOrNull()?.also { // See if It's Time we can request for support for maintaining this project or not fetchQuery.logger.d(message = { "Database List Last ID: $it" }, tag = "Database Last ID") - val offset = dir.getDonationOffset + val offset = preferenceManager.getDonationOffset dispatch( Result.AskForSupport( // Every 3rd Interval or After some offset diff --git a/common/main/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt b/common/main/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt index 275972ab..9bfc18ec 100644 --- a/common/main/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt +++ b/common/main/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt @@ -21,6 +21,7 @@ import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory import com.shabinder.common.di.Dir import com.shabinder.common.di.Picture +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.main.integration.SpotiFlyerMainImpl import com.shabinder.common.models.Consumer import com.shabinder.common.models.DownloadRecord @@ -63,6 +64,7 @@ interface SpotiFlyerMain { val storeFactory: StoreFactory val database: Database? val dir: Dir + val preferenceManager: PreferenceManager val mainAnalytics: Analytics } diff --git a/common/main/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt b/common/main/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt index d44878e7..5872d0c8 100644 --- a/common/main/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt +++ b/common/main/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt @@ -23,7 +23,10 @@ import com.shabinder.common.caching.Cache import com.shabinder.common.di.Picture import com.shabinder.common.di.utils.asValue import com.shabinder.common.main.SpotiFlyerMain -import com.shabinder.common.main.SpotiFlyerMain.* +import com.shabinder.common.main.SpotiFlyerMain.Dependencies +import com.shabinder.common.main.SpotiFlyerMain.HomeCategory +import com.shabinder.common.main.SpotiFlyerMain.Output +import com.shabinder.common.main.SpotiFlyerMain.State import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent import com.shabinder.common.main.store.SpotiFlyerMainStoreProvider import com.shabinder.common.main.store.getStore @@ -41,6 +44,7 @@ internal class SpotiFlyerMainImpl( private val store = instanceKeeper.getStore { SpotiFlyerMainStoreProvider( + preferenceManager = preferenceManager, storeFactory = storeFactory, database = database, dir = dir diff --git a/common/main/src/commonMain/kotlin/com/shabinder/common/main/store/SpotiFlyerMainStoreProvider.kt b/common/main/src/commonMain/kotlin/com/shabinder/common/main/store/SpotiFlyerMainStoreProvider.kt index 9bc41d10..4ee7c951 100644 --- a/common/main/src/commonMain/kotlin/com/shabinder/common/main/store/SpotiFlyerMainStoreProvider.kt +++ b/common/main/src/commonMain/kotlin/com/shabinder/common/main/store/SpotiFlyerMainStoreProvider.kt @@ -22,8 +22,7 @@ import com.arkivanov.mvikotlin.core.store.Store import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.extensions.coroutines.SuspendExecutor import com.shabinder.common.di.Dir -import com.shabinder.common.di.isAnalyticsEnabled -import com.shabinder.common.di.toggleAnalytics +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.main.SpotiFlyerMain import com.shabinder.common.main.SpotiFlyerMain.State import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent @@ -39,6 +38,7 @@ import kotlinx.coroutines.flow.map internal class SpotiFlyerMainStoreProvider( private val storeFactory: StoreFactory, + private val preferenceManager: PreferenceManager, private val dir: Dir, database: Database? ) { @@ -76,7 +76,7 @@ internal class SpotiFlyerMainStoreProvider( private inner class ExecutorImpl : SuspendExecutor() { override suspend fun executeAction(action: Unit, getState: () -> State) { - dispatch(Result.ToggleAnalytics(dir.isAnalyticsEnabled)) + dispatch(Result.ToggleAnalytics(preferenceManager.isAnalyticsEnabled)) updates?.collect { dispatch(Result.ItemsLoaded(it)) } @@ -91,7 +91,7 @@ internal class SpotiFlyerMainStoreProvider( is Intent.SelectCategory -> dispatch(Result.CategoryChanged(intent.category)) is Intent.ToggleAnalytics -> { dispatch(Result.ToggleAnalytics(intent.enabled)) - dir.toggleAnalytics(intent.enabled) + preferenceManager.toggleAnalytics(intent.enabled) } } } diff --git a/common/root/src/commonMain/kotlin/com/shabinder/common/root/SpotiFlyerRoot.kt b/common/root/src/commonMain/kotlin/com/shabinder/common/root/SpotiFlyerRoot.kt index c266f18f..9c260c97 100644 --- a/common/root/src/commonMain/kotlin/com/shabinder/common/root/SpotiFlyerRoot.kt +++ b/common/root/src/commonMain/kotlin/com/shabinder/common/root/SpotiFlyerRoot.kt @@ -22,6 +22,7 @@ import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory import com.shabinder.common.di.Dir import com.shabinder.common.di.FetchPlatformQueryResult +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.list.SpotiFlyerList import com.shabinder.common.main.SpotiFlyerMain import com.shabinder.common.models.Actions @@ -49,9 +50,10 @@ interface SpotiFlyerRoot { interface Dependencies { val storeFactory: StoreFactory val database: Database? - val fetchPlatformQueryResult: FetchPlatformQueryResult - val directories: Dir - val downloadProgressReport: MutableSharedFlow> + val fetchQuery: FetchPlatformQueryResult + val dir: Dir + val preferenceManager: PreferenceManager + val downloadProgressFlow: MutableSharedFlow> val actions: Actions val analytics: Analytics } diff --git a/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt b/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt index d2b5fb72..96ea55ac 100644 --- a/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt +++ b/common/root/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt @@ -27,7 +27,6 @@ import com.arkivanov.decompose.router import com.arkivanov.decompose.statekeeper.Parcelable import com.arkivanov.decompose.statekeeper.Parcelize import com.arkivanov.decompose.value.Value -import com.shabinder.common.di.Dir import com.shabinder.common.di.dispatcherIO import com.shabinder.common.list.SpotiFlyerList import com.shabinder.common.main.SpotiFlyerMain @@ -39,6 +38,7 @@ import com.shabinder.common.root.SpotiFlyerRoot.Analytics import com.shabinder.common.root.SpotiFlyerRoot.Child import com.shabinder.common.root.SpotiFlyerRoot.Dependencies import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch @@ -77,7 +77,7 @@ internal class SpotiFlyerRootImpl( instanceKeeper.ensureNeverFrozen() methods.value = dependencies.actions.freeze() /*Init App Launch & Authenticate Spotify Client*/ - initAppLaunchAndAuthenticateSpotify(dependencies.fetchPlatformQueryResult::authenticateSpotifyClient) + initAppLaunchAndAuthenticateSpotify(dependencies.fetchQuery::authenticateSpotifyClient) } private val router = @@ -128,6 +128,7 @@ internal class SpotiFlyerRootImpl( } } + @OptIn(DelicateCoroutinesApi::class) private fun initAppLaunchAndAuthenticateSpotify(authenticator: suspend () -> Unit) { GlobalScope.launch(dispatcherIO) { analytics.appLaunchEvent() @@ -150,10 +151,7 @@ private fun spotiFlyerMain(componentContext: ComponentContext, output: Consumer< componentContext = componentContext, dependencies = object : SpotiFlyerMain.Dependencies, Dependencies by dependencies { override val mainOutput: Consumer = output - override val dir: Dir = directories - override val mainAnalytics = object : SpotiFlyerMain.Analytics { - override fun donationDialogVisit() = analytics.donationDialogVisit() - } + override val mainAnalytics = object : SpotiFlyerMain.Analytics , Analytics by analytics {} } ) @@ -161,11 +159,8 @@ private fun spotiFlyerList(componentContext: ComponentContext, link: String, out SpotiFlyerList( componentContext = componentContext, dependencies = object : SpotiFlyerList.Dependencies, Dependencies by dependencies { - override val fetchQuery = fetchPlatformQueryResult - override val dir: Dir = directories override val link: String = link override val listOutput: Consumer = output - override val downloadProgressFlow = downloadProgressReport - override val listAnalytics = object : SpotiFlyerList.Analytics {} + override val listAnalytics = object : SpotiFlyerList.Analytics, Analytics by analytics {} } ) diff --git a/desktop/src/jvmMain/kotlin/Main.kt b/desktop/src/jvmMain/kotlin/Main.kt index fb3045f9..684b635b 100644 --- a/desktop/src/jvmMain/kotlin/Main.kt +++ b/desktop/src/jvmMain/kotlin/Main.kt @@ -27,12 +27,21 @@ import com.arkivanov.decompose.extensions.compose.jetbrains.rememberRootComponen import com.arkivanov.mvikotlin.core.lifecycle.LifecycleRegistry import com.arkivanov.mvikotlin.core.lifecycle.resume import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory -import com.shabinder.common.di.* +import com.shabinder.common.di.Dir +import com.shabinder.common.di.DownloadProgressFlow +import com.shabinder.common.di.FetchPlatformQueryResult +import com.shabinder.common.di.initKoin +import com.shabinder.common.di.isInternetAccessible +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.Actions import com.shabinder.common.models.PlatformActions import com.shabinder.common.models.TrackDetails import com.shabinder.common.root.SpotiFlyerRoot -import com.shabinder.common.uikit.* +import com.shabinder.common.uikit.SpotiFlyerColors +import com.shabinder.common.uikit.SpotiFlyerRootContent +import com.shabinder.common.uikit.SpotiFlyerShapes +import com.shabinder.common.uikit.SpotiFlyerTypography +import com.shabinder.common.uikit.colorOffWhite import com.shabinder.database.Database import kotlinx.coroutines.runBlocking import org.piwik.java.tracking.PiwikTracker @@ -79,10 +88,11 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = componentContext = componentContext, dependencies = object : SpotiFlyerRoot.Dependencies { override val storeFactory = DefaultStoreFactory - override val fetchPlatformQueryResult: FetchPlatformQueryResult = koin.get() - override val directories: Dir = koin.get() - override val database: Database? = directories.db - override val downloadProgressReport = DownloadProgressFlow + override val fetchQuery: FetchPlatformQueryResult = koin.get() + override val dir: Dir = koin.get() + override val database: Database? = dir.db + override val preferenceManager: PreferenceManager = koin.get() + override val downloadProgressFlow = DownloadProgressFlow override val actions: Actions = object: Actions { override val platformActions = object : PlatformActions {} @@ -100,7 +110,7 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = APPROVE_OPTION -> { val directory = fileChooser.selectedFile if(directory.canWrite()){ - directories.setDownloadDirectory(directory.absolutePath) + preferenceManager.setDownloadDirectory(directory.absolutePath) showPopUpMessage("Set New Download Directory:\n${directory.absolutePath}") } else { showPopUpMessage("Cant Write to Selected Directory!") @@ -137,10 +147,10 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = } override val analytics = object: SpotiFlyerRoot.Analytics { override fun appLaunchEvent() { - if(directories.isFirstLaunch) { + if(preferenceManager.isFirstLaunch) { // Enable Analytics on First Launch - directories.toggleAnalytics(true) - directories.firstLaunchDone() + preferenceManager.toggleAnalytics(true) + preferenceManager.firstLaunchDone() } tracker.trackAsync { eventName = "App Launch" diff --git a/settings.gradle.kts b/settings.gradle.kts index 3748628b..dcde5caa 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,6 +22,7 @@ include( ":common:root", ":common:main", ":common:list", + ":common:preference", ":common:data-models", ":common:dependency-injection", ":android", diff --git a/web-app/src/main/kotlin/App.kt b/web-app/src/main/kotlin/App.kt index 03d1ed52..785c1785 100644 --- a/web-app/src/main/kotlin/App.kt +++ b/web-app/src/main/kotlin/App.kt @@ -22,6 +22,7 @@ import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.shabinder.common.di.DownloadProgressFlow +import com.shabinder.common.di.preference.PreferenceManager import com.shabinder.common.models.Actions import com.shabinder.common.models.PlatformActions import com.shabinder.common.models.TrackDetails @@ -58,10 +59,11 @@ class App(props: AppProps): RComponent(props) { private val root = SpotiFlyerRoot(ctx, object : SpotiFlyerRoot.Dependencies { override val storeFactory: StoreFactory = LoggingStoreFactory(DefaultStoreFactory) - override val fetchPlatformQueryResult = dependencies.fetchPlatformQueryResult - override val directories = dependencies.directories - override val database: Database? = directories.db - override val downloadProgressReport = DownloadProgressFlow + override val fetchQuery = dependencies.fetchPlatformQueryResult + override val dir = dependencies.directories + override val preferenceManager: PreferenceManager = dependencies.preferenceManager + override val database: Database? = dir.db + override val downloadProgressFlow = DownloadProgressFlow override val actions = object : Actions { override val platformActions = object : PlatformActions {} diff --git a/web-app/src/main/kotlin/client.kt b/web-app/src/main/kotlin/client.kt index 996700ff..36661535 100644 --- a/web-app/src/main/kotlin/client.kt +++ b/web-app/src/main/kotlin/client.kt @@ -18,11 +18,12 @@ import co.touchlab.kermit.Kermit import com.shabinder.common.di.Dir import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.initKoin -import react.dom.render +import com.shabinder.common.di.preference.PreferenceManager import kotlinx.browser.document import kotlinx.browser.window import org.koin.core.component.KoinComponent import org.koin.core.component.get +import react.dom.render fun main() { window.onload = { @@ -38,10 +39,12 @@ object AppDependencies : KoinComponent { val logger: Kermit val directories: Dir val fetchPlatformQueryResult: FetchPlatformQueryResult + val preferenceManager: PreferenceManager init { initKoin() directories = get() logger = get() fetchPlatformQueryResult = get() + preferenceManager = get() } } \ No newline at end of file