diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index dc6ef57d..0185725f 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -66,7 +66,9 @@ dependencies {
implementation(Koin.android)
implementation(Koin.androidViewModel)
-
+ //DECOMPOSE
+ implementation(Decompose.decompose)
+ implementation(Decompose.extensionsCompose)
//Lifecycle
Versions.androidLifecycle.let{
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$it")
diff --git a/android/src/main/java/com/shabinder/android/App.kt b/android/src/main/java/com/shabinder/android/App.kt
new file mode 100644
index 00000000..7e2722eb
--- /dev/null
+++ b/android/src/main/java/com/shabinder/android/App.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Shabinder Singh
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.android
+
+import android.app.Application
+import com.shabinder.android.di.appModule
+import com.shabinder.common.database.appContext
+import com.shabinder.common.initKoin
+import org.koin.android.ext.koin.androidContext
+import org.koin.android.ext.koin.androidLogger
+import org.koin.core.KoinComponent
+
+class App: Application(), KoinComponent {
+ override fun onCreate() {
+ super.onCreate()
+
+ appContext = this
+
+ initKoin {
+ androidLogger()
+ androidContext(this@App)
+ modules(appModule)
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/shabinder/android/MainActivity.kt b/android/src/main/java/com/shabinder/android/MainActivity.kt
index f07388b3..a9f4b513 100644
--- a/android/src/main/java/com/shabinder/android/MainActivity.kt
+++ b/android/src/main/java/com/shabinder/android/MainActivity.kt
@@ -1,15 +1,14 @@
package com.shabinder.android
import android.os.Bundle
-import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.setContent
-import com.shabinder.common.spotify.authenticateSpotify
+import com.shabinder.android.di.appModule
+import com.shabinder.common.database.appContext
+import com.shabinder.common.initKoin
import com.shabinder.common.ui.SpotiFlyerMain
-import com.shabinder.common.youtube.YoutubeMusic
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
+import org.koin.android.ext.koin.androidLogger
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -17,9 +16,7 @@ class MainActivity : AppCompatActivity() {
setContent {
val scope = rememberCoroutineScope()
SpotiFlyerMain()
- scope.launch(Dispatchers.IO) {
- }
}
}
}
\ No newline at end of file
diff --git a/android/src/main/java/com/shabinder/android/SharedViewModel.kt b/android/src/main/java/com/shabinder/android/SharedViewModel.kt
new file mode 100644
index 00000000..e0fa5edd
--- /dev/null
+++ b/android/src/main/java/com/shabinder/android/SharedViewModel.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021 Shabinder Singh
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.android
+
+import android.content.Intent
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.graphics.Color
+import androidx.lifecycle.ViewModel
+import co.touchlab.kermit.Kermit
+import com.shabinder.common.DownloadStatus
+import com.shabinder.common.TrackDetails
+import com.shabinder.common.YoutubeProvider
+import com.shabinder.common.providers.GaanaProvider
+import com.shabinder.common.providers.SpotifyProvider
+import com.shabinder.database.Database
+import com.shabinder.spotiflyer.ui.colorPrimaryDark
+import com.tonyodev.fetch2.Status
+
+class SharedViewModel(
+ val database: Database,
+ val logger: Kermit,
+ val spotifyProvider: SpotifyProvider,
+ val gaanaProvider : GaanaProvider,
+ val youtubeProvider: YoutubeProvider
+) : ViewModel() {
+ var isAuthenticated by mutableStateOf(false)
+ private set
+
+ fun authenticated(s:Boolean) {
+ isAuthenticated = s
+ }
+
+ /*
+ * Nav Gives Error on YT links with ? sign
+ * */
+ var link by mutableStateOf("")
+ private set
+
+ fun updateLink(s:String) {
+ link = s
+ }
+
+
+ val trackList = mutableStateListOf()
+
+ fun updateTrackList(list:List){
+ trackList.clear()
+ trackList.addAll(list)
+ }
+ fun updateTrackStatus(position:Int, status: DownloadStatus){
+ if(position != -1){
+ val track = trackList[position].apply { downloaded = status }
+ trackList[position] = track
+ }
+ }
+
+ fun updateTrackStatus(intent: Intent){
+ val trackDetails = intent.getSerializableExtra("track") as TrackDetails?
+ trackDetails?.let {
+ val position: Int =
+ trackList.map { trackState -> trackState.title }.indexOf(it.title)
+ logger.d{"$position, ${intent.action} , ${it.title}"}
+ if (position != -1) {
+ trackList.getOrNull(position)?.let{ track ->
+ when (intent.action) {
+ Status.QUEUED.name -> {
+ track.downloaded = DownloadStatus.Queued
+ }
+ Status.FAILED.name -> {
+ track.downloaded = DownloadStatus.Failed
+ }
+ Status.DOWNLOADING.name -> {
+ track.downloaded = DownloadStatus.Downloading
+ }
+ "Progress" -> {
+ //Progress Update
+ track.progress = intent.getIntExtra("progress", 0)
+ track.downloaded = DownloadStatus.Downloading
+ }
+ "Converting" -> {
+ //Progress Update
+ track.downloaded = DownloadStatus.Converting
+ }
+ "track_download_completed" -> {
+ track.downloaded = DownloadStatus.Downloaded
+ }
+ }
+ trackList[position] = track
+ logger.d{"TrackListUpdated"}
+ }
+ }
+ }
+ }
+
+ var gradientColor by mutableStateOf(Color.Transparent)
+ private set
+
+ fun updateGradientColor(color: Color) {
+ gradientColor = color
+ }
+
+ fun resetGradient() {
+ gradientColor = colorPrimaryDark
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/shabinder/android/di/AppModule.kt b/android/src/main/java/com/shabinder/android/di/AppModule.kt
new file mode 100644
index 00000000..4a5a2101
--- /dev/null
+++ b/android/src/main/java/com/shabinder/android/di/AppModule.kt
@@ -0,0 +1,9 @@
+package com.shabinder.android.di
+
+import com.shabinder.android.SharedViewModel
+import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val appModule = module {
+ viewModel { SharedViewModel(get(),get(),get(),get(),get()) }
+}
diff --git a/android/src/main/java/com/shabinder/android/navigation/ComposeNavigation.kt b/android/src/main/java/com/shabinder/android/navigation/ComposeNavigation.kt
new file mode 100644
index 00000000..978defc0
--- /dev/null
+++ b/android/src/main/java/com/shabinder/android/navigation/ComposeNavigation.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 Shabinder Singh
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.android.navigation
+
+import androidx.compose.runtime.Composable
+import androidx.navigation.NavController
+import androidx.navigation.NavHostController
+import androidx.navigation.NavType
+import androidx.navigation.compose.*
+import com.shabinder.spotiflyer.MainActivity
+import com.shabinder.spotiflyer.providers.GaanaProvider
+import com.shabinder.spotiflyer.providers.SpotifyProvider
+import com.shabinder.spotiflyer.providers.YoutubeProvider
+import com.shabinder.common.ui.home.Home
+import com.shabinder.spotiflyer.ui.tracklist.TrackList
+import com.shabinder.spotiflyer.utils.sharedViewModel
+
+@Composable
+fun ComposeNavigation(
+ mainActivity: MainActivity,
+ navController: NavHostController,
+ spotifyProvider: SpotifyProvider,
+ gaanaProvider: GaanaProvider,
+ youtubeProvider: YoutubeProvider,
+ ) {
+ NavHost(
+ navController = navController,
+ startDestination = "home"
+ ) {
+
+ //HomeScreen - Starting Point
+ composable("home") {
+ Home(
+ navController = navController,
+ mainActivity,
+ )
+ }
+
+ //Spotify Screen
+ //Argument `link` = Link of Track/Album/Playlist
+ composable(
+ "track_list/{link}",
+ arguments = listOf(navArgument("link") { type = NavType.StringType })
+ ) {
+ TrackList(
+ fullLink = it.arguments?.getString("link") ?: "error",
+ navController = navController,
+ spotifyProvider,
+ gaanaProvider,
+ youtubeProvider
+ )
+ }
+ }
+}
+
+fun NavController.navigateToTrackList(link:String, singleInstance: Boolean = true, inclusive:Boolean = false) {
+ sharedViewModel.updateLink(link)
+ navigate("track_list/$link") {
+ launchSingleTop = singleInstance
+ popUpTo(route = "home") {
+ this.inclusive = inclusive
+ }
+ }
+}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index f2b06387..b64b99d9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,6 +9,7 @@ allprojects {
mavenCentral()
maven(url = "https://jitpack.io")
maven(url = "https://dl.bintray.com/ekito/koin")
+ maven(url = "https://kotlin.bintray.com/kotlinx/")
maven(url = "https://kotlin.bintray.com/kotlin-js-wrappers/")
maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev")
flatDir {
diff --git a/buildSrc/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/buildSrc/src/main/kotlin/Deps.kt
deleted file mode 100644
index 40d5463d..00000000
--- a/buildSrc/buildSrc/src/main/kotlin/Deps.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-object Deps {
- object ArkIvanov {
- object MVIKotlin {
- private const val VERSION = "2.0.0"
- const val rx = "com.arkivanov.mvikotlin:rx:$VERSION"
- const val mvikotlin = "com.arkivanov.mvikotlin:mvikotlin:$VERSION"
- const val mvikotlinMain = "com.arkivanov.mvikotlin:mvikotlin-main:$VERSION"
- const val mvikotlinMainIosX64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosx64:$VERSION"
- const val mvikotlinMainIosArm64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosarm64:$VERSION"
- const val mvikotlinLogging = "com.arkivanov.mvikotlin:mvikotlin-logging:$VERSION"
- const val mvikotlinTimeTravel = "com.arkivanov.mvikotlin:mvikotlin-timetravel:$VERSION"
- const val mvikotlinExtensionsReaktive = "com.arkivanov.mvikotlin:mvikotlin-extensions-reaktive:$VERSION"
- }
-
- object Decompose {
- private const val VERSION = "0.1.6"
- const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
- const val decomposeIosX64 = "com.arkivanov.decompose:decompose-iosx64:$VERSION"
- const val decomposeIosArm64 = "com.arkivanov.decompose:decompose-iosarm64:$VERSION"
- const val extensionsCompose = "com.arkivanov.decompose:extensions-compose-jetbrains:$VERSION"
- }
- }
-
- object Badoo {
- object Reaktive {
- private const val VERSION = "1.1.19"
- const val reaktive = "com.badoo.reaktive:reaktive:$VERSION"
- const val reaktiveTesting = "com.badoo.reaktive:reaktive-testing:$VERSION"
- const val utils = "com.badoo.reaktive:utils:$VERSION"
- const val coroutinesInterop = "com.badoo.reaktive:coroutines-interop:$VERSION"
- }
- }
-}
diff --git a/buildSrc/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/buildSrc/src/main/kotlin/Versions.kt
index 5ee763ee..7c161a05 100644
--- a/buildSrc/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/buildSrc/src/main/kotlin/Versions.kt
@@ -63,6 +63,33 @@ object JetBrains {
const val materialIcon = "androidx.compose.material:material-icons-extended:${Versions.composeVersion}"
}
}
+object Decompose {
+ private const val VERSION = "0.1.7"
+ const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
+ const val decomposeIosX64 = "com.arkivanov.decompose:decompose-iosx64:$VERSION"
+ const val decomposeIosArm64 = "com.arkivanov.decompose:decompose-iosarm64:$VERSION"
+ const val extensionsCompose = "com.arkivanov.decompose:extensions-compose-jetbrains:$VERSION"
+}
+object MVIKotlin {
+ private const val VERSION = "2.0.0"
+ const val rx = "com.arkivanov.mvikotlin:rx:$VERSION"
+ const val mvikotlin = "com.arkivanov.mvikotlin:mvikotlin:$VERSION"
+ const val mvikotlinMain = "com.arkivanov.mvikotlin:mvikotlin-main:$VERSION"
+ const val mvikotlinMainIosX64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosx64:$VERSION"
+ const val mvikotlinMainIosArm64 = "com.arkivanov.mvikotlin:mvikotlin-main-iosarm64:$VERSION"
+ const val mvikotlinLogging = "com.arkivanov.mvikotlin:mvikotlin-logging:$VERSION"
+ const val mvikotlinTimeTravel = "com.arkivanov.mvikotlin:mvikotlin-timetravel:$VERSION"
+ const val mvikotlinExtensionsReaktive = "com.arkivanov.mvikotlin:mvikotlin-extensions-reaktive:$VERSION"
+}
+object Badoo {
+ object Reaktive {
+ private const val VERSION = "1.1.19"
+ const val reaktive = "com.badoo.reaktive:reaktive:$VERSION"
+ const val reaktiveTesting = "com.badoo.reaktive:reaktive-testing:$VERSION"
+ const val utils = "com.badoo.reaktive:utils:$VERSION"
+ const val coroutinesInterop = "com.badoo.reaktive:coroutines-interop:$VERSION"
+ }
+}
object Ktor {
val clientCore = "io.ktor:ktor-client-core:${Versions.ktor}"
val clientJson = "io.ktor:ktor-client-json:${Versions.ktor}"
diff --git a/common/compose-ui/build.gradle.kts b/common/compose-ui/build.gradle.kts
index 660a114f..b138ff54 100644
--- a/common/compose-ui/build.gradle.kts
+++ b/common/compose-ui/build.gradle.kts
@@ -7,8 +7,14 @@ kotlin {
sourceSets {
commonMain {
dependencies {
- implementation(Deps.ArkIvanov.Decompose.decompose)
- implementation(Deps.ArkIvanov.Decompose.extensionsCompose)
+ implementation(project(":common:dependency-injection"))
+ implementation(project(":common:data-models"))
+ implementation(project(":common:database"))
+ implementation(MVIKotlin.mvikotlin)
+ implementation(MVIKotlin.mvikotlinExtensionsReaktive)
+ implementation(Badoo.Reaktive.reaktive)
+ implementation(Decompose.decompose)
+ implementation(Decompose.extensionsCompose)
}
}
}
diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt
new file mode 100644
index 00000000..67cd2422
--- /dev/null
+++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMain.kt
@@ -0,0 +1,30 @@
+package com.shabinder.common.main
+
+import com.arkivanov.decompose.value.Value
+import com.arkivanov.mvikotlin.core.store.StoreFactory
+import com.badoo.reaktive.base.Consumer
+import com.shabinder.common.DownloadRecord
+import com.shabinder.database.Database
+
+interface SpotiFlyerMain {
+
+ val models: Value
+
+ fun onDownloadRecordClicked(link: String)
+
+ fun onInputLinkChanged(link: String)
+
+ interface Dependencies {
+ val storeFactory: StoreFactory
+ val database: Database
+ val mainOutput: Consumer