diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 389ec275..847dc6dc 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -40,7 +40,6 @@ - (null) } + var pic by remember(link) { + mutableStateOf(null) + } LaunchedEffect(link) { withContext(dispatcherIO) { diff --git a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt index 744c52e2..e56a099e 100644 --- a/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt +++ b/common/compose/src/androidMain/kotlin/com/shabinder/common/uikit/AndroidImages.kt @@ -21,15 +21,23 @@ package com.shabinder.common.uikit import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource import com.shabinder.common.database.R import com.shabinder.common.translations.Strings import kotlinx.coroutines.flow.MutableStateFlow +@Composable +internal actual fun imageVectorResource(id: T): ImageVector = + ImageVector.Companion.vectorResource(id as Int) + @Composable actual fun DownloadImageTick() { Image( - painterResource(R.drawable.ic_tick), + getCachedPainter(R.drawable.ic_tick), Strings.downloadDone() ) } @@ -37,7 +45,7 @@ actual fun DownloadImageTick() { @Composable actual fun DownloadImageError(modifier: Modifier) { Image( - painterResource(R.drawable.ic_error), + getCachedPainter(R.drawable.ic_error), Strings.downloadError(), modifier = modifier ) @@ -46,44 +54,44 @@ actual fun DownloadImageError(modifier: Modifier) { @Composable actual fun DownloadImageArrow(modifier: Modifier) { Image( - painterResource(R.drawable.ic_arrow), + getCachedPainter(R.drawable.ic_arrow), Strings.downloadStart(), modifier ) } @Composable -actual fun DownloadAllImage() = painterResource(R.drawable.ic_download_arrow) +actual fun DownloadAllImage() = getCachedPainter(R.drawable.ic_download_arrow) @Composable -actual fun ShareImage() = painterResource(R.drawable.ic_share_open) +actual fun ShareImage() = getCachedPainter(R.drawable.ic_share_open) @Composable -actual fun PlaceHolderImage() = painterResource(R.drawable.ic_song_placeholder) +actual fun PlaceHolderImage() = getCachedPainter(R.drawable.ic_song_placeholder) @Composable -actual fun SpotiFlyerLogo() = painterResource(R.drawable.ic_spotiflyer_logo) +actual fun SpotiFlyerLogo() = getCachedPainter(R.drawable.ic_spotiflyer_logo) @Composable actual fun HeartIcon() = painterResource(R.drawable.ic_heart) @Composable -actual fun SpotifyLogo() = painterResource(R.drawable.ic_spotify_logo) +actual fun SpotifyLogo() = getCachedPainter(R.drawable.ic_spotify_logo) @Composable -actual fun SaavnLogo() = painterResource(R.drawable.ic_jio_saavn_logo) +actual fun SaavnLogo() = getCachedPainter(R.drawable.ic_jio_saavn_logo) @Composable -actual fun GaanaLogo() = painterResource(R.drawable.ic_gaana) +actual fun GaanaLogo() = getCachedPainter(R.drawable.ic_gaana) @Composable -actual fun YoutubeLogo() = painterResource(R.drawable.ic_youtube) +actual fun YoutubeLogo() = getCachedPainter(R.drawable.ic_youtube) @Composable -actual fun YoutubeMusicLogo() = painterResource(R.drawable.ic_youtube_music_logo) +actual fun YoutubeMusicLogo() = getCachedPainter(R.drawable.ic_youtube_music_logo) @Composable -actual fun GithubLogo() = painterResource(R.drawable.ic_github) +actual fun GithubLogo() = getCachedPainter(R.drawable.ic_github) @Composable actual fun PaypalLogo() = painterResource(R.drawable.ic_paypal_logo) @@ -100,4 +108,4 @@ actual fun Toast( duration: ToastDuration ) { // We Have Android's Implementation of Toast so its just Empty -} +} \ No newline at end of file diff --git a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt index d89974aa..6be14625 100644 --- a/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt +++ b/common/compose/src/commonMain/kotlin/com/shabinder/common/uikit/ExpectImages.kt @@ -15,11 +15,27 @@ */ @file:Suppress("FunctionName") + package com.shabinder.common.uikit import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import com.shabinder.common.caching.Cache + +private val ImageCache = Cache.Builder.newBuilder() + .maximumCacheSize(15).build() + +@Composable +internal expect fun imageVectorResource(id: T): ImageVector + +@Composable +fun getCachedPainter(key: K): Painter { + return rememberVectorPainter( + ImageCache.get(key) ?: imageVectorResource(key).also { ImageCache.put(key, it) }) +} @Composable expect fun DownloadImageTick() diff --git a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt index ee2f49e3..2c4c1a91 100644 --- a/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt +++ b/common/compose/src/desktopMain/kotlin/com/shabinder/common/uikit/DesktopImages.kt @@ -15,19 +15,26 @@ */ @file:Suppress("FunctionName") + package com.shabinder.common.uikit import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.res.loadXmlImageVector import androidx.compose.ui.res.vectorXmlResource +@Composable +internal actual fun imageVectorResource(id: T): ImageVector = + vectorXmlResource(id as String) + @Composable actual fun DownloadImageTick() { Image( - vectorXmlResource("drawable/ic_tick.xml"), + getCachedPainter("drawable/ic_tick.xml"), "Downloaded" ) } @@ -35,7 +42,7 @@ actual fun DownloadImageTick() { @Composable actual fun DownloadImageError(modifier: Modifier) { Image( - vectorXmlResource("drawable/ic_error.xml"), + getCachedPainter("drawable/ic_error.xml"), "Can't Download", modifier = modifier ) @@ -44,51 +51,61 @@ actual fun DownloadImageError(modifier: Modifier) { @Composable actual fun DownloadImageArrow(modifier: Modifier) { Image( - vectorXmlResource("drawable/ic_arrow.xml"), + getCachedPainter("drawable/ic_arrow.xml"), "Download", modifier ) } @Composable -actual fun DownloadAllImage() = rememberVectorPainter(vectorXmlResource("drawable/ic_download_arrow.xml")) as Painter +actual fun DownloadAllImage() = getCachedPainter("drawable/ic_download_arrow.xml") + @Composable -actual fun ShareImage() = rememberVectorPainter(vectorXmlResource("drawable/ic_share_open.xml")) as Painter +actual fun ShareImage() = getCachedPainter("drawable/ic_share_open.xml") @Composable -actual fun PlaceHolderImage() = rememberVectorPainter(vectorXmlResource("drawable/music.xml")) - as Painter -@Composable -actual fun SpotiFlyerLogo() = - rememberVectorPainter(vectorXmlResource("drawable/ic_spotiflyer_logo.xml")) as Painter +actual fun PlaceHolderImage() = getCachedPainter("drawable/music.xml") @Composable -actual fun HeartIcon() = rememberVectorPainter(vectorXmlResource("drawable/ic_heart.xml")) as Painter +actual fun SpotiFlyerLogo() = getCachedPainter("drawable/ic_spotiflyer_logo.xml") @Composable -actual fun SpotifyLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_spotify_logo.xml")) as Painter +actual fun HeartIcon() = + getCachedPainter("drawable/ic_heart.xml") @Composable -actual fun SaavnLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_jio_saavn_logo.xml")) as Painter +actual fun SpotifyLogo() = + getCachedPainter("drawable/ic_spotify_logo.xml") @Composable -actual fun YoutubeLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_youtube.xml")) as Painter +actual fun SaavnLogo() = + getCachedPainter("drawable/ic_jio_saavn_logo.xml") @Composable -actual fun GaanaLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_gaana.xml")) as Painter +actual fun YoutubeLogo() = + getCachedPainter("drawable/ic_youtube.xml") @Composable -actual fun YoutubeMusicLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_youtube_music_logo.xml")) as Painter +actual fun GaanaLogo() = + getCachedPainter("drawable/ic_gaana.xml") @Composable -actual fun GithubLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_github.xml")) as Painter +actual fun YoutubeMusicLogo() = + getCachedPainter("drawable/ic_youtube_music_logo.xml") @Composable -actual fun PaypalLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_paypal_logo.xml")) as Painter +actual fun GithubLogo() = + getCachedPainter("drawable/ic_github.xml") @Composable -actual fun OpenCollectiveLogo() = rememberVectorPainter(vectorXmlResource("drawable/ic_opencollective_icon.xml")) as Painter +actual fun PaypalLogo() = + getCachedPainter("drawable/ic_paypal_logo.xml") @Composable -actual fun RazorPay() = rememberVectorPainter(vectorXmlResource("drawable/ic_indian_rupee.xml")) as Painter +actual fun OpenCollectiveLogo() = + getCachedPainter("drawable/ic_opencollective_icon.xml") + +@Composable +actual fun RazorPay() = + getCachedPainter("drawable/ic_indian_rupee.xml") 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 15b53d32..1772e88c 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 @@ -1,6 +1,7 @@ package com.shabinder.common.models import android.content.SharedPreferences +import kotlinx.coroutines.CoroutineScope actual interface PlatformActions { @@ -26,3 +27,5 @@ internal actual val StubPlatformActions = object : PlatformActions { override fun sendTracksToService(array: List) {} } + +actual fun runBlocking(block: suspend CoroutineScope.() -> T): T = kotlinx.coroutines.runBlocking { block() } \ No newline at end of file diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/Cache.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/Cache.kt index 8882b7ae..6130419d 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/Cache.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/Cache.kt @@ -1,6 +1,7 @@ package com.shabinder.common.caching import kotlin.time.Duration +import kotlin.time.ExperimentalTime import kotlin.time.TimeSource /** @@ -23,6 +24,8 @@ public interface Cache { */ public suspend fun get(key: Key, loader: suspend () -> Value): Value + public fun getBlocking(key: Key, loader: suspend () -> Value): Value + /** * Associates [value] with [key] in this cache. If the cache previously contained a * value associated with [key], the old value is replaced by [value]. diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/RealCache.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/RealCache.kt index 6e0cf498..593c3e4a 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/RealCache.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/caching/RealCache.kt @@ -4,6 +4,7 @@ import co.touchlab.stately.collections.IsoMutableMap import co.touchlab.stately.collections.IsoMutableSet import co.touchlab.stately.concurrency.AtomicReference import co.touchlab.stately.concurrency.value +import com.shabinder.common.models.runBlocking import kotlin.time.Duration import kotlin.time.TimeMark import kotlin.time.TimeSource @@ -110,6 +111,12 @@ internal class RealCache( } } + + override fun getBlocking(key: Key, loader: suspend () -> Value): Value = + runBlocking { + get(key, loader) + } + override fun put(key: Key, value: Value) { expireEntries() @@ -185,7 +192,7 @@ internal class RealCache( */ private fun CacheEntry.isExpired(): Boolean { return expiresAfterAccess && (accessTimeMark.get() + expireAfterAccessDuration).hasPassedNow() || - expiresAfterWrite && (writeTimeMark.get() + expireAfterWriteDuration).hasPassedNow() + expiresAfterWrite && (writeTimeMark.get() + expireAfterWriteDuration).hasPassedNow() } /** diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/PlatformActions.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/PlatformActions.kt index 8fd73462..8454b0f7 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/PlatformActions.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/models/PlatformActions.kt @@ -1,5 +1,9 @@ package com.shabinder.common.models +import kotlinx.coroutines.CoroutineScope + expect interface PlatformActions internal expect val StubPlatformActions: PlatformActions + +expect fun runBlocking(block: suspend CoroutineScope.() -> T): T \ No newline at end of file diff --git a/common/data-models/src/commonMain/kotlin/com/shabinder/common/utils/Ext.kt b/common/data-models/src/commonMain/kotlin/com/shabinder/common/utils/Ext.kt index d7d30684..6164033f 100644 --- a/common/data-models/src/commonMain/kotlin/com/shabinder/common/utils/Ext.kt +++ b/common/data-models/src/commonMain/kotlin/com/shabinder/common/utils/Ext.kt @@ -7,7 +7,6 @@ import kotlin.contracts.contract fun T?.requireNotNull(): T = requireNotNull(this) - @OptIn(ExperimentalContracts::class) inline fun buildString(track: TrackDetails, builderAction: StringBuilder.() -> Unit): String { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } diff --git a/common/data-models/src/desktopMain/kotlin/com/shabinder/common/models/DesktopPlatformActions.kt b/common/data-models/src/desktopMain/kotlin/com/shabinder/common/models/DesktopPlatformActions.kt index 5386a96c..42b09eed 100644 --- a/common/data-models/src/desktopMain/kotlin/com/shabinder/common/models/DesktopPlatformActions.kt +++ b/common/data-models/src/desktopMain/kotlin/com/shabinder/common/models/DesktopPlatformActions.kt @@ -1,5 +1,9 @@ package com.shabinder.common.models +import kotlinx.coroutines.CoroutineScope + actual interface PlatformActions internal actual val StubPlatformActions = object : PlatformActions {} + +actual fun runBlocking(block: suspend CoroutineScope.() -> T): T = kotlinx.coroutines.runBlocking { block() } \ No newline at end of file diff --git a/common/data-models/src/jsMain/kotlin/com.shabinder.common.models/JSPlatformActions.kt b/common/data-models/src/jsMain/kotlin/com.shabinder.common.models/JSPlatformActions.kt index 8e1f948e..56362479 100644 --- a/common/data-models/src/jsMain/kotlin/com.shabinder.common.models/JSPlatformActions.kt +++ b/common/data-models/src/jsMain/kotlin/com.shabinder.common.models/JSPlatformActions.kt @@ -1,5 +1,10 @@ package com.shabinder.common.models +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.promise + actual interface PlatformActions -internal actual val StubPlatformActions = object : PlatformActions {} \ No newline at end of file +internal actual val StubPlatformActions = object : PlatformActions {} +actual fun runBlocking(block: suspend CoroutineScope.() -> T): dynamic = GlobalScope.promise(block = block) \ No newline at end of file