Skip to content

Commit

Permalink
feat: support several sort options for lookup history (#385)
Browse files Browse the repository at this point in the history
- persist
  • Loading branch information
David Ly committed Aug 25, 2023
1 parent 5ce7b2f commit 07a375c
Show file tree
Hide file tree
Showing 16 changed files with 271 additions and 52 deletions.
13 changes: 7 additions & 6 deletions app/src/main/java/ly/david/mbjc/ui/TopLevelScaffold.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ internal fun TopLevelScaffold(
) {
val snackbarHostState = remember { SnackbarHostState() }

val sortReleaseGroupListItems by viewModel.appPreferences.sortReleaseGroupListItems.collectAsState(initial = false)
val sortReleaseGroupListItems
by viewModel.appPreferences.sortReleaseGroupListItems.collectAsState(initial = false)
val showMoreInfoInReleaseListItem
by viewModel.appPreferences.showMoreInfoInReleaseListItem.collectAsState(initial = true)

val scope = rememberCoroutineScope()
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
var showBottomSheet by rememberSaveable { mutableStateOf(false) }
val bottomSheetState = rememberModalBottomSheetState()
var showCreateCollectionDialog by rememberSaveable { mutableStateOf(false) }
val collections: LazyPagingItems<CollectionListItemModel> = rememberFlowWithLifecycleStarted(viewModel.collections)
Expand Down Expand Up @@ -120,12 +121,12 @@ internal fun TopLevelScaffold(
}
}

if (openBottomSheet) {
if (showBottomSheet) {
CollectionBottomSheet(
bottomSheetState = bottomSheetState,
scope = scope,
collections = collections,
onDismiss = { openBottomSheet = false },
onDismiss = { showBottomSheet = false },
onCreateCollectionClick = { showCreateCollectionDialog = true },
onAddToCollection = { collectionId ->
scope.launch {
Expand Down Expand Up @@ -219,7 +220,7 @@ internal fun TopLevelScaffold(
onAddToCollectionMenuClick = { entity, id ->
viewModel.setEntity(entity)
viewModel.setEntityId(id)
openBottomSheet = true
showBottomSheet = true
},
onDeleteFromCollection = { collectionId, entityId, name ->
scope.launch {
Expand All @@ -234,7 +235,7 @@ internal fun TopLevelScaffold(
showMoreInfoInReleaseListItem = showMoreInfoInReleaseListItem,
onShowMoreInfoInReleaseListItemChange = viewModel.appPreferences::setShowMoreInfoInReleaseListItem,
sortReleaseGroupListItems = sortReleaseGroupListItems,
onSortReleaseGroupListItemsChange = viewModel.appPreferences::setSortReleaseGroupListItems
onSortReleaseGroupListItemsChange = viewModel.appPreferences::setSortReleaseGroupListItems,
)
}
}
21 changes: 11 additions & 10 deletions app/src/main/java/ly/david/mbjc/ui/navigation/NavigationGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import ly.david.mbjc.ui.work.WorkScaffold
import ly.david.ui.collections.CollectionListScaffold
import ly.david.ui.collections.CollectionScaffold
import ly.david.ui.common.R
import ly.david.ui.history.DeleteHistoryDelegate
import ly.david.ui.history.HistoryScaffold
import ly.david.ui.nowplaying.NowPlayingHistoryScaffold
import ly.david.ui.settings.SettingsScaffold
Expand Down Expand Up @@ -69,17 +70,17 @@ internal fun NavHostController.goTo(destination: Destination) {
@Composable
internal fun NavigationGraph(
navController: NavHostController,
deleteHistoryDelegate: ly.david.ui.history.DeleteHistoryDelegate,
deleteHistoryDelegate: DeleteHistoryDelegate,
onLoginClick: () -> Unit,
onLogoutClick: () -> Unit,
onCreateCollectionClick: () -> Unit,
onAddToCollectionMenuClick: (entity: MusicBrainzEntity, id: String) -> Unit,
onDeleteFromCollection: (collectionId: String, entityId: String, name: String) -> Unit,
showMoreInfoInReleaseListItem: Boolean,
onShowMoreInfoInReleaseListItemChange: (Boolean) -> Unit,
sortReleaseGroupListItems: Boolean,
onSortReleaseGroupListItemsChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
onLoginClick: () -> Unit = {},
onLogoutClick: () -> Unit = {},
onCreateCollectionClick: () -> Unit = {},
onAddToCollectionMenuClick: (entity: MusicBrainzEntity, id: String) -> Unit = { _, _ -> },
onDeleteFromCollection: (collectionId: String, entityId: String, name: String) -> Unit = { _, _, _ -> },
showMoreInfoInReleaseListItem: Boolean = true,
onShowMoreInfoInReleaseListItemChange: (Boolean) -> Unit = {},
sortReleaseGroupListItems: Boolean = false,
onSortReleaseGroupListItemsChange: (Boolean) -> Unit = {},
) {
val deeplinkSchema = stringResource(id = R.string.deeplink_schema)
val uriPrefix = "$deeplinkSchema://app/"
Expand Down
1 change: 1 addition & 0 deletions config/detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ complexity:
ignoreAnnotated:
- "Composable"
- "HiltViewModel"
- "Query"
LongMethod:
ignoreAnnotated:
- "Composable"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ly.david.data.domain.history

enum class HistorySortOption {
ALPHABETICALLY,
ALPHABETICALLY_REVERSE,
RECENTLY_VISITED,
LEAST_RECENTLY_VISITED,
MOST_VISITED,
LEAST_VISITED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ import ly.david.data.room.history.LookupHistoryDao
class LookupHistoryRepository @Inject constructor(
private val lookupHistoryDao: LookupHistoryDao,
) {
fun getAllLookupHistory(query: String) =
lookupHistoryDao.getAllLookupHistory("%$query%")
fun getAllLookupHistory(query: String, sortOption: HistorySortOption) =
lookupHistoryDao.getAllLookupHistory(
query = "%$query%",
alphabetically = sortOption == HistorySortOption.ALPHABETICALLY,
alphabeticallyReverse = sortOption == HistorySortOption.ALPHABETICALLY_REVERSE,
recentlyVisited = sortOption == HistorySortOption.RECENTLY_VISITED,
leastRecentlyVisited = sortOption == HistorySortOption.LEAST_RECENTLY_VISITED,
mostVisited = sortOption == HistorySortOption.MOST_VISITED,
leastVisited = sortOption == HistorySortOption.LEAST_VISITED,
)

suspend fun markHistoryAsDeleted(mbid: String) {
lookupHistoryDao.markAsDeleted(mbid, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,31 @@ import ly.david.data.room.BaseDao
@Dao
abstract class LookupHistoryDao : BaseDao<LookupHistoryRoomModel>() {

// @Transaction
// @Query(
// """
// SELECT * FROM lookup_history
// WHERE NOT deleted
// ORDER BY last_accessed DESC
// """
// )
// abstract fun getAllLookupHistory(): PagingSource<Int, LookupHistoryRoomModel>

// TODO: can't search "release group", need to use "release_group" or "release-group"
// rather than having the user type "artist" to filter artist, use pills or something
// reserving text search for title only
@Transaction
@Query(
"""
SELECT *
FROM lookup_history
WHERE NOT deleted AND
(title LIKE :query OR resource LIKE :query OR search_hint LIKE :query)
ORDER BY last_accessed DESC
(title LIKE :query OR resource LIKE :query OR search_hint LIKE :query)
ORDER BY
CASE WHEN :alphabetically THEN title END ASC,
CASE WHEN :alphabeticallyReverse THEN title END DESC,
CASE WHEN :recentlyVisited THEN last_accessed END DESC,
CASE WHEN :leastRecentlyVisited THEN last_accessed END ASC,
CASE WHEN :mostVisited THEN number_of_visits END DESC,
CASE WHEN :leastVisited THEN number_of_visits END ASC
"""
)
abstract fun getAllLookupHistory(query: String): PagingSource<Int, LookupHistoryForListItem>
abstract fun getAllLookupHistory(
query: String,
alphabetically: Boolean,
alphabeticallyReverse: Boolean,
recentlyVisited: Boolean,
leastRecentlyVisited: Boolean,
mostVisited: Boolean,
leastVisited: Boolean,
): PagingSource<Int, LookupHistoryForListItem>

@Query(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ fun CollectionBottomSheet(
bottomSheetState: SheetState,
scope: CoroutineScope,
collections: LazyPagingItems<CollectionListItemModel>,
onDismiss: () -> Unit,
onCreateCollectionClick: () -> Unit,
onAddToCollection: suspend (collectionId: String) -> Unit,
onDismiss: () -> Unit = {},
onCreateCollectionClick: () -> Unit = {},
onAddToCollection: suspend (collectionId: String) -> Unit = {},
) {
ModalBottomSheet(
onDismissRequest = onDismiss,
Expand Down
7 changes: 7 additions & 0 deletions ui/common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,11 @@
<string name="spotify_tutorial">Enable Device Broadcast Status in the Spotify app\'s settings in order for MusicSearch to detect the playing song</string>
<string name="search_x">Search %1$s</string>
<string name="search_x_by_x">Search %1$s by %2$s</string>

<string name="alphabetically">Alphabetically</string>
<string name="alphabetically_reverse">Reverse alphabetically</string>
<string name="recently_visited">Recently visited</string>
<string name="least_recently_visited">Least recently visited</string>
<string name="most_visited">Most visited</string>
<string name="least_visited">Least visited</string>
</resources>
1 change: 1 addition & 0 deletions ui/history/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
implementation(projects.ui.common)
implementation(projects.ui.core)
implementation(projects.ui.image)
implementation(projects.ui.settings)
testImplementation(projects.ui.test.image)
testImplementation(projects.ui.test.screenshot)

Expand Down
22 changes: 21 additions & 1 deletion ui/history/src/main/java/ly/david/ui/history/HistoryScaffold.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberDismissState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -42,8 +44,10 @@ fun HistoryScaffold(
var filterText by rememberSaveable { mutableStateOf("") }
val lazyPagingItems = rememberFlowWithLifecycleStarted(viewModel.lookUpHistory)
.collectAsLazyPagingItems()

val sortOption by viewModel.sortOption.collectAsState()
var showDeleteConfirmationDialog by rememberSaveable { mutableStateOf(false) }
var showBottomSheet by rememberSaveable { mutableStateOf(false) }
val bottomSheetState = rememberModalBottomSheetState()

if (showDeleteConfirmationDialog) {
SimpleAlertDialog(
Expand All @@ -55,6 +59,15 @@ fun HistoryScaffold(
)
}

if (showBottomSheet) {
HistorySortBottomSheet(
sortOption = sortOption,
onSortOptionClick = viewModel::updateSortOption,
bottomSheetState = bottomSheetState,
onDismiss = { showBottomSheet = false }
)
}

Scaffold(
modifier = modifier,
topBar = {
Expand All @@ -75,6 +88,13 @@ fun HistoryScaffold(
closeMenu()
}
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.sort)) },
onClick = {
showBottomSheet = true
closeMenu()
}
)
},
)
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package ly.david.ui.history

import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.Surface
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import ly.david.data.domain.history.HistorySortOption
import ly.david.ui.common.R
import ly.david.ui.common.component.ClickableItem
import ly.david.ui.core.preview.DefaultPreviews
import ly.david.ui.core.theme.PreviewTheme

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun HistorySortBottomSheet(
sortOption: HistorySortOption,
onSortOptionClick: (HistorySortOption) -> Unit = {},
bottomSheetState: SheetState = rememberModalBottomSheetState(),
onDismiss: () -> Unit = {},
) {
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = bottomSheetState,
) {
HistorySortBottomSheetContent(
sortOption = sortOption,
onSortOptionClick = onSortOptionClick
)
}
}

@Composable
private fun HistorySortBottomSheetContent(
sortOption: HistorySortOption = HistorySortOption.RECENTLY_VISITED,
onSortOptionClick: (HistorySortOption) -> Unit = {},
) {
Column {
HistorySortOption.entries.forEach {
ClickableItem(
title = stringResource(id = it.labelRes),
endIcon = if (sortOption == it) Icons.Default.Check else null,
onClick = {
onSortOptionClick(it)
}
)
}
}
}

internal val HistorySortOption.labelRes: Int
get() {
return when (this) {
HistorySortOption.ALPHABETICALLY -> R.string.alphabetically
HistorySortOption.ALPHABETICALLY_REVERSE -> R.string.alphabetically_reverse
HistorySortOption.LEAST_RECENTLY_VISITED -> R.string.least_recently_visited
HistorySortOption.RECENTLY_VISITED -> R.string.recently_visited
HistorySortOption.MOST_VISITED -> R.string.most_visited
HistorySortOption.LEAST_VISITED -> R.string.least_visited
}
}

@DefaultPreviews
@Composable
internal fun PreviewHistorySortBottomSheetContent() {
PreviewTheme {
Surface {
HistorySortBottomSheetContent()
}
}
}
Loading

0 comments on commit 07a375c

Please sign in to comment.