Skip to content

Commit

Permalink
Pull to refresh on main screens (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
siper authored Feb 8, 2025
1 parent d7fccd8 commit 23efdef
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 75 deletions.
1 change: 1 addition & 0 deletions feature/explore/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ dependencies {
implementation(libs.coil.compose)
implementation(libs.bundles.koin)
implementation(libs.compose.constraintLayout)
implementation(libs.timber)
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ internal class ExploreRepositoryImpl(
}
}

override suspend fun refresh() {
songRandomStorage.refresh()
}

private fun PlayingSource?.isSongPlaying(serverId: Long, songId: String): Boolean {
if (this == null) {
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import kotlinx.coroutines.flow.Flow

internal interface ExploreRepository {
fun getExplore(): Flow<Explore>
suspend fun refresh()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.derivedStateOf
Expand Down Expand Up @@ -54,6 +55,7 @@ fun ExploreScreen(
onSearchClick = onSearchClick,
onSongClick = onSongClick,
onRandomSongsClick = onRandomSongsClick,
onRefresh = viewModel::refresh,
onRetry = viewModel::retry,
onPlayPauseAudioSource = viewModel::onPlayPauseAudioSource,
)
Expand All @@ -66,6 +68,7 @@ private fun ExploreScreen(
onSongClick: (id: String) -> Unit,
onRandomSongsClick: () -> Unit,
onRetry: () -> Unit,
onRefresh: () -> Unit,
onPlayPauseAudioSource: (source: AudioSource) -> Unit,
modifier: Modifier = Modifier
) {
Expand All @@ -78,28 +81,33 @@ private fun ExploreScreen(
}
}
}
StateLayout(
state = layoutState,
content = {
Content(
state = state,
modifier = modifier,
onSearchClick = onSearchClick,
onSongClick = onSongClick,
onRandomSongsClick = onRandomSongsClick,
onPlayPauseAudioSource = onPlayPauseAudioSource
)
},
progress = {
Progress()
},
error = {
ErrorLayout(onRetry = onRetry)
},
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
)
PullToRefreshBox(
isRefreshing = state.refreshing,
onRefresh = onRefresh
) {
StateLayout(
state = layoutState,
content = {
Content(
state = state,
modifier = modifier,
onSearchClick = onSearchClick,
onSongClick = onSongClick,
onRandomSongsClick = onRandomSongsClick,
onPlayPauseAudioSource = onPlayPauseAudioSource
)
},
progress = {
Progress()
},
error = {
ErrorLayout(onRetry = onRetry)
},
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
)
}
}

@Composable
Expand Down Expand Up @@ -227,10 +235,10 @@ private fun Progress(
}
}

@Immutable
internal data class StateUi(
val progress: Boolean = true,
val error: Boolean = false,
val refreshing: Boolean = false,
val data: DataUi? = null
)

Expand All @@ -246,6 +254,7 @@ private fun ExploreScreenPreview() {
ExploreScreen(
state = StateUi(),
onRetry = {},
onRefresh = {},
onSongClick = {},
onRandomSongsClick = {},
onPlayPauseAudioSource = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ru.stersh.youamp.shared.player.queue.PlayerQueueAudioSourceManager
import ru.stersh.youamp.shared.player.queue.equals
import ru.stersh.youamp.shared.player.state.PlayStateStore
import ru.stresh.youamp.feature.explore.domain.ExploreRepository
import timber.log.Timber

internal class ExploreViewModel(
private val repository: ExploreRepository,
Expand Down Expand Up @@ -46,6 +47,7 @@ internal class ExploreViewModel(
.catch {
_state.update {
it.copy(
refreshing = false,
progress = false,
error = true
)
Expand All @@ -54,6 +56,7 @@ internal class ExploreViewModel(
.collect { explore ->
_state.update {
it.copy(
refreshing = false,
progress = false,
data = explore
)
Expand All @@ -62,6 +65,16 @@ internal class ExploreViewModel(
}
}

fun refresh() = viewModelScope.launch {
_state.update {
it.copy(refreshing = true)
}
runCatching { repository.refresh() }
.onFailure { Timber.w(it) }
stateJob?.cancel()
subscribeState()
}

fun retry() {
stateJob?.cancel()
_state.update {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
Expand Down Expand Up @@ -57,6 +58,7 @@ fun LibraryScreen(
onAlbumsClick = onAlbumsClick,
onArtistsClick = onArtistsClick,
onRetry = viewModel::retry,
onRefresh = viewModel::refresh,
onPlayPauseAudioSource = viewModel::onPlayPauseAudioSource
)
}
Expand All @@ -70,6 +72,7 @@ internal fun LibraryScreen(
onArtistsClick: () -> Unit,
onPlayPauseAudioSource: (source: AudioSource) -> Unit,
onRetry: () -> Unit,
onRefresh: () -> Unit,
) {
val layoutState by remember(state) {
derivedStateOf {
Expand All @@ -80,28 +83,33 @@ internal fun LibraryScreen(
}
}
}
StateLayout(
state = layoutState,
content = {
Content(
data = state.data,
onAlbumClick = onAlbumClick,
onArtistClick = onArtistClick,
onAlbumsClick = onAlbumsClick,
onArtistsClick = onArtistsClick,
onPlayPauseAudioSource = onPlayPauseAudioSource
)
},
progress = {
Progress()
},
error = {
ErrorLayout(onRetry = onRetry)
},
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
)
PullToRefreshBox(
isRefreshing = state.refreshing,
onRefresh = onRefresh
) {
StateLayout(
state = layoutState,
content = {
Content(
data = state.data,
onAlbumClick = onAlbumClick,
onArtistClick = onArtistClick,
onAlbumsClick = onAlbumsClick,
onArtistsClick = onArtistsClick,
onPlayPauseAudioSource = onPlayPauseAudioSource
)
},
progress = {
Progress()
},
error = {
ErrorLayout(onRetry = onRetry)
},
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
)
}
}

@Composable
Expand Down Expand Up @@ -278,6 +286,7 @@ private fun LibraryScreenPreview() {
LibraryScreen(
state = StateUi(),
onRetry = {},
onRefresh = {},
onAlbumClick = {},
onArtistClick = {},
onArtistsClick = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,17 @@ internal class LibraryViewModel(
_state.update {
it.copy(
progress = false,
error = true
error = true,
refreshing = false
)
}
}
.collect { explore ->
_state.update {
it.copy(
progress = false,
refreshing = false,
error = false,
data = explore
)
}
Expand All @@ -75,6 +78,14 @@ internal class LibraryViewModel(
subscribeState()
}

fun refresh() {
stateJob?.cancel()
_state.update {
it.copy(refreshing = true)
}
subscribeState()
}

fun onPlayPauseAudioSource(source: AudioSource) {
viewModelScope.launch {
val playingSource = playerQueueAudioSourceManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.runtime.Immutable
internal data class StateUi(
val progress: Boolean = true,
val error: Boolean = false,
val refreshing: Boolean = false,
val data: DataUi? = null
)

Expand Down
Loading

0 comments on commit 23efdef

Please sign in to comment.