diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c18b214d..b48b60e3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,7 +12,7 @@ apply(plugin = "dagger.hilt.android.plugin") val versionMajor = 0 val versionMinor = 2 -val versionPatch = 0 +val versionPatch = 1 val versionBuild = 0 val isStable = true diff --git a/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APICallState.kt b/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APICallState.kt index 32ff8f38..c8ec8d07 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APICallState.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APICallState.kt @@ -7,9 +7,11 @@ data class APICallState( Amoled_Latest = "", RC_Latest = "", ABC_Latest = "", + Lite_Latest = "", Regular = emptyList(), Amoled = emptyList(), Regular_Cloned = emptyList(), - Amoled_Cloned = emptyList() + Amoled_Cloned = emptyList(), + Lite = emptyList() ) ) diff --git a/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APIResponse.kt b/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APIResponse.kt index de3b0e46..ff4a718c 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APIResponse.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/domain/spotify/model/APIResponse.kt @@ -12,6 +12,8 @@ data class APIResponse( val RC_Latest: String, @SerializedName("ABC_Latest") val ABC_Latest: String, + @SerializedName("Lite_Latest") + val Lite_Latest: String, @SerializedName("Regular") val Regular: List, @SerializedName("Amoled") @@ -19,7 +21,9 @@ data class APIResponse( @SerializedName("Regular_Cloned") val Regular_Cloned: List, @SerializedName("Amoled_Cloned") - val Amoled_Cloned: List + val Amoled_Cloned: List, + @SerializedName("Lite") + val Lite: List ) { var status: Status = Status.SUCCESS var message: String? = null diff --git a/app/src/main/java/com/bobbyesp/spowlo/presentation/MainActivity.kt b/app/src/main/java/com/bobbyesp/spowlo/presentation/MainActivity.kt index b6bca9c2..addf15cd 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/presentation/MainActivity.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/presentation/MainActivity.kt @@ -95,11 +95,6 @@ class MainActivity : ComponentActivity() { icon = Icons.Filled.Home, route = Route.HOME ), - /*NavBarItem( - name = stringResource(id = R.string.settings), - icon = Icons.Filled.Settings, - route = Route.SETTINGS, - ),*/ NavBarItem( name = stringResource(id = R.string.searcher), icon = Icons.Filled.Search, diff --git a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/components/PackagesListItem.kt b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/components/PackagesListItem.kt index f5b092a9..8d108d74 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/components/PackagesListItem.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/components/PackagesListItem.kt @@ -2,7 +2,11 @@ package com.bobbyesp.spowlo.presentation.ui.components import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ExpandLess @@ -13,12 +17,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.times import com.bobbyesp.spowlo.R import com.bobbyesp.spowlo.domain.spotify.model.PackagesObject import com.bobbyesp.spowlo.presentation.MainActivity @@ -46,6 +53,10 @@ enum class PackagesListItemType( AmoledCloned( R.string.amoled_cloned, R.string.amoled_cloned_description + ), + Lite( + R.string.lite, + R.string.lite_description ) } @@ -56,6 +67,7 @@ fun PackagesListItem( type: PackagesListItemType = PackagesListItemType.Regular, expanded: Boolean = false, packages: List, + latestVersion: String = "Unknown", onClick: () -> Unit = {}, ) { var isExpanded by remember { mutableStateOf(expanded) } @@ -65,8 +77,9 @@ fun PackagesListItem( ElevatedCard( modifier = modifier, onClick = { isExpanded = !isExpanded }, - shape = MaterialTheme.shapes.small) { - Box{ + shape = MaterialTheme.shapes.small + ) { + Box { Row( modifier = Modifier .fillMaxWidth() @@ -96,17 +109,53 @@ fun PackagesListItem( color = MaterialTheme.colorScheme.onSurfaceVariant, overflow = TextOverflow.Ellipsis ) + Divider(modifier = Modifier.padding(top = 6.dp, bottom = 6.dp)) + Row( - modifier = Modifier.weight(1f), + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 4.dp), verticalAlignment = Alignment.CenterVertically - ){ - Spacer(modifier = Modifier - .weight(1f, true)) + ) { + Text( + text = stringResource(id = R.string.latest_version), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + fontStyle = FontStyle.Italic, + fontWeight = FontWeight.Bold + ) - val animatedDegree = animateFloatAsState(targetValue = if (isExpanded) 0f else -180f) Box(modifier = Modifier - .padding(2.dp) - .align(Alignment.Bottom)){ + .fillMaxWidth() + .wrapContentSize(Alignment.CenterEnd)){ + Text( + modifier = Modifier, + text = latestVersion, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + fontStyle = FontStyle.Italic, + fontWeight = FontWeight.Bold, + overflow = TextOverflow.Ellipsis + ) + } + } + + Row( + modifier = Modifier.weight(1f), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer( + modifier = Modifier + .weight(1f, true) + ) + val animatedDegree = + animateFloatAsState(targetValue = if (isExpanded) 0f else -180f) + + Box( + modifier = Modifier + .padding(2.dp) + .align(Alignment.Bottom) + ) { FilledTonalIconButton( modifier = Modifier .padding() @@ -125,38 +174,57 @@ fun PackagesListItem( } } AnimatedVisibility(visible = isExpanded) { - Box{ - Column(modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 6.dp) - ) { - packages.forEach { version -> - val title = packages[packages.indexOf(version)].Title - val link = packages[packages.indexOf(version)].Link - //if the package title has ARM64-V8A, the type is Arm64 - val isArm64: Boolean = title.contains("ARM64-V8A") - val containsArch: Boolean = title.contains("(ARM64-V8A)") || title.contains("ARMEABI-V7A") - //get just the version name without the architecture - val versionName = if (containsArch) title.substringBefore("(").trim() else title - PackageItem( - modifier = Modifier - .fillMaxWidth(), - //if its Arm64, ArchType is Arm64, else ArchType is Arm - type = if (isArm64) ArchType.Arm64 else ArchType.Arm, - version = versionName, - link = link, - //on click open the link in browser - onClick = { DownloadUtil.openLinkInBrowser(link) }, - onArchClick = {show = !show}, - onCopyClick = {DownloadUtil.copyLinkToClipboard(link)} + Box { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 6.dp) + //adjust the size of the column to the quantity of items + .height( + when { + packages.size <= 2 -> 84.dp + else -> packages.size * 18.dp + } ) + ) { + LazyColumn { + items( + items = packages, + ) { packageObject -> + val title = packageObject.Title + val link = packageObject.Link + + //if the package title has ARM64-V8A, the type is Arm64 + val isArm64: Boolean = title.contains("ARM64-V8A") + + val containsArch: Boolean = + title.contains("(ARM64-V8A)") || title.contains("ARMEABI-V7A") + + //Get just the version name without the architecture + val versionName = + if (containsArch) title.substringBefore("(").trim() else title - if (packages.indexOf(version) != packages.lastIndex) { - Divider( + PackageItem( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp) + .fillMaxWidth(), + //if its Arm64, ArchType is Arm64, else ArchType is Arm + type = if (isArm64) ArchType.Arm64 else ArchType.Arm, + version = versionName, + link = link, + //on click open the link in browser + onClick = { DownloadUtil.openLinkInBrowser(link) }, + onArchClick = { show = !show }, + onCopyClick = { DownloadUtil.copyLinkToClipboard(link) } ) + + //the last item of the lazy column will not have divider + if (packageObject != packages.last()) { + Divider( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp) + ) + } } } } @@ -173,19 +241,26 @@ fun PackagesListItem( ), ) { // content - Surface(modifier = Modifier, shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)) { - Column(modifier = Modifier - .fillMaxWidth() - .padding(16.dp)) { + Surface( + modifier = Modifier, + shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { Text( text = stringResource(id = R.string.architectures), modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) - Text(text = stringResource(id = R.string.archs_desc), + Text( + text = stringResource(id = R.string.archs_desc), modifier = Modifier, - style = MaterialTheme.typography.bodySmall) + style = MaterialTheme.typography.bodySmall + ) Divider( modifier = Modifier @@ -223,10 +298,39 @@ fun PackagesListItem( @Composable @Preview -fun CardPreview(){ +fun CardPreview() { Column() { - // PackagesListItem( type = PackagesListItemType.RegularCloned, expanded = true, versions = listOf("1.0.0", "1.0.1", "1.0.2").random(), archs = listOf(ArchType.Arm64, ArchType.Arm).random()) + // PackagesListItem( type = PackagesListItemType.RegularCloned, expanded = true, versions = listOf("1.0.0", "1.0.1", "1.0.2").random(), archs = listOf(ArchType.Arm64, ArchType.Arm).random()) //PackagesListItem(type = PackagesListItemType.Amoled, expanded = true, versions = listOf("1.0.0", "1.0.1", "1.0.2").random(), archs = listOf(ArchType.Arm64, ArchType.Arm).random()) } +} +//create a scrollbar for the lazy column +@Composable +fun Scrollbar( + modifier: Modifier = Modifier, + scrollState: ScrollState, + itemCount: Int, + averageItemSize: Dp +) { + val thumbHeight = with(LocalDensity.current) { + (scrollState.maxValue / itemCount * averageItemSize.toPx()).toDp() + } + val thumbOffset = with(LocalDensity.current) { + (scrollState.value / itemCount * averageItemSize.toPx()).toDp() + } + Box( + modifier = modifier + .fillMaxHeight() + .width(8.dp) + .padding(horizontal = 4.dp) + ) { + Box( + Modifier + .fillMaxWidth() + .height(thumbHeight) + .offset(y = thumbOffset) + .background(MaterialTheme.colorScheme.onPrimaryContainer) + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/InitialEntry.kt b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/InitialEntry.kt index d8cf3979..7670fa1a 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/InitialEntry.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/InitialEntry.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable @@ -86,7 +87,7 @@ fun InitialEntry(homeViewModel: HomeViewModel, } } - val homeviewState = homeViewModel.stateFlow.collectAsState() + val homeViewState = homeViewModel.stateFlow.collectAsState() val searcherViewState = searcherViewModel.stateFlow.collectAsState() @@ -94,7 +95,7 @@ fun InitialEntry(homeViewModel: HomeViewModel, Box( modifier = Modifier .fillMaxSize() - .background(androidx.compose.material3.MaterialTheme.colorScheme.background) + .background(MaterialTheme.colorScheme.background) ){ AnimatedNavHost( modifier = Modifier @@ -111,7 +112,7 @@ fun InitialEntry(homeViewModel: HomeViewModel, animatedComposable(Route.HOME){ HomePage(navController = navController, homeViewModel = homeViewModel) - if (!homeviewState.value.loaded){ + if (!homeViewState.value.loaded){ homeViewModel.setup() } } diff --git a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomePage.kt b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomePage.kt index dc7c1256..a864d812 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomePage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomePage.kt @@ -41,27 +41,35 @@ fun HomePage(navController: NavController, homeViewModel: HomeViewModel = hiltVi val scope = rememberCoroutineScope() val clipboardManager = LocalClipboardManager.current val hapticFeedback = LocalHapticFeedback.current - // val keyboardController = LocalSoftwareKeyboardController.current + // val keyboardController = LocalSoftwareKeyboardController.current val viewState = homeViewModel.stateFlow.collectAsState() val regularVersions = viewState.value.regular_versions val regularClonedVersions = viewState.value.regular_cloned_versions val amoledVersions = viewState.value.amoled_versions val amoledClonedVersions = viewState.value.amoled_cloned_versions + val liteVersions = viewState.value.liteVersions + //Version strings + val regularLastVersion = viewState.value.regularSpotifyVersion + val regularClonedLastVersion = viewState.value.clonedSpotifyVersion + val amoledLastVersion = viewState.value.amoledSpotifyVersion + val amoledClonedLastVersion = viewState.value.amoledClonedSpotifyVersion + val liteLastVersion = viewState.value.liteSpotifyVersion - with(viewState.value){ + with(viewState.value) { Box( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background) - ){ + ) { Scaffold(modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background), topBar = { TopAppBar( title = {}, - modifier = Modifier.padding(horizontal = 8.dp) + modifier = Modifier + .padding(horizontal = 8.dp) .fillMaxWidth(), navigationIcon = { IconButton(onClick = { @@ -74,50 +82,102 @@ fun HomePage(navController: NavController, homeViewModel: HomeViewModel = hiltVi } }) }) { - Column(modifier = Modifier - .padding(it) - .fillMaxSize() - .verticalScroll(rememberScrollState())) + Column( + modifier = Modifier + .padding(it) + .fillMaxSize() + .verticalScroll(rememberScrollState()) + ) { - Column(modifier = Modifier - .padding(16.dp)) - { - Row(modifier = Modifier - .fillMaxWidth() - .align(Alignment.Start) - .padding(start = 8.dp, top = 12.dp, bottom = 12.dp, end = 8.dp)) - { - Text( - modifier = Modifier, - text = stringResource(R.string.app_name), - style = MaterialTheme.typography.displaySmall + if (isLoading) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.Center) + .size(48.dp) ) } - PackagesListItem( type = PackagesListItemType.Regular, expanded = false, onClick = {}, packages = regularVersions.sortedByDescending { it.Title }) - PackagesListItem( type = PackagesListItemType.RegularCloned, expanded = false, onClick = {}, packages = regularClonedVersions.sortedByDescending { it.Title }) - PackagesListItem( type = PackagesListItemType.Amoled, expanded = false, onClick = {}, packages = amoledVersions.sortedByDescending { it.Title }) - PackagesListItem( type = PackagesListItemType.AmoledCloned, expanded = false, onClick = {}, packages = amoledClonedVersions.sortedByDescending { it.Title }) - Divider(modifier = Modifier.padding(top = 16.dp, bottom = 14.dp)) - AnimatedVisibility(visible = loaded) { - when(loaded){ - false -> { - Box(modifier = Modifier.fillMaxWidth()) { - CircularProgressIndicator(modifier = Modifier - .align(Alignment.Center) - .size(24.dp)) + } else { + Column( + modifier = Modifier + .padding(16.dp) + ) + { + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Start) + .padding(start = 8.dp, top = 12.dp, bottom = 12.dp, end = 8.dp) + ) + { + Text( + modifier = Modifier, + text = stringResource(R.string.app_name), + style = MaterialTheme.typography.displaySmall + ) + } + PackagesListItem( + type = PackagesListItemType.Regular, + expanded = false, + onClick = {}, + packages = homeViewModel.sortPackagesByVersion(regularVersions), //regularVersions.sortedByDescending { it.Title }, + latestVersion = regularLastVersion + ) + PackagesListItem( + type = PackagesListItemType.RegularCloned, + expanded = false, + onClick = {}, + packages = homeViewModel.sortPackagesByVersion(regularClonedVersions), + latestVersion = regularClonedLastVersion + ) + PackagesListItem( + type = PackagesListItemType.Amoled, + expanded = false, + onClick = {}, + packages = homeViewModel.sortPackagesByVersion(amoledVersions), + latestVersion = amoledLastVersion + ) + PackagesListItem( + type = PackagesListItemType.AmoledCloned, + expanded = false, + onClick = {}, + packages = homeViewModel.sortPackagesByVersion(amoledClonedVersions), + latestVersion = amoledClonedLastVersion + ) + PackagesListItem( + type = PackagesListItemType.Lite, + expanded = false, + onClick = {}, + packages = homeViewModel.sortPackagesByVersion(liteVersions), + latestVersion = liteLastVersion + ) + Divider(modifier = Modifier.padding(top = 16.dp, bottom = 14.dp)) + AnimatedVisibility(visible = loaded) { + when (loaded) { + false -> { + Box(modifier = Modifier.fillMaxWidth()) { + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.Center) + .size(24.dp) + ) + } + } + true -> { + RelevantInfoItem( + cpuArch = cpuArch, + originalSpotifyVersion = originalSpotifyVersion, + clonedSpotifyVersion = clonedSpotifyVersion, + ) } - } - true -> { - RelevantInfoItem( - cpuArch = cpuArch, - originalSpotifyVersion = originalSpotifyVersion, - clonedSpotifyVersion = clonedSpotifyVersion, - ) } } } - } + } } } } diff --git a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomeViewModel.kt b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomeViewModel.kt index 38939dbd..b3b36176 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomeViewModel.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/presentation/ui/pages/home/HomeViewModel.kt @@ -27,17 +27,25 @@ class HomeViewModel @Inject constructor( private val mutableStateFlow = MutableStateFlow(HomeViewState()) val stateFlow = mutableStateFlow.asStateFlow() private var currentJob: Job? = null + private val emptyAPIList: APIResponse = APIResponse("", "", "", "", "", emptyList(), emptyList(), emptyList(), emptyList(), emptyList()) data class HomeViewState( val regular_versions: List = mutableListOf(), val regular_cloned_versions: List = mutableListOf(), val amoled_versions: List = mutableListOf(), val amoled_cloned_versions: List = mutableListOf(), + val liteVersions: List = mutableListOf(), val cpuArch: String = "", val originalSpotifyVersion: String = "", + val regularSpotifyVersion: String = "", val clonedSpotifyVersion: String = "", + val amoledSpotifyVersion: String = "", + val amoledClonedSpotifyVersion: String = "", + val liteSpotifyVersion: String = "", val loaded: Boolean = false, val regular_latest_version: String = "", + val isError: Boolean = false, + val isLoading: Boolean = true, ) private val _state = mutableStateOf(APICallState()) @@ -65,6 +73,10 @@ class HomeViewModel @Inject constructor( } } + fun sortPackagesByVersion(list: List): List{ + return list.sortedByDescending { it.Title } + } + private fun callAPI(){ currentJob?.cancel() currentJob = viewModelScope.launch { @@ -73,16 +85,7 @@ class HomeViewModel @Inject constructor( when(result){ is Resource.Success -> { _state.value = state.value.copy( - APIResponse = result.data ?: APIResponse( - Regular_Latest = "", - Amoled_Latest = "", - RC_Latest = "", - ABC_Latest = "", - Regular = emptyList(), - Amoled = emptyList(), - Regular_Cloned = emptyList(), - Amoled_Cloned = emptyList() - ), + APIResponse = result.data ?: emptyAPIList, isLoading = false ) val localAPIResponse = state.value.APIResponse @@ -94,38 +97,40 @@ class HomeViewModel @Inject constructor( amoled_versions = localAPIResponse.Amoled, amoled_cloned_versions = localAPIResponse.Amoled_Cloned, regular_latest_version = localAPIResponse.Regular_Latest, + liteSpotifyVersion = localAPIResponse.Lite_Latest, + liteVersions = localAPIResponse.Lite, + regularSpotifyVersion = localAPIResponse.Regular_Latest, + amoledSpotifyVersion = localAPIResponse.Amoled_Latest, + amoledClonedSpotifyVersion = localAPIResponse.ABC_Latest, + clonedSpotifyVersion = localAPIResponse.RC_Latest, + //UI stuff + isError = false, + isLoading = false, ) } } is Resource.Error -> { _state.value = state.value.copy( - APIResponse = result.data ?: APIResponse( - Regular_Latest = "", - Amoled_Latest = "", - RC_Latest = "", - ABC_Latest = "", - Regular = emptyList(), - Amoled = emptyList(), - Regular_Cloned = emptyList(), - Amoled_Cloned = emptyList() - ), + APIResponse = result.data ?: emptyAPIList, isLoading = false ) + mutableStateFlow.update { + it.copy( + isError = true, + isLoading = false, + ) + } } is Resource.Loading -> { _state.value = state.value.copy( - APIResponse = result.data ?: APIResponse( - Regular_Latest = "", - Amoled_Latest = "", - RC_Latest = "", - ABC_Latest = "", - Regular = emptyList(), - Amoled = emptyList(), - Regular_Cloned = emptyList(), - Amoled_Cloned = emptyList() - ), + APIResponse = result.data ?: emptyAPIList, isLoading = true ) + mutableStateFlow.update { + it.copy( + isLoading = true, + ) + } } } }.launchIn(this) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9eb49683..c4e9a2cb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,4 +55,7 @@ \"spowlo://spotify-auth\" \"spowlo://spotify-pkce\" \"abcad8ba647d4b0ebae797a8f444ac9b\" + Spotify Lite + "A lightweight version of Spotify with no ads and unlimited skips. " + Latest version \ No newline at end of file