Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search history: Navigation and Clear All #767

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import au.com.shiftyjelly.pocketcasts.models.to.SearchHistoryEntry
import au.com.shiftyjelly.pocketcasts.search.SearchViewModel.SearchResultType
import au.com.shiftyjelly.pocketcasts.search.adapter.PodcastSearchAdapter
import au.com.shiftyjelly.pocketcasts.search.databinding.FragmentSearchBinding
import au.com.shiftyjelly.pocketcasts.search.searchhistory.SearchHistoryClearAllConfirmationDialog
import au.com.shiftyjelly.pocketcasts.search.searchhistory.SearchHistoryPage
import au.com.shiftyjelly.pocketcasts.search.searchhistory.SearchHistoryViewModel
import au.com.shiftyjelly.pocketcasts.ui.extensions.getThemeColor
Expand All @@ -36,6 +37,7 @@ import au.com.shiftyjelly.pocketcasts.ui.R as UR
private const val ARG_FLOATING = "arg_floating"
private const val ARG_ONLY_SEARCH_REMOTE = "arg_only_search_remote"
private const val ARG_SOURCE = "arg_source"
private const val SEARCH_HISTORY_CLEAR_ALL_CONFIRMATION_DIALOG_TAG = "search_history_clear_all_confirmation_dialog"

