mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-22 09:04:32 +01:00
Ui Fixes and ImageLoading fun improvised.
This commit is contained in:
parent
a186a1a1e7
commit
7602fa3f23
@ -8,6 +8,7 @@ import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.material.Surface
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent
|
||||
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
|
||||
@ -22,6 +23,7 @@ import com.shabinder.common.root.SpotiFlyerRoot
|
||||
import com.shabinder.common.root.SpotiFlyerRootContent
|
||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||
import com.shabinder.common.ui.SpotiFlyerTheme
|
||||
import com.shabinder.common.ui.colorOffWhite
|
||||
import com.shabinder.database.Database
|
||||
import kotlinx.coroutines.*
|
||||
import org.koin.android.ext.android.inject
|
||||
@ -41,7 +43,9 @@ class MainActivity : ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
SpotiFlyerTheme {
|
||||
Surface(contentColor = colorOffWhite) {
|
||||
root = SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot))
|
||||
}
|
||||
}
|
||||
}
|
||||
initialise()
|
||||
|
@ -24,6 +24,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun SpotiFlyerListContent(
|
||||
@ -67,13 +68,8 @@ fun TrackCard(
|
||||
loadImage:suspend (String)-> ImageBitmap?
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) {
|
||||
var pic by mutableStateOf<ImageBitmap?>(null)
|
||||
val scope = rememberCoroutineScope()
|
||||
LaunchedEffect((1..10).random()){
|
||||
pic = loadImage(track.albumArtURL)
|
||||
}
|
||||
ImageLoad(
|
||||
pic = pic,
|
||||
{loadImage(track.albumArtURL)},
|
||||
"Album Art",
|
||||
modifier = Modifier
|
||||
.width(75.dp)
|
||||
@ -128,14 +124,8 @@ fun CoverImage(
|
||||
modifier.padding(vertical = 8.dp).fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
var pic by mutableStateOf<ImageBitmap?>(null)
|
||||
LaunchedEffect(true){
|
||||
scope.launch(dispatcherIO) {
|
||||
pic = loadImage(coverURL)
|
||||
}
|
||||
}
|
||||
ImageLoad(
|
||||
pic,
|
||||
{ loadImage(coverURL) },
|
||||
"Cover Image",
|
||||
modifier = Modifier
|
||||
.width(210.dp)
|
||||
|
@ -30,8 +30,6 @@ import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
|
||||
import com.shabinder.common.di.openPlatform
|
||||
import com.shabinder.common.ui.*
|
||||
import com.shabinder.common.ui.SpotiFlyerTypography
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun SpotiFlyerMainContent(component: SpotiFlyerMain){
|
||||
@ -326,13 +324,15 @@ fun DownloadRecordItem(
|
||||
onItemClicked:(String)->Unit
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) {
|
||||
val scope = rememberCoroutineScope()
|
||||
var pic by mutableStateOf<ImageBitmap?>(null)
|
||||
scope.launch(dispatcherIO) {
|
||||
pic = loadImage(item.coverUrl)
|
||||
}
|
||||
/*KamelImage(
|
||||
lazyImageResource(item.coverUrl),
|
||||
"Album Art",
|
||||
modifier = Modifier.height(75.dp).width(90.dp),
|
||||
crossfade = true,
|
||||
onLoading = { PlaceHolderImage() }
|
||||
)*/
|
||||
ImageLoad(
|
||||
pic,
|
||||
{ loadImage(item.coverUrl) },
|
||||
"Album Art",
|
||||
modifier = Modifier.height(75.dp).width(90.dp)
|
||||
)
|
||||
|
@ -1,15 +1,25 @@
|
||||
@file:Suppress("FunctionName")
|
||||
package com.shabinder.common.ui
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun ImageLoad(pic: ImageBitmap?, desc: String, modifier:Modifier = Modifier, placeholder:ImageVector = PlaceHolderImage()) {
|
||||
if(pic == null) Image(placeholder, desc, modifier) else Image(pic, desc, modifier)
|
||||
fun ImageLoad(loader: suspend () -> ImageBitmap?, desc: String = "Album Art", modifier:Modifier = Modifier, placeholder:ImageVector = PlaceHolderImage()) {
|
||||
var pic by remember { mutableStateOf<ImageBitmap?>(null) }
|
||||
Crossfade(pic){
|
||||
if(pic == null) Image(placeholder, desc, modifier) else Image(pic!!, desc, modifier)
|
||||
}
|
||||
LaunchedEffect(loader){
|
||||
withContext(dispatcherIO) {
|
||||
pic = loader()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -21,5 +21,5 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class GaanaArtistTracks(
|
||||
val count : Int,
|
||||
val tracks : List<GaanaTrack>
|
||||
val tracks : List<GaanaTrack>? = null
|
||||
)
|
@ -16,7 +16,7 @@ class TokenStore(
|
||||
private val db: TokenDBQueries
|
||||
get() = tokenDB.tokenDBQueries
|
||||
|
||||
private suspend fun save(token: TokenData){
|
||||
private fun save(token: TokenData){
|
||||
if(!token.access_token.isNullOrBlank() && token.expiry != null)
|
||||
db.add(token.access_token!!, token.expiry!! + Clock.System.now().epochSeconds)
|
||||
}
|
||||
@ -25,6 +25,7 @@ class TokenStore(
|
||||
var token: TokenData? = db.select().executeAsOneOrNull()?.let {
|
||||
TokenData(it.accessToken,null,it.expiry)
|
||||
}
|
||||
logger.d{"System Time:${Clock.System.now().epochSeconds} , Token Expiry:${token?.expiry}"}
|
||||
if(Clock.System.now().epochSeconds > token?.expiry ?:0 || token == null){
|
||||
logger.d{"Requesting New Token"}
|
||||
token = authenticateSpotify()
|
||||
|
@ -85,7 +85,7 @@ class GaanaProvider(
|
||||
dir.defaultDir()
|
||||
)
|
||||
)) {//Download Already Present!!
|
||||
it.downloaded = com.shabinder.common.models.DownloadStatus.Downloaded
|
||||
it.downloaded = DownloadStatus.Downloaded
|
||||
}
|
||||
trackList = listOf(it).toTrackDetailsList(folderType, subFolder)
|
||||
title = it.track_title
|
||||
@ -115,7 +115,7 @@ class GaanaProvider(
|
||||
)
|
||||
)
|
||||
) {//Download Already Present!!
|
||||
track.downloaded = com.shabinder.common.models.DownloadStatus.Downloaded
|
||||
track.downloaded = DownloadStatus.Downloaded
|
||||
}
|
||||
}
|
||||
trackList = it.tracks.toTrackDetailsList(folderType, subFolder)
|
||||
@ -146,7 +146,7 @@ class GaanaProvider(
|
||||
)
|
||||
)
|
||||
) {//Download Already Present!!
|
||||
track.downloaded = com.shabinder.common.models.DownloadStatus.Downloaded
|
||||
track.downloaded = DownloadStatus.Downloaded
|
||||
}
|
||||
}
|
||||
trackList = it.tracks.toTrackDetailsList(folderType, subFolder)
|
||||
@ -175,7 +175,7 @@ class GaanaProvider(
|
||||
coverUrl = it.artworkLink ?: gaanaPlaceholderImageUrl
|
||||
}
|
||||
getGaanaArtistTracks(seokey = link).also {
|
||||
it.tracks.forEach { track ->
|
||||
it.tracks?.forEach { track ->
|
||||
if (dir.isPresent(
|
||||
dir.finalOutputDir(
|
||||
track.track_title,
|
||||
@ -185,10 +185,10 @@ class GaanaProvider(
|
||||
)
|
||||
)
|
||||
) {//Download Already Present!!
|
||||
track.downloaded = com.shabinder.common.models.DownloadStatus.Downloaded
|
||||
track.downloaded = DownloadStatus.Downloaded
|
||||
}
|
||||
}
|
||||
trackList = it.tracks.toTrackDetailsList(folderType, subFolder)
|
||||
trackList = it.tracks?.toTrackDetailsList(folderType, subFolder) ?: emptyList()
|
||||
withContext(Dispatchers.Default) {
|
||||
db.add(
|
||||
type = "Artist",
|
||||
|
@ -19,8 +19,11 @@ package com.shabinder.common.di.providers
|
||||
import co.touchlab.kermit.Kermit
|
||||
import com.shabinder.common.database.DownloadRecordDatabaseQueries
|
||||
import com.shabinder.common.di.Dir
|
||||
import com.shabinder.common.di.TokenStore
|
||||
import com.shabinder.common.di.finalOutputDir
|
||||
import com.shabinder.common.di.kotlinxSerializer
|
||||
import com.shabinder.common.di.spotify.SpotifyRequests
|
||||
import com.shabinder.common.di.spotify.authenticateSpotify
|
||||
import com.shabinder.common.models.PlatformQueryResult
|
||||
import com.shabinder.common.models.TrackDetails
|
||||
import com.shabinder.common.models.spotify.Album
|
||||
@ -29,16 +32,40 @@ import com.shabinder.common.models.spotify.Source
|
||||
import com.shabinder.common.models.spotify.Track
|
||||
import com.shabinder.database.Database
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.features.*
|
||||
import io.ktor.client.features.json.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class SpotifyProvider(
|
||||
override val httpClient: HttpClient,
|
||||
private val tokenStore: TokenStore,
|
||||
private val database: Database,
|
||||
private val logger: Kermit,
|
||||
private val dir: Dir,
|
||||
) : SpotifyRequests {
|
||||
|
||||
init {
|
||||
logger.d { "Creating Spotify Provider" }
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
val token = tokenStore.getToken()
|
||||
httpClient = HttpClient {
|
||||
defaultRequest {
|
||||
header("Authorization","Bearer ${token.access_token}")
|
||||
}
|
||||
install(JsonFeature) {
|
||||
serializer = kotlinxSerializer
|
||||
}
|
||||
}
|
||||
logger.d { "Spotify Provider Created with $token" }
|
||||
}
|
||||
}
|
||||
|
||||
override lateinit var httpClient: HttpClient
|
||||
|
||||
private val db:DownloadRecordDatabaseQueries
|
||||
get() = database.downloadRecordDatabaseQueries
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.shabinder.common.di.spotify
|
||||
|
||||
import com.shabinder.common.di.kotlinxSerializer
|
||||
import com.shabinder.common.models.spotify.TokenData
|
||||
import com.shabinder.database.Database
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.features.auth.*
|
||||
import io.ktor.client.features.auth.providers.*
|
||||
@ -9,6 +10,7 @@ import io.ktor.client.features.json.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.datetime.Clock
|
||||
|
||||
suspend fun authenticateSpotify(): TokenData {
|
||||
return spotifyAuthClient.post("https://accounts.spotify.com/api/token"){
|
||||
|
@ -17,6 +17,7 @@ import com.shabinder.common.root.SpotiFlyerRootContent
|
||||
import com.shabinder.common.ui.SpotiFlyerColors
|
||||
import com.shabinder.common.ui.SpotiFlyerShapes
|
||||
import com.shabinder.common.ui.SpotiFlyerTypography
|
||||
import com.shabinder.common.ui.colorOffWhite
|
||||
import com.shabinder.database.Database
|
||||
|
||||
private val koin = initKoin(enableNetworkLogs = true).koin
|
||||
@ -29,7 +30,8 @@ fun main(){
|
||||
Window("SpotiFlyer") {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = Color.Black
|
||||
color = Color.Black,
|
||||
contentColor = colorOffWhite
|
||||
) {
|
||||
DesktopMaterialTheme(
|
||||
colors = SpotiFlyerColors,
|
||||
|
Loading…
Reference in New Issue
Block a user