diff --git a/android/src/main/java/com/shabinder/android/MainActivity.kt b/android/src/main/java/com/shabinder/android/MainActivity.kt index 9228905f..b44d46f8 100644 --- a/android/src/main/java/com/shabinder/android/MainActivity.kt +++ b/android/src/main/java/com/shabinder/android/MainActivity.kt @@ -9,6 +9,7 @@ import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.shabinder.common.di.Dir import com.shabinder.common.di.FetchPlatformQueryResult +import com.shabinder.common.di.createDirectories import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRootContent import com.shabinder.common.ui.SpotiFlyerTheme @@ -28,6 +29,7 @@ class MainActivity : AppCompatActivity() { SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot)) } } + dir.createDirectories() } diff --git a/common/compose-ui/build.gradle.kts b/common/compose-ui/build.gradle.kts index 0577471e..6b731cd2 100644 --- a/common/compose-ui/build.gradle.kts +++ b/common/compose-ui/build.gradle.kts @@ -13,6 +13,7 @@ kotlin { implementation(compose.materialIconsExtended) //implementation("org.jetbrains.compose.material:material-icons-extended:0.3.0-build150") implementation(project(":common:dependency-injection")) + //implementation("com.alialbaali.kamel:kamel-image:0.0.7") implementation(project(":common:data-models")) implementation(project(":common:database")) implementation(SqlDelight.coroutineExtensions) diff --git a/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Actual.kt b/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Actual.kt index 7cf4161a..fa4021b2 100644 --- a/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Actual.kt +++ b/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Actual.kt @@ -1,48 +1,9 @@ package com.shabinder.common.ui -import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource -import com.shabinder.common.di.Picture import com.shabinder.common.database.appContext -@Composable -actual fun ImageLoad( - pic: Picture?, - modifier: Modifier -){ - Image(pic?.image?.asImageBitmap(), vectorResource(R.drawable.music) ,"Image",modifier) -} - -@Composable -fun Image(pic: ImageBitmap?, placeholder:ImageVector, desc: String,modifier:Modifier = Modifier) { - if(pic == null) Image(placeholder,desc,modifier) else Image(pic,desc,modifier) -} - -/* -@Composable -actual fun ImageLoad( - url:String, - loadingResource:ImageBitmap?, - errorResource:ImageBitmap?, - modifier: Modifier -){ - val imgUri = url.toUri().buildUpon().scheme("https").build() - CoilImage( - data = imgUri, - contentScale = ContentScale.Crop, - loading = { loadingResource?.let { Image(it,"loading image") } }, - error = { errorResource?.let { it1 -> Image(it1,"Error Image") } }, - modifier = modifier - ) -} -*/ - @Composable actual fun Toast( text: String, diff --git a/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Images.kt b/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Images.kt index 5ed7eb82..ecae215d 100644 --- a/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Images.kt +++ b/common/compose-ui/src/androidMain/kotlin/com/shabinder/common/ui/Images.kt @@ -34,6 +34,9 @@ actual fun DownloadImageArrow(modifier: Modifier){ @Composable actual fun DownloadAllImage() = vectorResource(R.drawable.ic_download_arrow) +@Composable +actual fun PlaceHolderImage() = vectorResource(R.drawable.music) + @Composable actual fun SpotiFlyerLogo() = vectorResource(R.drawable.ic_spotiflyer_logo) @@ -51,5 +54,6 @@ actual fun YoutubeLogo() = vectorResource(R.drawable.ic_youtube) @Composable actual fun YoutubeMusicLogo() = vectorResource(R.drawable.ic_youtube_music_logo) + @Composable actual fun GithubLogo() = vectorResource(R.drawable.ic_github) \ No newline at end of file diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt index 188dbf92..9c48f84f 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerList.kt @@ -1,10 +1,10 @@ package com.shabinder.common.list +import androidx.compose.ui.graphics.ImageBitmap import com.arkivanov.decompose.ComponentContext 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.list.integration.SpotiFlyerListImpl import com.shabinder.common.models.spotify.Source import com.shabinder.common.utils.Consumer @@ -33,14 +33,14 @@ interface SpotiFlyerList { /* * Load Image from cache/Internet and cache it * */ - fun loadImage(url:String): Picture? + suspend fun loadImage(url:String): ImageBitmap? interface Dependencies { val storeFactory: StoreFactory val fetchQuery: FetchPlatformQueryResult val dir: Dir val link: String - fun listOutput(finished: Output.Finished): Consumer + val listOutput: Consumer } sealed class Output { object Finished : Output() diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerListUi.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerListUi.kt index 6d642a33..d3a85490 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerListUi.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/SpotiFlyerListUi.kt @@ -5,25 +5,23 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.shabinder.common.models.DownloadStatus -import com.shabinder.common.di.Picture import com.shabinder.common.models.TrackDetails import com.shabinder.common.ui.* import com.shabinder.common.ui.SpotiFlyerTypography import com.shabinder.common.ui.colorAccent import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch @Composable fun SpotiFlyerListContent( @@ -64,12 +62,17 @@ fun SpotiFlyerListContent( fun TrackCard( track: TrackDetails, downloadTrack:()->Unit, - loadImage:(String)-> Picture? + loadImage:suspend (String)-> ImageBitmap? ) { Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) { - val pic: Picture? = loadImage(track.albumArtURL) + var pic by mutableStateOf(null) + val scope = rememberCoroutineScope() + scope.launch { + pic = loadImage(track.albumArtURL) + } ImageLoad( pic = pic, + "Album Art", modifier = Modifier .preferredWidth(75.dp) .preferredHeight(90.dp) @@ -116,16 +119,20 @@ fun CoverImage( title: String, coverURL: String, scope: CoroutineScope, - loadImage: (String) -> Picture?, + loadImage: suspend (String) -> ImageBitmap?, modifier: Modifier = Modifier, ) { Column( modifier.padding(vertical = 8.dp).fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - val pic = loadImage(coverURL) + var pic by mutableStateOf(null) + scope.launch { + pic = loadImage(coverURL) + } ImageLoad( pic, + "Cover Image", modifier = Modifier .preferredWidth(210.dp) .preferredHeight(230.dp) diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt index 07679870..f64cb4ad 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/list/integration/SpotiFlyerListImpl.kt @@ -1,8 +1,8 @@ package com.shabinder.common.list.integration +import androidx.compose.ui.graphics.ImageBitmap import com.arkivanov.decompose.ComponentContext import com.arkivanov.mvikotlin.extensions.coroutines.states -import com.shabinder.common.di.Picture import com.shabinder.common.models.TrackDetails import com.shabinder.common.list.SpotiFlyerList import com.shabinder.common.list.SpotiFlyerList.Dependencies @@ -37,8 +37,8 @@ internal class SpotiFlyerListImpl( } override fun onBackPressed(){ - listOutput(SpotiFlyerList.Output.Finished) + listOutput.callback(SpotiFlyerList.Output.Finished) } - override fun loadImage(url: String): Picture? = dir.loadImage(url) + override suspend fun loadImage(url: String): ImageBitmap? = dir.loadImage(url) } \ No newline at end of file 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 index 2f71c396..6adde321 100644 --- 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 @@ -1,10 +1,10 @@ package com.shabinder.common.main +import androidx.compose.ui.graphics.ImageBitmap import com.arkivanov.decompose.ComponentContext import com.arkivanov.mvikotlin.core.store.StoreFactory import com.shabinder.common.di.Dir import com.shabinder.common.models.DownloadRecord -import com.shabinder.common.di.Picture import com.shabinder.common.main.integration.SpotiFlyerMainImpl import com.shabinder.common.utils.Consumer import com.shabinder.database.Database @@ -33,10 +33,10 @@ interface SpotiFlyerMain { /* * Load Image from cache/Internet and cache it * */ - fun loadImage(url:String): Picture? + suspend fun loadImage(url:String): ImageBitmap? interface Dependencies { - fun mainOutput(searched: Output): Consumer + val mainOutput: Consumer val storeFactory: StoreFactory val database: Database val dir: Dir diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMainUi.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMainUi.kt index 12e2efab..47f1dfbf 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMainUi.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/SpotiFlyerMainUi.kt @@ -14,23 +14,24 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.History import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.rounded.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.shabinder.common.models.DownloadRecord -import com.shabinder.common.di.Picture 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){ @@ -120,18 +121,18 @@ fun SearchPanel( value = link, onValueChange = updateLink , leadingIcon = { - Icon(Icons.Rounded.Edit,"Link Text Box",tint = Color(0xFFCCCCCC))//LightGray + Icon(Icons.Rounded.Edit,"Link Text Box",tint = Color.LightGray) }, - label = { Text(text = "Paste Link Here...",color = Color(0xFFCCCCCC)) }, + label = { Text(text = "Paste Link Here...",color = Color.LightGray) }, singleLine = true, - //textStyle = LocalTextStyle.current.merge(TextStyle(fontSize = 18.sp,color = Color.White)), + textStyle = TextStyle.Default.merge(TextStyle(fontSize = 18.sp,color = Color.White)), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri), modifier = modifier.padding(12.dp).fillMaxWidth() .border( BorderStroke(2.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent))), RoundedCornerShape(30.dp) ), - backgroundColor = Color(0xFF000000), + backgroundColor = Color.Black, shape = RoundedCornerShape(size = 30.dp), activeColor = transparent, inactiveColor = transparent, @@ -158,7 +159,7 @@ fun AboutColumn(modifier: Modifier = Modifier) { Column(modifier.fillMaxSize().verticalScroll(rememberScrollState())) { Card( modifier = modifier.fillMaxWidth(), - border = BorderStroke(1.dp,Color(0xFF888888))//Gray + border = BorderStroke(1.dp,Color.Gray) ) { Column(modifier.padding(12.dp)) { Text( @@ -171,28 +172,28 @@ fun AboutColumn(modifier: Modifier = Modifier) { Icon( imageVector = SpotifyLogo(), "Open Spotify", - tint = unspecifiedColor, + tint = Color.Unspecified, modifier = Modifier.clickable( onClick = { openPlatform("com.spotify.music","http://open.spotify.com") }) ) Spacer(modifier = modifier.padding(start = 16.dp)) Icon(imageVector = GaanaLogo(), "Open Gaana", - tint = unspecifiedColor, + tint = Color.Unspecified, modifier = Modifier.clickable( onClick = { openPlatform("com.gaana","http://gaana.com") }) ) Spacer(modifier = modifier.padding(start = 16.dp)) Icon(imageVector = YoutubeLogo(), "Open Youtube", - tint = unspecifiedColor, + tint = Color.Unspecified, modifier = Modifier.clickable( onClick = { openPlatform("com.google.android.youtube","http://m.youtube.com") }) ) Spacer(modifier = modifier.padding(start = 12.dp)) Icon(imageVector = YoutubeMusicLogo(), "Open Youtube Music", - tint = unspecifiedColor, + tint = Color.Unspecified, modifier = Modifier.clickable( onClick = { openPlatform("com.google.android.apps.youtube.music","https://music.youtube.com/") }) ) @@ -202,7 +203,7 @@ fun AboutColumn(modifier: Modifier = Modifier) { Spacer(modifier = Modifier.padding(top = 8.dp)) Card( modifier = modifier.fillMaxWidth(), - border = BorderStroke(1.dp,Color(0xFF888888))//Gray + border = BorderStroke(1.dp,Color.Gray)//Gray ) { Column(modifier.padding(12.dp)) { Text( @@ -300,7 +301,7 @@ fun AboutColumn(modifier: Modifier = Modifier) { @Composable fun HistoryColumn( list: List, - loadImage:(String)-> Picture?, + loadImage:suspend (String)-> ImageBitmap?, onItemClicked: (String) -> Unit ) { LazyColumn( @@ -321,13 +322,18 @@ fun HistoryColumn( @Composable fun DownloadRecordItem( item: DownloadRecord, - loadImage:(String)-> Picture?, + loadImage:suspend (String)-> ImageBitmap?, onItemClicked:(String)->Unit ) { Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) { - val pic = loadImage(item.coverUrl) + val scope = rememberCoroutineScope() + var pic by mutableStateOf(null) + scope.launch(Dispatchers.Unconfined) { + pic = loadImage(item.coverUrl) + } ImageLoad( pic, + "Album Art", modifier = Modifier.preferredHeight(75.dp).preferredWidth(90.dp) ) Column(modifier = Modifier.padding(horizontal = 8.dp).preferredHeight(60.dp).weight(1f),verticalArrangement = Arrangement.SpaceEvenly) { @@ -343,7 +349,7 @@ fun DownloadRecordItem( } Image( imageVector = Icons.Rounded.Share, - "Share App", + "Research", modifier = Modifier.clickable(onClick = { //if(!isOnline(ctx)) showDialog("Check Your Internet Connection") else onItemClicked(item.link) diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt index 2e64634b..413fc40d 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/main/integration/SpotiFlyerMainImpl.kt @@ -1,8 +1,8 @@ package com.shabinder.common.main.integration +import androidx.compose.ui.graphics.ImageBitmap import com.arkivanov.decompose.ComponentContext import com.arkivanov.mvikotlin.extensions.coroutines.states -import com.shabinder.common.di.Picture import com.shabinder.common.main.SpotiFlyerMain import com.shabinder.common.main.SpotiFlyerMain.* import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent @@ -26,7 +26,7 @@ internal class SpotiFlyerMainImpl( override val models: Flow = store.states override fun onLinkSearch(link: String) { - mainOutput(Output.Search(link = link)) + mainOutput.callback(Output.Search(link = link)) } override fun onInputLinkChanged(link: String) { @@ -37,5 +37,5 @@ internal class SpotiFlyerMainImpl( store.accept(Intent.SelectCategory(category)) } - override fun loadImage(url: String): Picture? = dir.loadImage(url) + override suspend fun loadImage(url: String): ImageBitmap? = dir.loadImage(url) } \ No newline at end of file diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt index 83f4a321..5ddff2b4 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/root/integration/SpotiFlyerRootImpl.kt @@ -14,6 +14,7 @@ import com.shabinder.common.main.SpotiFlyerMain import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot.Child import com.shabinder.common.root.SpotiFlyerRoot.Dependencies +import com.shabinder.common.ui.showPopUpMessage import com.shabinder.common.utils.Consumer internal class SpotiFlyerRootImpl( @@ -40,7 +41,7 @@ internal class SpotiFlyerRootImpl( SpotiFlyerMain( componentContext = componentContext, dependencies = object : SpotiFlyerMain.Dependencies, Dependencies by this { - override fun mainOutput(searched: SpotiFlyerMain.Output): Consumer = Consumer(::onMainOutput) + override val mainOutput: Consumer = Consumer(::onMainOutput) override val dir: Dir = directories } ) @@ -52,16 +53,16 @@ internal class SpotiFlyerRootImpl( override val fetchQuery = fetchPlatformQueryResult override val dir: Dir = directories override val link: String = link - - override fun listOutput(finished: SpotiFlyerList.Output.Finished): Consumer = - Consumer(::onListOutput) + override val listOutput : Consumer = Consumer(::onListOutput) } ) - private fun onMainOutput(output: SpotiFlyerMain.Output): Unit = + private fun onMainOutput(output: SpotiFlyerMain.Output){ + showPopUpMessage("Button Pressed") when (output) { is SpotiFlyerMain.Output.Search -> router.push(Configuration.List(link = output.link)) } + } private fun onListOutput(output: SpotiFlyerList.Output): Unit = when (output) { diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Color.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Color.kt index 2b5033b6..3a65e181 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Color.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Color.kt @@ -27,7 +27,6 @@ val colorSuccessGreen = Color(0xFF59C351) val darkBackgroundColor = Color(0xFF000000) val colorOffWhite = Color(0xFFE7E7E7) val transparent = Color(0x00000000) -val unspecifiedColor =Color(0f, 0f, 0f, 0f) val black = Color(0xFF000000) val lightGray = Color(0xFFCCCCCC) diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Expect.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Expect.kt index 499caa90..ea0afda8 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Expect.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Expect.kt @@ -1,13 +1,3 @@ package com.shabinder.common.ui -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.shabinder.common.di.Picture - -@Composable -expect fun ImageLoad( - pic: Picture?, - modifier: Modifier = Modifier -) - expect fun showPopUpMessage(text: String) \ No newline at end of file diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Images.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Images.kt index 904361d9..b0492868 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Images.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/Images.kt @@ -1,15 +1,25 @@ package com.shabinder.common.ui +import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.vector.ImageVector +@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) +} + @Composable expect fun DownloadImageTick() @Composable expect fun DownloadAllImage():ImageVector +@Composable +expect fun PlaceHolderImage():ImageVector + @Composable expect fun SpotiFlyerLogo():ImageVector diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/splash/Splash.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/splash/Splash.kt index 4179a877..286022f5 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/splash/Splash.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/ui/splash/Splash.kt @@ -20,12 +20,15 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.material.Icon import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.BrokenImage import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.shabinder.common.ui.* @@ -43,7 +46,7 @@ fun Splash(modifier: Modifier = Modifier, onTimeout: () -> Unit) { delay(SplashWaitTime) currentOnTimeout() } - Image(imageVector = SpotiFlyerLogo(),"SpotiFlyer Logo") + Image(imageVector = Icons.Default.BrokenImage/*SpotiFlyerLogo()*/,"SpotiFlyer Logo") MadeInIndia(Modifier.align(Alignment.BottomCenter)) } } @@ -66,7 +69,7 @@ fun MadeInIndia( fontSize = 22.sp ) Spacer(modifier = Modifier.padding(start = 4.dp)) - Icon(HeartIcon(),"Love",tint = unspecifiedColor) + //Icon(HeartIcon(),"Love",tint = Color.Unspecified) Spacer(modifier = Modifier.padding(start = 4.dp)) Text( text = " in India", diff --git a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/utils/Consumer.kt b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/utils/Consumer.kt index 11ae96eb..ea81aa81 100644 --- a/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/utils/Consumer.kt +++ b/common/compose-ui/src/commonMain/kotlin/com/shabinder/common/utils/Consumer.kt @@ -4,13 +4,13 @@ package com.shabinder.common.utils * Callback Utility * */ interface Consumer { - fun onCall(value: T) + fun callback(value: T) } @Suppress("FunctionName") // Factory function inline fun Consumer(crossinline block: (T) -> Unit): Consumer = object : Consumer { - override fun onCall(value: T) { + override fun callback(value: T) { block(value) } } diff --git a/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Actual.kt b/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Actual.kt index f85eef04..c4a732bf 100644 --- a/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Actual.kt +++ b/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Actual.kt @@ -9,31 +9,3 @@ import com.shabinder.common.di.Picture import java.awt.image.BufferedImage import java.io.ByteArrayOutputStream import javax.imageio.ImageIO - -@Composable -actual fun ImageLoad( - pic: Picture?, - modifier: Modifier -){ - if(pic == null) { - Image( - vectorXmlResource("common/compose-ui/src/main/res/drawable/music.xml"), - "", - modifier - ) - } - else{ - Image( - org.jetbrains.skija.Image.makeFromEncoded( - toByteArray(pic.image) - ).asImageBitmap(), - "Image", - modifier = modifier - ) - } -} -fun toByteArray(bitmap: BufferedImage) : ByteArray { - val baOs = ByteArrayOutputStream() - ImageIO.write(bitmap, "png", baOs) - return baOs.toByteArray() -} \ No newline at end of file diff --git a/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Images.kt b/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Images.kt index 814935ed..17b80cb3 100644 --- a/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Images.kt +++ b/common/compose-ui/src/desktopMain/kotlin/com/shabinder/common/ui/Images.kt @@ -34,6 +34,10 @@ actual fun DownloadImageArrow(modifier: Modifier){ @Composable actual fun DownloadAllImage():ImageVector = vectorXmlResource("common/compose-ui/src/main/res/drawable/ic_download_arrow.xml") +@Composable +actual fun PlaceHolderImage():ImageVector = vectorXmlResource("common/compose-ui/src/main/res/drawable/music.xml") + + @Composable actual fun SpotiFlyerLogo():ImageVector = vectorXmlResource("common/compose-ui/src/main/res/drawable/ic_spotiflyer_logo.xml") diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/Artist.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/Artist.kt index 964c1743..2e8cadab 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/Artist.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/Artist.kt @@ -24,5 +24,5 @@ data class Artist ( val popularity : Int, val seokey : String, val name : String, - @SerialName("artwork_175x175")var artworkLink :String? + @SerialName("artwork_175x175")var artworkLink :String? = null ) \ No newline at end of file diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/CustomArtworks.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/CustomArtworks.kt index f0abab16..d6718ce8 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/CustomArtworks.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/CustomArtworks.kt @@ -18,6 +18,9 @@ package com.shabinder.common.models.gaana import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable data class CustomArtworks ( @SerialName("40x40") val size_40p : String, @SerialName("80x80") val size_80p : String, diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaAlbum.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaAlbum.kt index e14ed36e..cb01d110 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaAlbum.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaAlbum.kt @@ -16,6 +16,9 @@ package com.shabinder.common.models.gaana +import kotlinx.serialization.Serializable + +@Serializable data class GaanaAlbum ( val tracks : List, val count : Int, diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistDetails.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistDetails.kt index a153675b..82093577 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistDetails.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistDetails.kt @@ -16,6 +16,9 @@ package com.shabinder.common.models.gaana +import kotlinx.serialization.Serializable + +@Serializable data class GaanaArtistDetails( val artist : List, val count : Int, diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistTracks.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistTracks.kt index 50e713bc..15279cde 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistTracks.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaArtistTracks.kt @@ -16,6 +16,9 @@ package com.shabinder.common.models.gaana +import kotlinx.serialization.Serializable + +@Serializable data class GaanaArtistTracks( val count : Int, val tracks : List diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaPlaylist.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaPlaylist.kt index dc3bd2f5..b8b96a12 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaPlaylist.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaPlaylist.kt @@ -16,6 +16,9 @@ package com.shabinder.common.models.gaana +import kotlinx.serialization.Serializable + +@Serializable data class GaanaPlaylist ( val modified_on : String, val count : Int, diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaSong.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaSong.kt index 0801980a..39d0a9c0 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaSong.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaSong.kt @@ -16,6 +16,9 @@ package com.shabinder.common.models.gaana +import kotlinx.serialization.Serializable + +@Serializable data class GaanaSong( val tracks : List ) \ No newline at end of file diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaTrack.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaTrack.kt index 5ba91749..e687b5ac 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaTrack.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/gaana/GaanaTrack.kt @@ -22,21 +22,21 @@ import kotlinx.serialization.Serializable @Serializable data class GaanaTrack ( - val tags : List?, + val tags : List? = null, val seokey : String, - val albumseokey : String?, + val albumseokey : String? = null, val track_title : String, - val album_title : String?, - val language : String?, + val album_title : String? = null, + val language : String? = null, val duration: Int, @SerialName("artwork_large") val artworkLink : String, - val artist : List, - @SerialName("gener") val genre : List?, - val lyrics_url : String?, - val youtube_id : String?, - val total_favourite_count : Int?, - val release_date : String?, - val play_ct : String?, - val secondary_language : String?, + val artist : List = emptyList(), + @SerialName("gener") val genre : List? = null, + val lyrics_url : String? = null, + val youtube_id : String? = null, + val total_favourite_count : Int? = null, + val release_date : String? = null, + val play_ct : String? = null, + val secondary_language : String? = null, var downloaded: DownloadStatus? = DownloadStatus.NotDownloaded ) \ No newline at end of file diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Dir.kt b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Dir.kt index 975ea03d..c7bf1832 100644 --- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Dir.kt +++ b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Dir.kt @@ -4,6 +4,8 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Environment +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import co.touchlab.kermit.Kermit import com.mpatric.mp3agic.Mp3File import com.shabinder.common.models.TrackDetails @@ -57,25 +59,11 @@ actual class Dir actual constructor( File(imageCacheDir()).deleteRecursively() } - actual suspend fun cacheImage(picture: Picture) { + actual suspend fun cacheImage(image: Any,path:String) { try { - val path = imageCacheDir() + picture.name FileOutputStream(path).use { out -> - picture.image.compress(Bitmap.CompressFormat.JPEG, 100, out) + (image as? Bitmap)?.compress(Bitmap.CompressFormat.JPEG, 100, out) } - - val bw = - BufferedWriter( - OutputStreamWriter( - FileOutputStream(path + cacheImagePostfix()), StandardCharsets.UTF_8 - ) - ) - - bw.write(picture.source) - bw.write("\r\n${picture.width}") - bw.write("\r\n${picture.height}") - bw.close() - } catch (e: IOException) { e.printStackTrace() } @@ -96,45 +84,20 @@ actual class Dir actual constructor( .setId3v2TagsAndSaveFile(trackDetails,path) } - actual fun loadImage(url: String): Picture? { + actual suspend fun loadImage(url: String): ImageBitmap? { val cachePath = imageCacheDir() + getNameURL(url) - var picture: Picture? = loadCachedImage(cachePath) - if (picture == null) picture = freshImage(url) - return picture + return (loadCachedImage(cachePath) ?: freshImage(url))?.asImageBitmap() } - private fun loadCachedImage(cachePath: String): Picture? { + private fun loadCachedImage(cachePath: String): Bitmap? { return try { - val read = BufferedReader( - InputStreamReader( - FileInputStream(cachePath + cacheImagePostfix()), - StandardCharsets.UTF_8 - ) - ) - - val source = read.readLine() - val width = read.readLine().toInt() - val height = read.readLine().toInt() - - read.close() - - val result: Bitmap? = BitmapFactory.decodeFile(cachePath) - - if (result != null) { - com.shabinder.common.di.Picture( - source, - getNameURL(source), - result, - width, - height - ) - }else null + BitmapFactory.decodeFile(cachePath) } catch (e: Exception) { e.printStackTrace() null } } - private fun freshImage(url:String): Picture?{ + private suspend fun freshImage(url:String): Bitmap?{ return try { val source = URL(url) val connection: HttpURLConnection = source.openConnection() as HttpURLConnection @@ -145,17 +108,10 @@ actual class Dir actual constructor( val result: Bitmap? = BitmapFactory.decodeStream(input) if (result != null) { - val picture = com.shabinder.common.di.Picture( - url, - getNameURL(url), - result, - result.width, - result.height - ) GlobalScope.launch(Dispatchers.IO) { - cacheImage(picture) + cacheImage(result,imageCacheDir() + getNameURL(url)) } - picture + result } else null } catch (e: Exception) { e.printStackTrace() diff --git a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Picture.kt b/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Picture.kt deleted file mode 100644 index 93ad4d38..00000000 --- a/common/dependency-injection/src/androidMain/kotlin/com/shabinder/common/di/Picture.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.shabinder.common.di - -import android.graphics.Bitmap - -actual data class Picture( - var source: String = "", - var name: String = "", - var image: Bitmap, - var width: Int = 0, - var height: Int = 0, - var id: Int = 0 -) \ No newline at end of file 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 b9d1205c..989a33d5 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 @@ -1,5 +1,6 @@ package com.shabinder.common.di +import androidx.compose.ui.graphics.ImageBitmap import co.touchlab.kermit.Kermit import com.shabinder.common.models.DownloadResult import com.shabinder.common.models.TrackDetails @@ -18,8 +19,8 @@ expect class Dir( fun defaultDir(): String fun imageCacheDir(): String fun createDirectory(dirPath:String) - suspend fun cacheImage(picture: Picture) - fun loadImage(url:String): Picture? + suspend fun cacheImage(image: Any,path: String) // in Android = ImageBitmap, Desktop = BufferedImage + suspend fun loadImage(url:String): ImageBitmap? suspend fun clearCache() suspend fun saveFileWithMetadata(mp3ByteArray: ByteArray, path: String, trackDetails: TrackDetails) } @@ -44,8 +45,6 @@ suspend fun downloadFile(url: String): Flow { client.close() } } - -fun Dir.cacheImagePostfix():String = "info" fun getNameURL(url: String): String { return url.substring(url.lastIndexOf('/') + 1, url.length) } diff --git a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Expect.kt b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Expect.kt index 32e955e9..9ee3d8fc 100644 --- a/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Expect.kt +++ b/common/dependency-injection/src/commonMain/kotlin/com/shabinder/common/di/Expect.kt @@ -2,8 +2,6 @@ package com.shabinder.common.di import com.shabinder.common.models.TrackDetails -expect class Picture - expect fun openPlatform(platformID:String ,platformLink:String) expect fun shareApp() diff --git a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Dir.kt b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Dir.kt index de073c8c..836f6302 100644 --- a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Dir.kt +++ b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Dir.kt @@ -1,16 +1,18 @@ package com.shabinder.common.di +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import co.touchlab.kermit.Kermit import com.mpatric.mp3agic.Mp3File import com.shabinder.common.models.TrackDetails import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import org.jetbrains.skija.Image import java.awt.image.BufferedImage import java.io.* import java.net.HttpURLConnection import java.net.URL -import java.nio.charset.StandardCharsets import javax.imageio.ImageIO actual class Dir actual constructor(private val logger: Kermit) { @@ -46,25 +48,11 @@ actual class Dir actual constructor(private val logger: Kermit) { File(imageCacheDir()).deleteRecursively() } - actual suspend fun cacheImage(picture: Picture) { + actual suspend fun cacheImage(image: Any,path:String) { try { - val path = imageCacheDir() + picture.name - - ImageIO.write(picture.image, "jpeg", File(path)) - - val bw = - BufferedWriter( - OutputStreamWriter( - FileOutputStream(path + cacheImagePostfix()), - StandardCharsets.UTF_8 - ) - ) - - bw.write(picture.source) - bw.write("\r\n${picture.width}") - bw.write("\r\n${picture.height}") - bw.close() - + (image as? BufferedImage)?.let { + ImageIO.write(it,"jpeg", File(path)) + } } catch (e: IOException) { e.printStackTrace() } @@ -85,45 +73,23 @@ actual class Dir actual constructor(private val logger: Kermit) { .setId3v2TagsAndSaveFile(trackDetails,path) } - actual fun loadImage(url: String): Picture? { + actual suspend fun loadImage(url: String): ImageBitmap? { val cachePath = imageCacheDir() + getNameURL(url) - var picture: Picture? = loadCachedImage(cachePath) - if (picture == null) picture = freshImage(url,cachePath) + var picture: ImageBitmap? = loadCachedImage(cachePath) + if (picture == null) picture = freshImage(url) return picture } - private fun loadCachedImage(cachePath: String): Picture? { + private fun loadCachedImage(cachePath: String): ImageBitmap? { return try { - val read = BufferedReader( - InputStreamReader( - FileInputStream(cachePath + cacheImagePostfix()), - StandardCharsets.UTF_8 - ) - ) - - val source = read.readLine() - val width = read.readLine().toInt() - val height = read.readLine().toInt() - - read.close() - - val result: BufferedImage? = ImageIO.read(File(cachePath)) - - if (result != null) { - com.shabinder.common.di.Picture( - source, - getNameURL(source), - result, - width, - height - ) - }else null + ImageIO.read(File(cachePath))?.toImageBitmap() } catch (e: Exception) { - e.printStackTrace() + //e.printStackTrace() null } } - private fun freshImage(url:String,cachePath: String): Picture?{ + + private suspend fun freshImage(url:String): ImageBitmap?{ return try { val source = URL(url) val connection: HttpURLConnection = source.openConnection() as HttpURLConnection @@ -134,17 +100,10 @@ actual class Dir actual constructor(private val logger: Kermit) { val result: BufferedImage? = ImageIO.read(input) if (result != null) { - val picture = com.shabinder.common.di.Picture( - url, - getNameURL(url), - result, - result.width, - result.height - ) GlobalScope.launch(Dispatchers.IO) { //TODO Refactor - cacheImage(picture) + cacheImage(result,imageCacheDir() + getNameURL(url)) } - picture + result.toImageBitmap() } else null } catch (e: Exception) { e.printStackTrace() @@ -152,3 +111,12 @@ actual class Dir actual constructor(private val logger: Kermit) { } } } +fun BufferedImage.toImageBitmap() = Image.makeFromEncoded( + toByteArray(this) +).asImageBitmap() + +private fun toByteArray(bitmap: BufferedImage) : ByteArray { + val baOs = ByteArrayOutputStream() + ImageIO.write(bitmap, "png", baOs) + return baOs.toByteArray() +} diff --git a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Picture.kt b/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Picture.kt deleted file mode 100644 index f9a3ccda..00000000 --- a/common/dependency-injection/src/desktopMain/kotlin/com/shabinder/common/di/Picture.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.shabinder.common.di - -import java.awt.image.BufferedImage - -actual data class Picture( - var source: String = "", - var name: String = "", - var image: BufferedImage, - var width: Int = 0, - var height: Int = 0, - var id: Int = 0 -) \ No newline at end of file