feat: 长按删除单条搜索历史

This commit is contained in:
HuanCheng65 2023-09-23 16:14:06 +08:00
parent 4e6d9aab70
commit 5272f0f328
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
2 changed files with 42 additions and 2 deletions

View File

@ -6,6 +6,7 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.Arrangement
@ -271,6 +272,7 @@ fun SearchPage(
},
expanded = expanded,
onToggleExpand = { expanded = !expanded },
onDelete = { viewModel.send(SearchUiIntent.DeleteSearchHistory(it.id)) },
onClear = { viewModel.send(SearchUiIntent.ClearSearchHistory) }
)
}
@ -389,13 +391,14 @@ private fun ColumnScope.SearchTabRow(
}
}
@OptIn(ExperimentalLayoutApi::class)
@OptIn(ExperimentalLayoutApi::class, ExperimentalFoundationApi::class)
@Composable
private fun SearchHistoryList(
searchHistories: ImmutableList<SearchHistory>,
onSearchHistoryClick: (SearchHistory) -> Unit,
expanded: Boolean = false,
onToggleExpand: () -> Unit = {},
onDelete: (SearchHistory) -> Unit = {},
onClear: () -> Unit = {},
) {
val hasMore = remember(searchHistories) {
@ -438,7 +441,10 @@ private fun SearchHistoryList(
modifier = Modifier
.padding(bottom = 8.dp)
.clip(RoundedCornerShape(100))
.clickable { onSearchHistoryClick(searchHistory) }
.combinedClickable(
onClick = { onSearchHistoryClick(searchHistory) },
onLongClick = { onDelete(searchHistory) }
)
.background(ExtendedTheme.colors.chip)
.padding(horizontal = 16.dp, vertical = 8.dp)
) {

View File

@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import org.litepal.LitePal
import org.litepal.extension.delete
import org.litepal.extension.deleteAll
import org.litepal.extension.find
@ -47,6 +48,10 @@ class SearchViewModel :
App.INSTANCE.getString(R.string.toast_clear_failure, partialChange.errorMessage)
)
is SearchPartialChange.DeleteSearchHistory.Failure -> CommonUiEvent.Toast(
App.INSTANCE.getString(R.string.toast_delete_failure, partialChange.errorMessage)
)
is SearchPartialChange.SubmitKeyword -> SearchUiEvent.KeywordChanged(partialChange.keyword)
else -> null
@ -61,6 +66,8 @@ class SearchViewModel :
.flatMapConcat { produceInitPartialChange() },
intentFlow.filterIsInstance<SearchUiIntent.ClearSearchHistory>()
.flatMapConcat { produceClearHistoryPartialChange() },
intentFlow.filterIsInstance<SearchUiIntent.DeleteSearchHistory>()
.flatMapConcat { it.producePartialChange() },
intentFlow.filterIsInstance<SearchUiIntent.SubmitKeyword>()
.flatMapConcat { it.producePartialChange() },
)
@ -83,6 +90,14 @@ class SearchViewModel :
emit(SearchPartialChange.ClearSearchHistory.Failure(it.getErrorMessage()))
}.flowOn(Dispatchers.IO)
private fun SearchUiIntent.DeleteSearchHistory.producePartialChange() =
flow<SearchPartialChange.DeleteSearchHistory> {
LitePal.delete<SearchHistory>(id)
emit(SearchPartialChange.DeleteSearchHistory.Success(id))
}.catch {
emit(SearchPartialChange.DeleteSearchHistory.Failure(it.getErrorMessage()))
}.flowOn(Dispatchers.IO)
private fun SearchUiIntent.SubmitKeyword.producePartialChange() =
flowOf(SearchPartialChange.SubmitKeyword(keyword.trim()))
.onEach {
@ -102,6 +117,8 @@ sealed interface SearchUiIntent : UiIntent {
data object ClearSearchHistory : SearchUiIntent
data class DeleteSearchHistory(val id: Long) : SearchUiIntent
data class SubmitKeyword(val keyword: String) : SearchUiIntent
}
@ -130,6 +147,23 @@ sealed interface SearchPartialChange : PartialChange<SearchUiState> {
) : ClearSearchHistory()
}
sealed class DeleteSearchHistory : SearchPartialChange {
override fun reduce(oldState: SearchUiState): SearchUiState = when (this) {
is Success -> oldState.copy(
searchHistories = oldState.searchHistories.filterNot { it.id == id }
.toImmutableList()
)
is Failure -> oldState
}
data class Success(val id: Long) : DeleteSearchHistory()
data class Failure(
val errorMessage: String,
) : DeleteSearchHistory()
}
data class SubmitKeyword(val keyword: String) : SearchPartialChange {
override fun reduce(oldState: SearchUiState): SearchUiState {
if (keyword.isEmpty()) {