@AndroidEntryPoint
class SearchFragment : BaseFragment() {
Expand Down Expand Up @@ -116,6 +118,15 @@ class SearchFragment : BaseFragment() {
viewModel.onFragmentPause(activity?.isChangingConfigurations)
}

private fun navigateFromSearchHistoryEntry(entry: SearchHistoryEntry) {
when (entry) {
is SearchHistoryEntry.Episode -> Unit // TODO
is SearchHistoryEntry.Folder -> listener?.onSearchFolderClick(entry.uuid)
is SearchHistoryEntry.Podcast -> listener?.onSearchPodcastClick(entry.uuid)
is SearchHistoryEntry.SearchTerm -> binding?.searchView?.setQuery(entry.term, true)
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand Down Expand Up @@ -219,7 +230,16 @@ class SearchFragment : BaseFragment() {

binding.searchHistoryPanel.setContent {
AppTheme(theme.activeTheme) {
SearchHistoryPage(searchHistoryViewModel)
SearchHistoryPage(
viewModel = searchHistoryViewModel,
onClick = ::navigateFromSearchHistoryEntry,
onShowClearAllConfirmation = {
SearchHistoryClearAllConfirmationDialog(
context = [email protected](),
onConfirm = { searchHistoryViewModel.clearAll() }
).show(parentFragmentManager, SEARCH_HISTORY_CLEAR_ALL_CONFIRMATION_DIALOG_TAG)
}
)
if (viewModel.isFragmentChangingConfigurations && viewModel.showSearchHistory) {
binding.searchHistoryPanel.show()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package au.com.shiftyjelly.pocketcasts.search.searchhistory

import android.content.Context
import au.com.shiftyjelly.pocketcasts.views.dialog.ConfirmationDialog
import au.com.shiftyjelly.pocketcasts.localization.R as LR
import au.com.shiftyjelly.pocketcasts.views.R as VR

class SearchHistoryClearAllConfirmationDialog(
context: Context,
onConfirm: () -> Unit,
) : ConfirmationDialog() {
init {
setTitle(context.getString(LR.string.clear_all))
setSummary(context.getString(LR.string.search_history_clear_all_confirmation_message))
setIconId(VR.drawable.ic_delete)
setButtonType(ButtonType.Danger(context.getString(LR.string.delete)))
setOnConfirm { onConfirm() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,39 @@ import au.com.shiftyjelly.pocketcasts.compose.AppTheme
import au.com.shiftyjelly.pocketcasts.compose.bars.NavigationButton
import au.com.shiftyjelly.pocketcasts.compose.components.HorizontalDivider
import au.com.shiftyjelly.pocketcasts.compose.components.PodcastImage
import au.com.shiftyjelly.pocketcasts.compose.components.TextH20
import au.com.shiftyjelly.pocketcasts.compose.components.TextH40
import au.com.shiftyjelly.pocketcasts.compose.components.TextP40
import au.com.shiftyjelly.pocketcasts.compose.components.TextP50
import au.com.shiftyjelly.pocketcasts.compose.folder.FolderImageSmall
import au.com.shiftyjelly.pocketcasts.compose.preview.ThemePreviewParameterProvider
import au.com.shiftyjelly.pocketcasts.compose.theme
import au.com.shiftyjelly.pocketcasts.localization.R
import au.com.shiftyjelly.pocketcasts.models.to.SearchHistoryEntry
import au.com.shiftyjelly.pocketcasts.ui.theme.Theme
import java.util.UUID
import au.com.shiftyjelly.pocketcasts.images.R as IR
import au.com.shiftyjelly.pocketcasts.localization.R as LR

private val IconSize = 64.dp
private const val CLEAR_ALL_THRESHOLD = 3
@Composable
internal fun SearchHistoryPage(
viewModel: SearchHistoryViewModel
viewModel: SearchHistoryViewModel,
onClick: (SearchHistoryEntry) -> Unit,
onShowClearAllConfirmation: () -> Unit,
) {
val state by viewModel.state.collectAsState()
SearchHistoryView(
state = state,
onCloseClick = { viewModel.remove(it) }
onCloseClick = { viewModel.remove(it) },
onClearAllClick = {
if (state.entries.size > CLEAR_ALL_THRESHOLD) {
onShowClearAllConfirmation()
} else {
viewModel.clearAll()
}
},
onRowClick = onClick,
)
viewModel.start()
}
Expand All @@ -56,26 +70,56 @@ internal fun SearchHistoryPage(
fun SearchHistoryView(
state: SearchHistoryViewModel.State,
onCloseClick: (SearchHistoryEntry) -> Unit,
onClearAllClick: () -> Unit,
onRowClick: (SearchHistoryEntry) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn {
LazyColumn(
modifier = modifier.background(color = MaterialTheme.theme.colors.primaryUi01)
) {
if (state.entries.isNotEmpty()) {
item {
Row(
modifier = modifier
.fillMaxWidth()
.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
TextH20(
text = stringResource(LR.string.search_history_recent_searches),
color = MaterialTheme.theme.colors.primaryText01,
modifier = modifier.weight(1f)

)
TextH40(
text = stringResource(LR.string.clear_all).uppercase(),
color = MaterialTheme.theme.colors.support03,
modifier = modifier.clickable { onClearAllClick() }
)
}
}
}
state.entries.forEach { entry ->
item {
when (entry) {
is SearchHistoryEntry.Episode -> Unit // TODO

is SearchHistoryEntry.Folder -> SearchHistoryRow(
content = { SearchHistoryFolderView(entry) },
onCloseClick = { onCloseClick(entry) }
onCloseClick = { onCloseClick(entry) },
onRowClick = { onRowClick(entry) },
)

is SearchHistoryEntry.Podcast -> SearchHistoryRow(
content = { SearchHistoryPodcastView(entry) },
onCloseClick = { onCloseClick(entry) }
onCloseClick = { onCloseClick(entry) },
onRowClick = { onRowClick(entry) },
)

is SearchHistoryEntry.SearchTerm -> SearchHistoryRow(
content = { SearchHistoryTermView(entry) },
onCloseClick = { onCloseClick(entry) }
onCloseClick = { onCloseClick(entry) },
onRowClick = { onRowClick(entry) },
)
}
}
Expand All @@ -86,16 +130,15 @@ fun SearchHistoryView(
@Composable
fun SearchHistoryRow(
onCloseClick: () -> Unit,
onRowClick: () -> Unit,
modifier: Modifier = Modifier,
content: @Composable () -> Unit = {},
) {
Column(
modifier = modifier.background(color = MaterialTheme.theme.colors.primaryUi01)
) {
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.clickable { /*TODO*/ }
.clickable { onRowClick() }
.fillMaxWidth()
) {
Box(Modifier.weight(weight = 1f, fill = true)) {
Expand Down Expand Up @@ -155,10 +198,10 @@ fun SearchHistoryFolderView(
modifier = Modifier.padding(bottom = 2.dp)
)
val podcastCount = if (entry.podcastIds.size == 1) {
stringResource(R.string.podcasts_singular)
stringResource(LR.string.podcasts_singular)
} else {
stringResource(
R.string.podcasts_plural,
LR.string.podcasts_plural,
entry.podcastIds.size
)
}
Expand Down Expand Up @@ -232,7 +275,7 @@ fun SearchHistoryTermView(
contentAlignment = Alignment.Center,
) {
Icon(
painter = painterResource(id = au.com.shiftyjelly.pocketcasts.images.R.drawable.ic_search),
painter = painterResource(id = IR.drawable.ic_search),
contentDescription = null,
tint = MaterialTheme.theme.colors.primaryIcon02
)
Expand Down Expand Up @@ -275,7 +318,9 @@ fun SearchHistoryViewPreview(
),
)
),
onCloseClick = {}
onCloseClick = {},
onClearAllClick = {},
onRowClick = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,11 @@ class SearchHistoryViewModel @Inject constructor(
loadSearchHistory()
}
}

fun clearAll() {
viewModelScope.launch {
searchHistoryManager.clearAll()
loadSearchHistory()
}
}
}
2 changes: 2 additions & 0 deletions modules/services/localization/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@
<string name="search_no_podcasts_found_summary">Try more general or different keywords.</string>
<string name="search_podcasts">Search podcasts</string>
<string name="search_hint">Search by podcast name</string>
<string name="search_history_clear_all_confirmation_message">Are you sure you want to clear all your search history?</string>
<string name="search_history_recent_searches">Recent searches</string>

<string name="time_short_hours">%dh</string>
<string name="time_short_hours_minutes">%1$dh %2$dm</string>
Expand Down