Skip to content

Commit

Permalink
Merge pull request #63 from swingmx/fav-from-menu
Browse files Browse the repository at this point in the history
`:folder`,  `:album`, `:artist`, `:queue`   Add Fav From BottomSheet
  • Loading branch information
Ericgacoki authored Jan 9, 2025
2 parents 2d280df + 72c0869 commit 6094d11
Show file tree
Hide file tree
Showing 19 changed files with 450 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import androidx.navigation.NavOptionsBuilder
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.android.swingmusic.album.presentation.screen.destinations.AllAlbumScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.ArtistsScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.AllArtistsScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.ViewAllScreenDestination
import com.android.swingmusic.artist.presentation.viewmodel.ArtistInfoViewModel
import com.android.swingmusic.auth.data.workmanager.scheduleTokenRefreshWork
Expand Down Expand Up @@ -133,7 +133,7 @@ class MainActivity : ComponentActivity() {
val showBottomNav = route in listOf(
"folder/${FoldersAndTracksScreenDestination.route}",
"album/${AllAlbumScreenDestination.route}",
"artist/${ArtistsScreenDestination.route}"
"artist/${AllArtistsScreenDestination.route}"
)

val bottomNavHeight by animateDpAsState(
Expand All @@ -146,7 +146,7 @@ class MainActivity : ComponentActivity() {
val showSpacer = route !in listOf(
"folder/${FoldersAndTracksScreenDestination.route}",
"album/${AllAlbumScreenDestination.route}",
"artist/${ArtistsScreenDestination.route}",
"artist/${AllArtistsScreenDestination.route}",
)

val spacerHeight by animateDpAsState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.android.swingmusic.presentation.navigator

import com.android.swingmusic.album.presentation.screen.destinations.AlbumWithInfoScreenDestination
import com.android.swingmusic.album.presentation.screen.destinations.AllAlbumScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.AllArtistsScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.ArtistInfoScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.ArtistsScreenDestination
import com.android.swingmusic.artist.presentation.screen.destinations.ViewAllScreenDestination
import com.android.swingmusic.auth.presentation.screen.destinations.LoginWithQrCodeDestination
import com.android.swingmusic.auth.presentation.screen.destinations.LoginWithUsernameScreenDestination
Expand Down Expand Up @@ -75,11 +75,11 @@ object NavGraphs {
val artist = object : NavGraphSpec {
override val route: String = "artist"

override val startRoute: Route = ArtistsScreenDestination routedIn this
override val startRoute: Route = AllArtistsScreenDestination routedIn this

override val destinationsByRoute: Map<String, DestinationSpec<*>> =
listOf<DestinationSpec<*>>(
ArtistsScreenDestination,
AllArtistsScreenDestination,
ArtistInfoScreenDestination,
AlbumWithInfoScreenDestination,
ViewAllScreenDestination,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ interface AlbumWithInfoUiEvent {

object OnRefreshAlbumInfo : AlbumWithInfoUiEvent

object ResetState: AlbumWithInfoUiEvent
object ResetState : AlbumWithInfoUiEvent

data class OnToggleAlbumFavorite(
val isFavorite: Boolean,
val albumHash: String,
) : AlbumWithInfoUiEvent

data class OnToggleAlbumTrackFavorite(
val trackHash: String,
val favorite: Boolean
) : AlbumWithInfoUiEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,16 @@ fun AlbumWithInfo(
playbackState: PlaybackState,
albumInfo: AlbumInfo,
copyright: String,
albumTracks: Map<Int, List<Track>>,
albumTracksMap: Map<Int, List<Track>>,
baseUrl: String,
onClickBack: () -> Unit,
onClickMore: () -> Unit,
onClickArtist: (artistHsh: String) -> Unit,
onClickAlbumTrack: (index: Int, queue: List<Track>) -> Unit,
onToggleTrackFavorite: (isFavorite: Boolean, trackHash: String) -> Unit,
onPlay: (queue: List<Track>) -> Unit,
onShuffle: () -> Unit,
onToggleFavorite: (Boolean, String) -> Unit,
onToggleAlbumFavorite: (Boolean, String) -> Unit,
onToggleTrackFavorite: (trackHash: String, isFavorite: Boolean) -> Unit,
onGetSheetAction: (track: Track, sheetAction: BottomSheetAction) -> Unit,
onGotoArtist: (hash: String) -> Unit,
) {
Expand All @@ -140,12 +140,21 @@ fun AlbumWithInfo(
var showTrackBottomSheet by remember { mutableStateOf(false) }
var clickedTrack: Track? by remember { mutableStateOf(null) }

LaunchedEffect(albumTracksMap) {
albumTracksMap.forEach { entry ->
clickedTrack = entry.value.find { track ->
track.trackHash == clickedTrack?.trackHash
} ?: clickedTrack
}
}

Scaffold {
if (showTrackBottomSheet) {
clickedTrack?.let { track ->
CustomTrackBottomSheet(
scope = scope,
sheetState = sheetState,
isFavorite = track.isFavorite,
clickedTrack = track,
baseUrl = baseUrl,
bottomSheetItems = listOf(
Expand Down Expand Up @@ -186,8 +195,8 @@ fun AlbumWithInfo(
onChooseArtist = { hash ->
onGotoArtist(hash)
},
onToggleTrackFavorite = { isFavorite, trackHash ->
onToggleTrackFavorite(isFavorite, trackHash)
onToggleTrackFavorite = { trackHash, isFavorite ->
onToggleTrackFavorite(trackHash, isFavorite)
}
)
}
Expand Down Expand Up @@ -408,7 +417,7 @@ fun AlbumWithInfo(
else R.drawable.fav_not_filled
IconButton(
onClick = {
onToggleFavorite(
onToggleAlbumFavorite(
albumInfo.isFavorite,
albumInfo.albumHash
)
Expand Down Expand Up @@ -456,7 +465,7 @@ fun AlbumWithInfo(
Spacer(modifier = Modifier.height(12.dp))
}

albumTracks.forEach { (discNumber, tracks) ->
albumTracksMap.forEach { (discNumber, tracks) ->
item {
// Disc Number Header
Text(
Expand Down Expand Up @@ -507,6 +516,7 @@ fun AlbumWithInfo(
) {
TrackItem(
track = track,
baseUrl = baseUrl,
isAlbumTrack = true,
showMenuIcon = true,
isCurrentTrack = track.trackHash == currentTrack?.trackHash,
Expand All @@ -520,8 +530,7 @@ fun AlbumWithInfo(
onClickMoreVert = {
clickedTrack = it
showTrackBottomSheet = true
},
baseUrl = baseUrl
}
)
}
}
Expand Down Expand Up @@ -775,7 +784,7 @@ fun AlbumWithInfoScreen(
playbackState = playerUiState.playbackState,
albumInfo = albumWithInfoState.infoResource.data?.albumInfo!!,
copyright = albumWithInfoState.infoResource.data?.copyright!!,
albumTracks = albumWithInfoState.infoResource.data!!.groupedTracks,
albumTracksMap = albumWithInfoState.infoResource.data!!.groupedTracks,
baseUrl = baseUrl ?: "https://default",
onClickBack = { navigator.navigateBack() },
onClickMore = {
Expand Down Expand Up @@ -828,7 +837,7 @@ fun AlbumWithInfoScreen(
)
)
},
onToggleFavorite = { isFavorite, albumHash ->
onToggleAlbumFavorite = { isFavorite, albumHash ->
albumWithInfoViewModel.onAlbumWithInfoUiEvent(
AlbumWithInfoUiEvent.OnToggleAlbumFavorite(
isFavorite,
Expand Down Expand Up @@ -899,8 +908,12 @@ fun AlbumWithInfoScreen(
onGotoArtist = { hash ->
navigator.gotoArtistInfo(artistHash = hash)
},
onToggleTrackFavorite = { isFavorite, trackHash ->
// TODO: Call Album Track fav toggle
onToggleTrackFavorite = { trackHash, isFavorite ->
albumWithInfoViewModel.onAlbumWithInfoUiEvent(
AlbumWithInfoUiEvent.OnToggleAlbumTrackFavorite(
trackHash, isFavorite,
)
)
}
)
}
Expand Down Expand Up @@ -1068,7 +1081,7 @@ fun AlbumWithInfoScreenPreview() {
playbackState = PlaybackState.PLAYING,
albumInfo = albumInfo,
copyright = "© 2018 Republic Records",
albumTracks = mapOf(
albumTracksMap = mapOf(
1 to listOf(tracks[1], tracks[5])
),
baseUrl = "",
Expand All @@ -1078,7 +1091,7 @@ fun AlbumWithInfoScreenPreview() {
onClickAlbumTrack = { index, queue -> },
onPlay = { queue -> },
onShuffle = {},
onToggleFavorite = { isFavorite, albumHash -> },
onToggleAlbumFavorite = { isFavorite, albumHash -> },
onGetSheetAction = { _, _ -> },
onGotoArtist = {},
onToggleTrackFavorite = { _, _ -> }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.android.swingmusic.album.presentation.state.AlbumInfoWithGroupedTrack
import com.android.swingmusic.album.presentation.state.AlbumWithInfoState
import com.android.swingmusic.core.data.util.Resource
import com.android.swingmusic.core.domain.model.AlbumWithInfo
import com.android.swingmusic.player.domain.repository.PLayerRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand All @@ -17,7 +18,8 @@ import javax.inject.Inject

@HiltViewModel
class AlbumWithInfoViewModel @Inject constructor(
private val albumRepository: AlbumRepository
private val albumRepository: AlbumRepository,
private val pLayerRepository: PLayerRepository
) : ViewModel() {

private val _albumWithInfoState: MutableStateFlow<AlbumWithInfoState> =
Expand Down Expand Up @@ -123,6 +125,113 @@ class AlbumWithInfoViewModel @Inject constructor(
}
}

private fun toggleAlbumTrackFavorite(trackHash: String, isFavorite: Boolean) {
viewModelScope.launch {
// Optimistically update the Ui
_albumWithInfoState.value = _albumWithInfoState.value.copy(
orderedTracks = _albumWithInfoState.value.orderedTracks.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = !isFavorite)
} else {
track
}
}
)

_albumWithInfoState.value = _albumWithInfoState.value.copy(
infoResource = Resource.Success(
AlbumInfoWithGroupedTracks(
albumInfo = _albumWithInfoState.value.infoResource.data?.albumInfo,
groupedTracks = _albumWithInfoState.value.infoResource.data?.groupedTracks?.mapValues { entry ->
entry.value.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = !isFavorite)
} else {
track
}
}
} ?: emptyMap(),
copyright = _albumWithInfoState.value.infoResource.data?.copyright
)
)
)


val request = if (isFavorite) {
pLayerRepository.removeTrackFromFavorite(trackHash)
} else {
pLayerRepository.addTrackToFavorite(trackHash)
}

request.collectLatest {
when (it) {
is Resource.Loading -> {}

is Resource.Success -> {
_albumWithInfoState.value = _albumWithInfoState.value.copy(
orderedTracks = _albumWithInfoState.value.orderedTracks.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = it.data ?: false)
} else {
track
}
}
)

_albumWithInfoState.value = _albumWithInfoState.value.copy(
infoResource = Resource.Success(
AlbumInfoWithGroupedTracks(
albumInfo = _albumWithInfoState.value.infoResource.data?.albumInfo,
groupedTracks = _albumWithInfoState.value.infoResource.data?.groupedTracks?.mapValues { entry ->
entry.value.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = it.data ?: false)
} else {
track
}
}
} ?: emptyMap(),
copyright = _albumWithInfoState.value.infoResource.data?.copyright
)
)
)
}

is Resource.Error -> {
// Revert the optimistic updates in case of an error
_albumWithInfoState.value = _albumWithInfoState.value.copy(
orderedTracks = _albumWithInfoState.value.orderedTracks.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = isFavorite)
} else {
track
}
}
)

_albumWithInfoState.value = _albumWithInfoState.value.copy(
infoResource = Resource.Success(
AlbumInfoWithGroupedTracks(
albumInfo = _albumWithInfoState.value.infoResource.data?.albumInfo,
groupedTracks = _albumWithInfoState.value.infoResource.data?.groupedTracks?.mapValues { entry ->
entry.value.map { track ->
if (track.trackHash == trackHash) {
track.copy(isFavorite = isFavorite)
} else {
track
}
}
} ?: emptyMap(),
copyright = _albumWithInfoState.value.infoResource.data?.copyright
)
)
)
}
}
}
}
}

fun onAlbumWithInfoUiEvent(event: AlbumWithInfoUiEvent) {
when (event) {
is AlbumWithInfoUiEvent.ResetState -> {
Expand Down Expand Up @@ -163,6 +272,10 @@ class AlbumWithInfoViewModel @Inject constructor(
toggleAlbumFavorite(event.albumHash, event.isFavorite)
}

is AlbumWithInfoUiEvent.OnToggleAlbumTrackFavorite -> {
toggleAlbumTrackFavorite(event.trackHash, event.favorite)
}

else -> {}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ interface ArtistInfoUiEvent {
) : ArtistInfoUiEvent

data class OnRefresh(val artistHash: String) : ArtistInfoUiEvent

data class ToggleArtistTrackFavorite(
val trackHash: String,
val isFavorite: Boolean
) : ArtistInfoUiEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import com.ramcosta.composedestinations.annotation.Destination
import com.android.swingmusic.uicomponent.R as UiComponents

@Composable
private fun Artists(
private fun AllArtists(
pagingArtists: LazyPagingItems<Artist>,
artistsUiState: ArtistsUiState,
sortByPairs: List<Pair<SortBy, String>>,
Expand Down Expand Up @@ -307,12 +307,12 @@ private fun Artists(
}

/**
* This Composable is heavily coupled with ArtistsViewModel. [Artists] Compsable has no ties.
* This Composable is heavily coupled with ArtistsViewModel. [AllArtists] Compsable has no ties.
**/
@OptIn(ExperimentalMaterial3Api::class)
@Destination
@Composable
fun ArtistsScreen(
fun AllArtistsScreen(
navigator: CommonNavigator,
artistsViewModel: ArtistsViewModel = hiltViewModel(),
artistInfoViewModel: ArtistInfoViewModel
Expand Down Expand Up @@ -361,7 +361,7 @@ fun ArtistsScreen(
)
}
) {
Artists(
AllArtists(
pagingArtists = pagingArtists,
artistsUiState = artistsUiState,
sortByPairs = sortByPairs,
Expand Down
Loading

0 comments on commit 6094d11

Please sign in to comment.