From e6f3386e2d0b78a8f26f753286afd613474d3948 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:18:06 +0530 Subject: [PATCH 1/4] Update versions --- .../brainzplayer/BrainzPlayerBackDropScreen.kt | 13 ++++++++----- .../android/ui/screens/feed/FeedScreen.kt | 2 +- .../android/ui/screens/profile/UserData.kt | 7 +++---- .../java/org/listenbrainz/android/ui/theme/Theme.kt | 13 +++++++++---- gradle/libs.versions.toml | 6 +++--- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt index 87b87d1a..2141406e 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/brainzplayer/BrainzPlayerBackDropScreen.kt @@ -50,6 +50,7 @@ import androidx.compose.material3.FloatingActionButtonDefaults import androidx.compose.material3.LargeFloatingActionButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf @@ -98,7 +99,6 @@ import org.listenbrainz.android.viewmodel.PlaylistViewModel import kotlin.math.absoluteValue import kotlin.math.max -@OptIn(ExperimentalFoundationApi::class) @ExperimentalMaterialApi @Composable fun BrainzPlayerBackDropScreen( @@ -136,8 +136,11 @@ fun BrainzPlayerBackDropScreen( appBar = {}, persistentAppBar = false, frontLayerContent = { - val delta by backdropScaffoldState.offset - maxDelta = max(delta, maxDelta) + LaunchedEffect(Unit) { + val delta = backdropScaffoldState.requireOffset() + maxDelta = max(delta, maxDelta) + } + PlayerScreen( currentlyPlayingSong = currentlyPlayingSong, isShuffled = isShuffled, @@ -146,7 +149,7 @@ fun BrainzPlayerBackDropScreen( val songList = brainzPlayerViewModel.mediaItem.collectAsState().value.data ?: listOf() SongViewPager( modifier = Modifier.graphicsLayer { - alpha = ( delta / (maxDelta - headerHeight.toPx()) ) + alpha = ( backdropScaffoldState.requireOffset() / (maxDelta - headerHeight.toPx()) ) }, songList = songList, backdropScaffoldState = backdropScaffoldState, @@ -511,7 +514,7 @@ fun AlbumArtViewPager(currentlyPlayingSong: Song, pagerState: PagerState) { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror // any effects for both directions - val pageOffset = pagerState.getOffsetFractionForPage(page).absoluteValue + val pageOffset = pagerState.getOffsetDistanceInPages(page).absoluteValue // We animate the scaleX + scaleY, between 85% and 100% lerp( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt index 873fc0a7..6b299460 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt @@ -221,7 +221,7 @@ fun FeedScreen( HorizontalPager( state = pagerState, - beyondBoundsPageCount = 1 + beyondViewportPageCount = 1 ) { position -> when (position) { 0 -> MyFeed( diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/UserData.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/UserData.kt index c38292ee..c047dd03 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/profile/UserData.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/profile/UserData.kt @@ -51,7 +51,6 @@ import org.listenbrainz.android.ui.theme.ListenBrainzTheme import org.listenbrainz.android.ui.theme.offWhite import org.listenbrainz.android.ui.theme.onScreenUiModeIsDark -@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun UserData( preferencesUiState: PreferencesUiState, @@ -141,9 +140,9 @@ fun UserData( color = if (onScreenUiModeIsDark()) Color.White else Color.Black ) }, - colors = TextFieldDefaults.outlinedTextFieldColors( - focusedBorderColor = if (onScreenUiModeIsDark()) Color.White else Color.Black, - unfocusedBorderColor = if (onScreenUiModeIsDark()) Color.White else Color.Black, + colors = TextFieldDefaults.colors( + focusedIndicatorColor = if (onScreenUiModeIsDark()) Color.White else Color.Black, + unfocusedIndicatorColor = if (onScreenUiModeIsDark()) Color.White else Color.Black, cursorColor = if (onScreenUiModeIsDark()) Color.White else Color.Black ) ) diff --git a/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt b/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt index 42740019..18a133b7 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/theme/Theme.kt @@ -284,10 +284,15 @@ private lateinit var LocalUiMode: ProvidableCompositionLocal * what theme the device is using. Different from [isSystemInDarkTheme].*/ @Composable fun onScreenUiModeIsDark() : Boolean { - return when (LocalUiMode.current){ - UiMode.DARK -> true - UiMode.LIGHT -> false - else -> isSystemInDarkTheme() + val uiMode = LocalUiMode.current + val isSystemInDarkTheme = isSystemInDarkTheme() + + return remember(uiMode, isSystemInDarkTheme) { + when (uiMode){ + UiMode.DARK -> true + UiMode.LIGHT -> false + else -> isSystemInDarkTheme + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b62b0f3..c288b96e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.0.0" navigation = "2.7.7" hilt = "2.52" -compose = "1.6.8" +compose = "1.7.5" room = "2.6.1" accompanist = "0.34.0" work = "2.9.1" @@ -11,9 +11,9 @@ paging = "3.3.2" androidGradlePlugin = "8.5.2" sentry = "4.10.0" ksp = "2.0.0-1.0.23" -composeBom = "2024.08.00" +composeBom = "2024.11.00" appcompat = "1.7.0" -lifecycle = "2.8.4" +lifecycle = "2.8.7" browser = "1.8.0" preference = "1.2.1" coreSplashscreen = "1.0.1" From 0fad9fd0d05338d5c71e58d8aecc4771a8e99d19 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:42:59 +0530 Subject: [PATCH 2/4] Fix stability --- .../listenbrainz/android/ui/screens/feed/FeedUiState.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedUiState.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedUiState.kt index 35fb9ba7..cddcd298 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedUiState.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedUiState.kt @@ -1,5 +1,6 @@ package org.listenbrainz.android.ui.screens.feed +import androidx.compose.runtime.Stable import androidx.paging.PagingData import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow @@ -7,8 +8,8 @@ import org.listenbrainz.android.model.ResponseError import org.listenbrainz.android.model.feed.FeedEvent import org.listenbrainz.android.model.feed.FeedEventType - /** Top most state wrapper for Feed Screen.*/ +@Stable data class FeedUiState( val myFeedState: FeedUiEventData = FeedUiEventData(), val followListensFeedState: FeedUiEventData = FeedUiEventData(), @@ -18,13 +19,15 @@ data class FeedUiState( ) /** Data held by each screen.*/ +@Stable data class FeedUiEventData( val isHiddenMap: Map = emptyMap(), val isDeletedMap: Map = emptyMap(), - var eventList: Flow> = emptyFlow() + val eventList: Flow> = emptyFlow() ) /** UI representation for one feed event.*/ +@Stable data class FeedUiEventItem( val eventType: FeedEventType, val event: FeedEvent, From 44907cbb06fbe816834da163295c7055878c6100 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:49:19 +0530 Subject: [PATCH 3/4] move class init effect to flow collection start --- .../android/ui/screens/feed/FeedScreen.kt | 2 +- .../android/viewmodel/FeedViewModel.kt | 57 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt index 6b299460..dd3d0fa4 100644 --- a/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt +++ b/app/src/main/java/org/listenbrainz/android/ui/screens/feed/FeedScreen.kt @@ -131,7 +131,7 @@ fun FeedScreen( } -@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterialApi::class) @Composable fun FeedScreen( uiState: FeedUiState, diff --git a/app/src/main/java/org/listenbrainz/android/viewmodel/FeedViewModel.kt b/app/src/main/java/org/listenbrainz/android/viewmodel/FeedViewModel.kt index d708b7ce..1098b7c1 100644 --- a/app/src/main/java/org/listenbrainz/android/viewmodel/FeedViewModel.kt +++ b/app/src/main/java/org/listenbrainz/android/viewmodel/FeedViewModel.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -101,28 +102,6 @@ class FeedViewModel @Inject constructor( // Exposed UI state override val uiState = createUiStateFlow() - init { - viewModelScope.launch(defaultDispatcher) { - searchFollowerQuery.collectLatest { query -> - if (query.isEmpty()) return@collectLatest - - val result = socialRepository.getFollowers(appPreferences.username.get()) - if (result.status == Resource.Status.SUCCESS){ - searchFollowerResult.emit( - result.data?.followers?.filter { - it.startsWith(query, ignoreCase = true) || it.contains(query, ignoreCase = true) - } ?: emptyList() - ) - println(searchFollowerResult.value) - } else { - emitError(error = result.error) - } - - } - } - - } - override fun createUiStateFlow(): StateFlow { return combine( myFeedFlow, @@ -132,11 +111,15 @@ class FeedViewModel @Inject constructor( errorFlow ){ feedScreenState, followListensState, similarListensState, searchResult, error -> FeedUiState(feedScreenState, followListensState, similarListensState, searchResult, error) - }.stateIn( - viewModelScope, - SharingStarted.Eagerly, - FeedUiState() - ) + } + .onStart { + observeSearchFollowerQuery() + } + .stateIn( + viewModelScope, + SharingStarted.Eagerly, + FeedUiState() + ) } private fun createNewMyFeedPagingSource(): MyFeedPagingSource = @@ -320,5 +303,23 @@ class FeedViewModel @Inject constructor( e.printStackTrace() } } - + + private fun observeSearchFollowerQuery() { + viewModelScope.launch(defaultDispatcher) { + searchFollowerQuery.collectLatest { query -> + if (query.isEmpty()) return@collectLatest + + val result = socialRepository.getFollowers(appPreferences.username.get()) + if (result.status == Resource.Status.SUCCESS){ + searchFollowerResult.emit( + result.data?.followers?.filter { + it.startsWith(query, ignoreCase = true) || it.contains(query, ignoreCase = true) + } ?: emptyList() + ) + } else { + emitError(error = result.error) + } + } + } + } } \ No newline at end of file From cd76e268d691b3b01f0c3d2013a753604b25ea3b Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:01:23 +0530 Subject: [PATCH 4/4] Prepare 2.7.3 --- app/build.gradle.kts | 4 ++-- fastlane/metadata/android/en-US/changelogs/55.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/55.txt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 656e63d3..0aa0a03a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,8 +22,8 @@ android { applicationId = "org.listenbrainz.android" minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 54 - versionName = "2.7.2" + versionCode = 55 + versionName = "2.7.3" multiDexEnabled = true testInstrumentationRunner = "org.listenbrainz.android.di.CustomTestRunner" vectorDrawables { diff --git a/fastlane/metadata/android/en-US/changelogs/55.txt b/fastlane/metadata/android/en-US/changelogs/55.txt new file mode 100644 index 00000000..c603e565 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/55.txt @@ -0,0 +1 @@ +Bug fixes and improvements \ No newline at end of file