diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index dfd33500..8f935e16 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -121,13 +121,14 @@ dependencies {
implementation(MVIKotlin.mvikotlinTimeTravel)
// Extras
- Extras.Android.apply {
+ with(Extras.Android) {
implementation(Acra.notification)
implementation(Acra.http)
implementation(appUpdator)
implementation(matomo)
}
+ implementation(Extras.kermit)
//implementation("com.jakewharton.timber:timber:4.7.1")
implementation("dev.icerock.moko:parcelize:0.7.0")
implementation("com.github.shabinder:storage-chooser:2.0.4.45")
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 5fa70abf..04d4f636 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -72,6 +72,6 @@
-
+
\ No newline at end of file
diff --git a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
index 1344566c..0bd21b8d 100644
--- a/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
+++ b/android/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
@@ -17,15 +17,16 @@
package com.shabinder.spotiflyer
import android.annotation.SuppressLint
-import android.content.BroadcastReceiver
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
-import android.content.IntentFilter
+import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Bundle
+import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import androidx.activity.ComponentActivity
@@ -51,18 +52,17 @@ 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.worker.ForegroundService
import com.shabinder.common.models.Actions
import com.shabinder.common.models.DownloadStatus
import com.shabinder.common.models.PlatformActions
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
-import com.shabinder.common.models.Status
import com.shabinder.common.models.TrackDetails
import com.shabinder.common.models.methods
import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.root.SpotiFlyerRoot.Analytics
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.uikit.*
+import com.shabinder.spotiflyer.service.ForegroundService
import com.shabinder.spotiflyer.ui.AnalyticsDialog
import com.shabinder.spotiflyer.ui.NetworkDialog
import com.shabinder.spotiflyer.ui.PermissionDialog
@@ -82,12 +82,16 @@ class MainActivity : ComponentActivity() {
private val callBacks: SpotiFlyerRootCallBacks get() = root.callBacks
private val trackStatusFlow = MutableSharedFlow>(1)
private var permissionGranted = mutableStateOf(true)
- private lateinit var updateUIReceiver: BroadcastReceiver
- private lateinit var queryReceiver: BroadcastReceiver
private val internetAvailability by lazy { ConnectionLiveData(applicationContext) }
private val tracker get() = (application as App).tracker
private val visibleChild get(): SpotiFlyerRoot.Child = root.routerState.value.activeChild.instance
+ // Variable for storing instance of our service class
+ var foregroundService: ForegroundService? = null
+
+ // Boolean to check if our activity is bound to service or not
+ var isServiceBound: Boolean? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// This app draws behind the system bars, so we want to handle fitting system windows
@@ -162,8 +166,62 @@ class MainActivity : ComponentActivity() {
TrackHelper.track().download().with(tracker)
}
handleIntentFromExternalActivity()
+
+ initForegroundService()
}
+ /*START: Foreground Service Handlers*/
+ private fun initForegroundService() {
+ // Start and then Bind to the Service
+ ContextCompat.startForegroundService(
+ this@MainActivity,
+ Intent(this, ForegroundService::class.java)
+ )
+ bindService()
+ }
+
+ /**
+ * Interface for getting the instance of binder from our service class
+ * So client can get instance of our service class and can directly communicate with it.
+ */
+ private val serviceConnection = object : ServiceConnection {
+ val tag = "Service Connection"
+
+ override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {
+ Log.d(tag, "connected to service.")
+ // We've bound to MyService, cast the IBinder and get MyBinder instance
+ val binder = iBinder as ForegroundService.DownloadServiceBinder
+ foregroundService = binder.service
+ isServiceBound = true
+ lifecycleScope.launch {
+ foregroundService?.trackStatusFlowMap?.statusFlow?.let {
+ trackStatusFlow.emitAll(it.conflate())
+ }
+ }
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ Log.d(tag, "disconnected from service.")
+ isServiceBound = false
+ }
+ }
+
+ /*Used to bind to our service class*/
+ private fun bindService() {
+ Intent(this, ForegroundService::class.java).also { intent ->
+ bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
+ }
+ }
+
+ /*Used to unbind from our service class*/
+ private fun unbindService() {
+ Intent(this, ForegroundService::class.java).also {
+ unbindService(serviceConnection)
+ }
+ }
+ /*END: Foreground Service Handlers*/
+
+
@Composable
private fun isInternetAvailableState(): State {
return internetAvailability.observeAsState()
@@ -206,12 +264,9 @@ class MainActivity : ComponentActivity() {
)
}
- override fun sendTracksToService(array: ArrayList) {
- for (list in array.chunked(50)) {
- val serviceIntent = Intent(this@MainActivity, ForegroundService::class.java)
- serviceIntent.putParcelableArrayListExtra("object", list as ArrayList)
- ContextCompat.startForegroundService(this@MainActivity, serviceIntent)
- }
+ override fun sendTracksToService(array: List) {
+ if (foregroundService == null) initForegroundService()
+ foregroundService?.downloadAllTracks(array)
}
}
@@ -296,10 +351,16 @@ class MainActivity : ComponentActivity() {
)
private fun queryActiveTracks() {
- val serviceIntent = Intent(this@MainActivity, ForegroundService::class.java).apply {
- action = "query"
+ lifecycleScope.launch {
+ foregroundService?.trackStatusFlowMap?.let { tracksStatus ->
+ trackStatusFlow.emit(tracksStatus)
+ }
}
- ContextCompat.startForegroundService(this@MainActivity, serviceIntent)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ queryActiveTracks()
}
@Suppress("DEPRECATION")
@@ -357,80 +418,6 @@ class MainActivity : ComponentActivity() {
}
}
- /*
- * Broadcast Handlers
- * */
- private fun initializeBroadcast(){
- val intentFilter = IntentFilter().apply {
- addAction(Status.QUEUED.name)
- addAction(Status.FAILED.name)
- addAction(Status.DOWNLOADING.name)
- addAction(Status.COMPLETED.name)
- addAction("Progress")
- addAction("Converting")
- }
- updateUIReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- //Update Flow with latest details
- if (intent != null) {
- val trackDetails = intent.getParcelableExtra("track")
- trackDetails?.let { track ->
- lifecycleScope.launch {
- val latestMap = trackStatusFlow.replayCache.getOrElse(0
- ) { hashMapOf() }.apply {
- this[track.title] = when (intent.action) {
- Status.QUEUED.name -> DownloadStatus.Queued
- Status.FAILED.name -> DownloadStatus.Failed
- Status.DOWNLOADING.name -> DownloadStatus.Downloading()
- "Progress" -> DownloadStatus.Downloading(intent.getIntExtra("progress", 0))
- "Converting" -> DownloadStatus.Converting
- Status.COMPLETED.name -> DownloadStatus.Downloaded
- else -> DownloadStatus.NotDownloaded
- }
- }
- trackStatusFlow.emit(latestMap)
- Log.i("Track Update",track.title + track.downloaded.toString())
- }
- }
- }
- }
- }
- val queryFilter = IntentFilter().apply { addAction("query_result") }
- queryReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- //UI update here
- if (intent != null){
- @Suppress("UNCHECKED_CAST")
- val trackList = intent.getSerializableExtra("tracks") as? HashMap?
- trackList?.let { list ->
- Log.i("Service Response", "${list.size} Tracks Active")
- lifecycleScope.launch {
- trackStatusFlow.emit(list)
- }
- }
- }
- }
- }
- registerReceiver(updateUIReceiver, intentFilter)
- registerReceiver(queryReceiver, queryFilter)
- }
-
- override fun onResume() {
- super.onResume()
- initializeBroadcast()
- if(visibleChild is SpotiFlyerRoot.Child.List) {
- // Update Track List Statuses when Returning to App
- queryActiveTracks()
- }
- }
-
- override fun onPause() {
- super.onPause()
- unregisterReceiver(updateUIReceiver)
- unregisterReceiver(queryReceiver)
- }
-
-
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntentFromExternalActivity(intent)
@@ -455,6 +442,11 @@ class MainActivity : ComponentActivity() {
}
}
+ override fun onDestroy() {
+ super.onDestroy()
+ unbindService()
+ }
+
companion object {
const val disableDozeCode = 1223
}
diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt b/android/src/main/java/com/shabinder/spotiflyer/service/ForegroundService.kt
similarity index 76%
rename from common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt
rename to android/src/main/java/com/shabinder/spotiflyer/service/ForegroundService.kt
index f2bf595c..dee184a9 100644
--- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/ForegroundService.kt
+++ b/android/src/main/java/com/shabinder/spotiflyer/service/ForegroundService.kt
@@ -14,7 +14,7 @@
* along with this program. If not, see .
*/
-package com.shabinder.common.di.worker
+package com.shabinder.spotiflyer.service
import android.annotation.SuppressLint
import android.app.DownloadManager
@@ -26,6 +26,7 @@ import android.app.PendingIntent.FLAG_CANCEL_CURRENT
import android.app.Service
import android.content.Context
import android.content.Intent
+import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
@@ -40,12 +41,13 @@ import com.shabinder.common.di.downloadFile
import com.shabinder.common.di.utils.ParallelExecutor
import com.shabinder.common.models.DownloadResult
import com.shabinder.common.models.DownloadStatus
-import com.shabinder.common.models.Status
import com.shabinder.common.models.TrackDetails
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
@@ -68,7 +70,8 @@ class ForegroundService : Service(), CoroutineScope {
override val coroutineContext: CoroutineContext
get() = serviceJob + Dispatchers.IO
- private val allTracksStatus = hashMapOf()
+ val trackStatusFlowMap = TrackStatusFlowMap(MutableSharedFlow(replay = 1),this)
+
private var messageList = mutableListOf("", "", "", "", "")
private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false
@@ -80,7 +83,16 @@ class ForegroundService : Service(), CoroutineScope {
private val logger: Kermit by inject()
private val dir: Dir by inject()
- override fun onBind(intent: Intent): IBinder? = null
+
+ inner class DownloadServiceBinder : Binder() {
+ // Return this instance of MyService so clients can call public methods
+ val service: ForegroundService
+ get() =// Return this instance of Foreground Service so clients can call public methods
+ this@ForegroundService
+ }
+ private val myBinder: IBinder = DownloadServiceBinder()
+
+ override fun onBind(intent: Intent): IBinder = myBinder
@SuppressLint("UnspecifiedImmutableFlag")
override fun onCreate() {
@@ -110,31 +122,13 @@ class ForegroundService : Service(), CoroutineScope {
"query" -> {
val response = Intent().apply {
action = "query_result"
- synchronized(allTracksStatus) {
- putExtra("tracks", allTracksStatus)
+ synchronized(trackStatusFlowMap) {
+ putExtra("tracks", trackStatusFlowMap)
}
}
sendBroadcast(response)
}
}
-
- val downloadObjects: ArrayList? = (
- it.getParcelableArrayListExtra("object") ?: it.extras?.getParcelableArrayList(
- "object"
- )
- )
-
- downloadObjects?.let { list ->
- downloadObjects.size.let { size ->
- total += size
- isSingleDownload = (size == 1)
- }
- list.forEach { track ->
- allTracksStatus[track.title] = DownloadStatus.Queued
- }
- updateNotification()
- downloadAllTracks(list)
- }
}
// Wake locks and misc tasks from here :
return if (isServiceStarted) {
@@ -156,8 +150,16 @@ class ForegroundService : Service(), CoroutineScope {
/**
* Function To Download All Tracks Available in a List
**/
- private fun downloadAllTracks(trackList: List) {
+ fun downloadAllTracks(trackList: List) {
+
+ trackList.size.also { size ->
+ total += size
+ isSingleDownload = (size == 1)
+ updateNotification()
+ }
+
trackList.forEach {
+ trackStatusFlowMap[it.title] = DownloadStatus.Queued
launch(Dispatchers.IO) {
downloadService.execute {
fetcher.findMp3DownloadLink(it).fold(
@@ -165,10 +167,9 @@ class ForegroundService : Service(), CoroutineScope {
enqueueDownload(url, it)
},
failure = { _ ->
- sendTrackBroadcast(Status.FAILED.name, it)
failed++
updateNotification()
- allTracksStatus[it.title] = DownloadStatus.Failed
+ trackStatusFlowMap[it.title] = DownloadStatus.Failed
}
)
}
@@ -180,24 +181,20 @@ class ForegroundService : Service(), CoroutineScope {
// Initiating Download
addToNotification("Downloading ${track.title}")
logger.d(tag) { "${track.title} Download Started" }
- allTracksStatus[track.title] = DownloadStatus.Downloading()
- sendTrackBroadcast(Status.DOWNLOADING.name, track)
+ trackStatusFlowMap[track.title] = DownloadStatus.Downloading()
// Enqueueing Download
downloadFile(url).collect {
when (it) {
is DownloadResult.Error -> {
- launch {
- logger.d(tag) { it.message }
- removeFromNotification("Downloading ${track.title}")
- failed++
- updateNotification()
- sendTrackBroadcast(Status.FAILED.name, track)
- }
+ logger.d(tag) { it.message }
+ removeFromNotification("Downloading ${track.title}")
+ failed++
+ updateNotification()
}
is DownloadResult.Progress -> {
- allTracksStatus[track.title] = DownloadStatus.Downloading(it.progress)
+ trackStatusFlowMap[track.title] = DownloadStatus.Downloading(it.progress)
logger.d(tag) { "${track.title} Progress: ${it.progress} %" }
val intent = Intent().apply {
@@ -209,26 +206,31 @@ class ForegroundService : Service(), CoroutineScope {
}
is DownloadResult.Success -> {
- try {
- // Save File and Embed Metadata
- val job = launch(Dispatchers.Default) { dir.saveFileWithMetadata(it.byteArray, track) {} }
- allTracksStatus[track.title] = DownloadStatus.Converting
- sendTrackBroadcast("Converting", track)
- addToNotification("Processing ${track.title}")
- job.invokeOnCompletion {
- converted++
- allTracksStatus[track.title] = DownloadStatus.Downloaded
- sendTrackBroadcast(Status.COMPLETED.name, track)
- removeFromNotification("Processing ${track.title}")
+ coroutineScope {
+ try {
+ // Save File and Embed Metadata
+ val job = launch(Dispatchers.Default) { dir.saveFileWithMetadata(it.byteArray, track) {} }
+
+ // Send Converting Status
+ trackStatusFlowMap[track.title] = DownloadStatus.Converting
+ addToNotification("Processing ${track.title}")
+
+ // All Processing Completed for this Track
+ job.invokeOnCompletion {
+ converted++
+ trackStatusFlowMap[track.title] = DownloadStatus.Downloaded
+ removeFromNotification("Processing ${track.title}")
+ }
+ logger.d(tag) { "${track.title} Download Completed" }
+ downloaded++
+ } catch (e: Exception) {
+ e.printStackTrace()
+ // Download Failed
+ logger.d(tag) { "${track.title} Download Failed! Error:Fetch!!!!" }
+ failed++
}
- logger.d(tag) { "${track.title} Download Completed" }
- downloaded++
- } catch (e: Exception) {
- // Download Failed
- logger.d(tag) { "${track.title} Download Failed! Error:Fetch!!!!" }
- failed++
+ removeFromNotification("Downloading ${track.title}")
}
- removeFromNotification("Downloading ${track.title}")
}
}
}
@@ -270,7 +272,7 @@ class ForegroundService : Service(), CoroutineScope {
messageList = mutableListOf("Cleaning And Exiting", "", "", "", "")
downloadService.close()
updateNotification()
- cleanFiles(File(dir.defaultDir()), logger)
+ cleanFiles(File(dir.defaultDir()))
// TODO cleanFiles(File(dir.imageCacheDir()))
messageList = mutableListOf("", "", "", "", "")
releaseWakeLock()
@@ -336,12 +338,4 @@ class ForegroundService : Service(), CoroutineScope {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify(notificationId, getNotification())
}
-
- private fun sendTrackBroadcast(action: String, track: TrackDetails) {
- val intent = Intent().apply {
- setAction(action)
- putExtra("track", track)
- }
- this@ForegroundService.sendBroadcast(intent)
- }
}
diff --git a/android/src/main/java/com/shabinder/spotiflyer/service/TrackStatusFlowMap.kt b/android/src/main/java/com/shabinder/spotiflyer/service/TrackStatusFlowMap.kt
new file mode 100644
index 00000000..be4bcab7
--- /dev/null
+++ b/android/src/main/java/com/shabinder/spotiflyer/service/TrackStatusFlowMap.kt
@@ -0,0 +1,17 @@
+package com.shabinder.spotiflyer.service
+
+import com.shabinder.common.models.DownloadStatus
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.launch
+
+class TrackStatusFlowMap(
+ val statusFlow: MutableSharedFlow>,
+ private val scope: CoroutineScope
+): HashMap() {
+ override fun put(key: String, value: DownloadStatus): DownloadStatus? {
+ val res = super.put(key, value)
+ scope.launch { statusFlow.emit(this@TrackStatusFlowMap) }
+ return res
+ }
+}
\ No newline at end of file
diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/Utils.kt b/android/src/main/java/com/shabinder/spotiflyer/service/Utils.kt
similarity index 61%
rename from common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/Utils.kt
rename to android/src/main/java/com/shabinder/spotiflyer/service/Utils.kt
index 06c26c80..309e68fd 100644
--- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/worker/Utils.kt
+++ b/android/src/main/java/com/shabinder/spotiflyer/service/Utils.kt
@@ -1,22 +1,22 @@
-package com.shabinder.common.di.worker
+package com.shabinder.spotiflyer.service
-import co.touchlab.kermit.Kermit
+import android.util.Log
import java.io.File
/**
* Cleaning All Residual Files except Mp3 Files
**/
-fun cleanFiles(dir: File, logger: Kermit) {
+fun cleanFiles(dir: File) {
try {
- logger.d("File Cleaning") { "Starting Cleaning in ${dir.path} " }
+ Log.d("File Cleaning","Starting Cleaning in ${dir.path} ")
val fList = dir.listFiles()
fList?.let {
for (file in fList) {
if (file.isDirectory) {
- cleanFiles(file, logger)
+ cleanFiles(file)
} else if (file.isFile) {
if (file.path.toString().substringAfterLast(".") != "mp3") {
- logger.d("Files Cleaning") { "Cleaning ${file.path}" }
+ Log.d("Files Cleaning","Cleaning ${file.path}")
file.delete()
}
}
@@ -24,3 +24,4 @@ fun cleanFiles(dir: File, logger: Kermit) {
}
} catch (e: Exception) { e.printStackTrace() }
}
+
diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt
index af210499..72dce041 100644
--- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt
+++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/SpotiFlyerListUi.kt
@@ -17,12 +17,32 @@
package com.shabinder.common.uikit
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.material.*
-import androidx.compose.runtime.*
+import androidx.compose.material.CircularProgressIndicator
+import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.material.ExtendedFloatingActionButton
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -53,6 +73,7 @@ fun SpotiFlyerListContent(
component.onBackPressed()
}
}
+
Box(modifier = modifier.fillMaxSize()) {
val result = model.queryResult
if (result == null) {
diff --git a/common/data-models/src/androidMain/kotlin/com.shabinder.common.models/AndroidPlatformActions.kt b/common/data-models/src/androidMain/kotlin/com.shabinder.common.models/AndroidPlatformActions.kt
index 6fd52fd8..0d6adde2 100644
--- a/common/data-models/src/androidMain/kotlin/com.shabinder.common.models/AndroidPlatformActions.kt
+++ b/common/data-models/src/androidMain/kotlin/com.shabinder.common.models/AndroidPlatformActions.kt
@@ -14,7 +14,7 @@ actual interface PlatformActions {
fun addToLibrary(path: String)
- fun sendTracksToService(array: ArrayList)
+ fun sendTracksToService(array: List)
}
actual val StubPlatformActions = object : PlatformActions {
@@ -24,5 +24,5 @@ actual val StubPlatformActions = object : PlatformActions {
override fun addToLibrary(path: String) {}
- override fun sendTracksToService(array: ArrayList) {}
+ override fun sendTracksToService(array: List) {}
}
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 ad7d8bf9..7820eb92 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
@@ -23,11 +23,9 @@ import com.shabinder.common.di.utils.removeIllegalChars
import com.shabinder.common.models.DownloadResult
import com.shabinder.common.models.TrackDetails
import com.shabinder.database.Database
-import io.ktor.client.request.HttpRequestBuilder
-import io.ktor.client.request.get
-import io.ktor.client.statement.HttpStatement
-import io.ktor.http.contentLength
-import io.ktor.http.isSuccess
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlin.math.roundToInt
@@ -105,7 +103,7 @@ suspend fun downloadFile(url: String): Flow {
var offset = 0
do {
// Set Length optimally, after how many kb you want a progress update, now it 0.25mb
- val currentRead = response.content.readAvailable(data, offset, 250000)
+ val currentRead = response.content.readAvailable(data, offset, 2_50_000)
offset += currentRead
val progress = (offset * 100f / data.size).roundToInt()
emit(DownloadResult.Progress(progress))
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 642a3443..ede4efee 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
@@ -18,6 +18,7 @@ package com.shabinder.common.list.integration
import co.touchlab.stately.ensureNeverFrozen
import com.arkivanov.decompose.ComponentContext
+import com.arkivanov.decompose.lifecycle.doOnResume
import com.arkivanov.decompose.value.Value
import com.shabinder.common.caching.Cache
import com.shabinder.common.di.Picture
@@ -38,6 +39,9 @@ internal class SpotiFlyerListImpl(
init {
instanceKeeper.ensureNeverFrozen()
+ lifecycle.doOnResume {
+ onRefreshTracksStatuses()
+ }
}
private val store =
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 c1459231..5d9e148a 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
@@ -60,7 +60,7 @@ internal class SpotiFlyerListStoreProvider(
data class UpdateTrackList(val list: List) : Result()
data class UpdateTrackItem(val item: TrackDetails) : Result()
data class ErrorOccurred(val error: Throwable) : Result()
- data class AskForDonation(val isAllowed: Boolean) : Result()
+ data class AskForSupport(val isAllowed: Boolean) : Result()
}
private inner class ExecutorImpl : SuspendExecutor() {
@@ -73,7 +73,7 @@ internal class SpotiFlyerListStoreProvider(
logger.d(message = "Database List Last ID: $it", tag = "Database Last ID")
val offset = dir.getDonationOffset
dispatch(
- Result.AskForDonation(
+ Result.AskForSupport(
// Every 3rd Interval or After some offset
isAllowed = offset < 4 && (it % offset == 0L)
)
@@ -81,7 +81,7 @@ internal class SpotiFlyerListStoreProvider(
}
downloadProgressFlow.collect { map ->
- logger.d(map.size.toString(), "ListStore: flow Updated")
+ // logger.d(map.size.toString(), "ListStore: flow Updated")
val updatedTrackList = getState().trackList.updateTracksStatuses(map)
if (updatedTrackList.isNotEmpty()) dispatch(Result.UpdateTrackList(updatedTrackList))
}
@@ -131,7 +131,7 @@ internal class SpotiFlyerListStoreProvider(
is Result.UpdateTrackList -> copy(trackList = result.list)
is Result.UpdateTrackItem -> updateTrackItem(result.item)
is Result.ErrorOccurred -> copy(errorOccurred = result.error)
- is Result.AskForDonation -> copy(askForDonation = result.isAllowed)
+ is Result.AskForSupport -> copy(askForDonation = result.isAllowed)
}
private fun State.updateTrackItem(item: TrackDetails): State {