mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-12-22 20:57:54 +01:00
Progress bars Added
This commit is contained in:
parent
0a2cd5400a
commit
dd0fd06036
@ -1,8 +1,10 @@
|
||||
package com.shabinder.spotiflyer
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@ -27,6 +29,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.example.jetcaster.util.verticalGradientScrim
|
||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||
import com.shabinder.spotiflyer.navigation.ComposeNavigation
|
||||
import com.shabinder.spotiflyer.navigation.navigateToTrackList
|
||||
import com.shabinder.spotiflyer.networking.SpotifyServiceTokenRequest
|
||||
@ -35,6 +38,7 @@ import com.shabinder.spotiflyer.ui.appNameStyle
|
||||
import com.shabinder.spotiflyer.ui.colorOffWhite
|
||||
import com.shabinder.spotiflyer.utils.*
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tonyodev.fetch2.Status
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
|
||||
import dev.chrisbanes.accompanist.insets.statusBarsHeight
|
||||
@ -47,6 +51,8 @@ import javax.inject.Inject
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var navController: NavHostController
|
||||
private lateinit var updateUIReceiver: BroadcastReceiver
|
||||
private lateinit var queryReceiver: BroadcastReceiver
|
||||
@Inject lateinit var moshi: Moshi
|
||||
@Inject lateinit var spotifyServiceTokenRequest: SpotifyServiceTokenRequest
|
||||
|
||||
@ -102,6 +108,56 @@ class MainActivity : AppCompatActivity() {
|
||||
handleIntentFromExternalActivity(intent)
|
||||
}
|
||||
|
||||
private fun initializeBroadcast(){
|
||||
val intentFilter = IntentFilter().apply {
|
||||
addAction(Status.QUEUED.name)
|
||||
addAction(Status.FAILED.name)
|
||||
addAction(Status.DOWNLOADING.name)
|
||||
addAction("Progress")
|
||||
addAction("Converting")
|
||||
addAction("track_download_completed")
|
||||
}
|
||||
updateUIReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
//UI update here
|
||||
if (intent != null) {
|
||||
sharedViewModel.updateTrackStatus(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
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<String, DownloadStatus>?
|
||||
trackList?.let { list ->
|
||||
log("Service Response", "${list.size} Tracks Active")
|
||||
for (it in list) {
|
||||
val position: Int = sharedViewModel.trackList.map { it.title }.indexOf(it.key)
|
||||
log("BroadCast Received","$position, ${it.value} , ${it.key}")
|
||||
sharedViewModel.updateTrackStatus(position,it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
registerReceiver(updateUIReceiver, intentFilter)
|
||||
registerReceiver(queryReceiver, queryFilter)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
initializeBroadcast()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
unregisterReceiver(updateUIReceiver)
|
||||
unregisterReceiver(queryReceiver)
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
fun disableDozeMode() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
@ -17,21 +17,23 @@
|
||||
|
||||
package com.shabinder.spotiflyer
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import android.content.Intent
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.hilt.lifecycle.ViewModelInject
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.github.kiulian.downloader.YoutubeDownloader
|
||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||
import com.shabinder.spotiflyer.models.TrackDetails
|
||||
import com.shabinder.spotiflyer.networking.GaanaInterface
|
||||
import com.shabinder.spotiflyer.networking.SpotifyService
|
||||
import com.shabinder.spotiflyer.ui.colorPrimaryDark
|
||||
import dagger.hilt.android.scopes.ActivityRetainedScoped
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import com.shabinder.spotiflyer.utils.log
|
||||
import com.tonyodev.fetch2.Status
|
||||
|
||||
@ActivityRetainedScoped
|
||||
class SharedViewModel @ViewModelInject constructor(
|
||||
val databaseDAO: DatabaseDAO,
|
||||
val spotifyService: SpotifyService,
|
||||
@ -45,6 +47,59 @@ class SharedViewModel @ViewModelInject constructor(
|
||||
isAuthenticated = s
|
||||
}
|
||||
|
||||
|
||||
val trackList = mutableStateListOf<TrackDetails>()
|
||||
|
||||
fun updateTrackList(list:List<TrackDetails>){
|
||||
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.getParcelableExtra<TrackDetails?>("track")
|
||||
trackDetails?.let {
|
||||
val position: Int =
|
||||
trackList.map { trackState -> trackState.title }.indexOf(it.title)
|
||||
// log("TrackList", trackList.value.joinToString("\n") { trackState -> trackState.title })
|
||||
log("BroadCast Received", "$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
|
||||
log("SharedVM","TrackListUpdated")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var gradientColor by mutableStateOf(colorPrimaryDark)
|
||||
private set
|
||||
|
||||
|
@ -1,19 +1,14 @@
|
||||
package com.shabinder.spotiflyer.ui.tracklist
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
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.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@ -29,7 +24,6 @@ import com.shabinder.spotiflyer.R
|
||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||
import com.shabinder.spotiflyer.models.PlatformQueryResult
|
||||
import com.shabinder.spotiflyer.models.TrackDetails
|
||||
import com.shabinder.spotiflyer.models.spotify.Source
|
||||
import com.shabinder.spotiflyer.ui.SpotiFlyerTypography
|
||||
import com.shabinder.spotiflyer.ui.colorAccent
|
||||
import com.shabinder.spotiflyer.providers.queryGaana
|
||||
@ -37,7 +31,6 @@ import com.shabinder.spotiflyer.providers.querySpotify
|
||||
import com.shabinder.spotiflyer.providers.queryYoutube
|
||||
import com.shabinder.spotiflyer.ui.utils.calculateDominantColor
|
||||
import com.shabinder.spotiflyer.utils.downloadTracks
|
||||
import com.shabinder.spotiflyer.utils.loadAllImages
|
||||
import com.shabinder.spotiflyer.utils.sharedViewModel
|
||||
import com.shabinder.spotiflyer.utils.showDialog
|
||||
import dev.chrisbanes.accompanist.coil.CoilImage
|
||||
@ -79,6 +72,7 @@ fun TrackList(
|
||||
if(result == null) navController.popBackStack()
|
||||
}
|
||||
|
||||
sharedViewModel.updateTrackList(result?.trackList ?: listOf())
|
||||
|
||||
result?.let{
|
||||
Box(modifier = modifier.fillMaxSize()){
|
||||
@ -88,13 +82,13 @@ fun TrackList(
|
||||
item {
|
||||
CoverImage(it.title,it.coverUrl,coroutineScope)
|
||||
}
|
||||
items(it.trackList) { item ->
|
||||
itemsIndexed(sharedViewModel.trackList) { index, item ->
|
||||
TrackCard(
|
||||
track = item,
|
||||
onDownload = {
|
||||
showDialog("Downloading ${it.title}")
|
||||
downloadTracks(arrayListOf(it))
|
||||
}
|
||||
downloadTracks(arrayListOf(item))
|
||||
sharedViewModel.updateTrackStatus(index,DownloadStatus.Queued)
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -102,17 +96,12 @@ fun TrackList(
|
||||
)
|
||||
DownloadAllButton(
|
||||
onClick = {
|
||||
loadAllImages(
|
||||
it.trackList.map { it.albumArtURL },
|
||||
Source.Spotify
|
||||
)
|
||||
val finalList = it.trackList.filter{it.downloaded == DownloadStatus.NotDownloaded}
|
||||
val finalList = sharedViewModel.trackList.filter{it.downloaded == DownloadStatus.NotDownloaded}
|
||||
if (finalList.isNullOrEmpty()) showDialog("Not Downloading Any Song")
|
||||
else downloadTracks(finalList as ArrayList<TrackDetails>)
|
||||
for (track in it.trackList) {
|
||||
for (track in sharedViewModel.trackList) {
|
||||
if (track.downloaded == DownloadStatus.NotDownloaded) {
|
||||
track.downloaded = DownloadStatus.Queued
|
||||
//adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track))
|
||||
}
|
||||
}
|
||||
showDialog("Downloading All Tracks")
|
||||
@ -168,7 +157,7 @@ fun DownloadAllButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
@Composable
|
||||
fun TrackCard(
|
||||
track:TrackDetails,
|
||||
onDownload:(TrackDetails)->Unit
|
||||
onDownload:(TrackDetails)->Unit,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) {
|
||||
val imgUri = track.albumArtURL.toUri().buildUpon().scheme("https").build()
|
||||
@ -192,7 +181,28 @@ fun TrackCard(
|
||||
Text("${track.durationSec/60} minutes, ${track.durationSec%60} sec",fontSize = 13.sp)
|
||||
}
|
||||
}
|
||||
Image(vectorResource(id = R.drawable.ic_arrow), Modifier.clickable(onClick = { onDownload(track) }))
|
||||
when(track.downloaded){
|
||||
DownloadStatus.Downloaded -> {
|
||||
Image(vectorResource(id = R.drawable.ic_tick))
|
||||
}
|
||||
DownloadStatus.Queued -> {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
DownloadStatus.Failed -> {
|
||||
Image(vectorResource(id = R.drawable.ic_error))
|
||||
}
|
||||
DownloadStatus.Downloading -> {
|
||||
CircularProgressIndicator(progress = track.progress.toFloat()/100f)
|
||||
}
|
||||
DownloadStatus.Converting -> {
|
||||
CircularProgressIndicator(progress = 100f,color = colorAccent)
|
||||
}
|
||||
DownloadStatus.NotDownloaded -> {
|
||||
Image(vectorResource(id = R.drawable.ic_arrow), Modifier.clickable(onClick = {
|
||||
onDownload(track)
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,10 @@ fun downloadTracks(
|
||||
context: Context? = mainActivity
|
||||
) {
|
||||
if(!trackList.isNullOrEmpty()){
|
||||
loadAllImages(
|
||||
trackList.map { it.albumArtURL },
|
||||
trackList.first().source
|
||||
)
|
||||
val serviceIntent = Intent(context, ForegroundService::class.java)
|
||||
serviceIntent.putParcelableArrayListExtra("object",trackList)
|
||||
context?.let { ContextCompat.startForegroundService(it, serviceIntent) }
|
||||
|
@ -190,7 +190,6 @@ class ForegroundService : Service(){
|
||||
trackDurationSec = it.durationSec
|
||||
).keys.firstOrNull()
|
||||
log("Service VideoID", videoId ?: "Not Found")
|
||||
//println(response.body().toString())
|
||||
if (videoId.isNullOrBlank()) {
|
||||
sendTrackBroadcast(Status.FAILED.name, it)
|
||||
failed++
|
||||
@ -536,45 +535,45 @@ class ForegroundService : Service(){
|
||||
* Last Element of this List defines Its Source
|
||||
* */
|
||||
val source = urlList.last()
|
||||
log("Image","Fetching All ")
|
||||
for (url in urlList.subList(0, urlList.size - 1)) {
|
||||
log("Image","Fetching")
|
||||
val imgUri = url.toUri().buildUpon().scheme("https").build()
|
||||
|
||||
for (url in urlList.subList(0, urlList.size - 2)) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val imgUri = url.toUri().buildUpon().scheme("https").build()
|
||||
val r = ImageRequest.Builder(this@ForegroundService)
|
||||
.data(imgUri)
|
||||
.build()
|
||||
|
||||
val r = ImageRequest.Builder(this@ForegroundService)
|
||||
.data(imgUri)
|
||||
.build()
|
||||
|
||||
val bitmap = Coil.execute(r).drawable?.toBitmap()
|
||||
val file = when (source) {
|
||||
Source.Spotify.name -> {
|
||||
File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||
}
|
||||
Source.YouTube.name -> {
|
||||
File(
|
||||
imageDir,
|
||||
url.substringBeforeLast('/', url)
|
||||
.substringAfterLast(
|
||||
'/',
|
||||
url
|
||||
) + ".jpeg"
|
||||
)
|
||||
}
|
||||
Source.Gaana.name -> {
|
||||
File(
|
||||
imageDir,
|
||||
(url.substringBeforeLast('/').substringAfterLast(
|
||||
'/'
|
||||
)) + ".jpeg"
|
||||
)
|
||||
}
|
||||
else -> File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||
val bitmap = Coil.execute(r).drawable?.toBitmap()
|
||||
val file = when (source) {
|
||||
Source.Spotify.name -> {
|
||||
File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||
}
|
||||
if (bitmap != null) {
|
||||
file.writeBitmap(bitmap)
|
||||
func?.let { it(file) }
|
||||
} else log("Foreground Service", "Album Art Could Not be Fetched")
|
||||
Source.YouTube.name -> {
|
||||
File(
|
||||
imageDir,
|
||||
url.substringBeforeLast('/', url)
|
||||
.substringAfterLast(
|
||||
'/',
|
||||
url
|
||||
) + ".jpeg"
|
||||
)
|
||||
}
|
||||
Source.Gaana.name -> {
|
||||
File(
|
||||
imageDir,
|
||||
(url.substringBeforeLast('/').substringAfterLast(
|
||||
'/'
|
||||
)) + ".jpeg"
|
||||
)
|
||||
}
|
||||
else -> File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||
}
|
||||
if (bitmap != null) {
|
||||
file.writeBitmap(bitmap)
|
||||
func?.let { it(file) }
|
||||
log("Image","Saved")
|
||||
} else log("Foreground Service", "Album Art Could Not be Fetched")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user