pref: 交换清除全部和展开更多历史按钮
This commit is contained in:
parent
5f7203228e
commit
4e6d9aab70
|
|
@ -6,28 +6,23 @@ import androidx.compose.ui.text.font.FontFamily
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
internal val DefaultTextStyle = TextStyle.Default.copy()
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
body1 = TextStyle(
|
||||
body1 = DefaultTextStyle.copy(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
),
|
||||
subtitle1 = TextStyle(
|
||||
subtitle1 = DefaultTextStyle.copy(
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 16.sp,
|
||||
letterSpacing = 0.15.sp
|
||||
),
|
||||
/* Other default text styles to override
|
||||
button = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.W500,
|
||||
fontSize = 14.sp
|
||||
),
|
||||
caption = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 12.sp
|
||||
button = DefaultTextStyle.copy(
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
letterSpacing = 0.15.sp
|
||||
)
|
||||
*/
|
||||
)
|
||||
|
|
@ -38,8 +38,9 @@ import androidx.compose.material.Text
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
||||
import androidx.compose.material.icons.rounded.CleaningServices
|
||||
import androidx.compose.material.icons.rounded.Clear
|
||||
import androidx.compose.material.icons.rounded.ExpandLess
|
||||
import androidx.compose.material.icons.rounded.ExpandMore
|
||||
import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -79,6 +80,7 @@ import com.huanchengfly.tieba.post.models.database.SearchHistory
|
|||
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
|
||||
import com.huanchengfly.tieba.post.ui.common.theme.compose.TiebaLiteTheme
|
||||
import com.huanchengfly.tieba.post.ui.page.ProvideNavigator
|
||||
import com.huanchengfly.tieba.post.ui.page.destinations.SearchPageDestination
|
||||
import com.huanchengfly.tieba.post.ui.page.search.forum.SearchForumPage
|
||||
import com.huanchengfly.tieba.post.ui.page.search.thread.SearchThreadPage
|
||||
import com.huanchengfly.tieba.post.ui.page.search.thread.SearchThreadSortType
|
||||
|
|
@ -88,6 +90,7 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.BaseTextField
|
|||
import com.huanchengfly.tieba.post.ui.widgets.compose.Button
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.ClickMenu
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoadHorizontalPager
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.MyBackHandler
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.PagerTabIndicator
|
||||
import com.huanchengfly.tieba.post.ui.widgets.compose.TopAppBarContainer
|
||||
|
|
@ -132,10 +135,25 @@ fun SearchPage(
|
|||
prop1 = SearchUiState::keyword,
|
||||
initial = ""
|
||||
)
|
||||
val isKeywordEmpty by remember {
|
||||
derivedStateOf { keyword.isEmpty() }
|
||||
}
|
||||
|
||||
val isKeywordEmpty by viewModel.uiState.collectPartialAsState(
|
||||
prop1 = SearchUiState::isKeywordEmpty,
|
||||
initial = true
|
||||
)
|
||||
var inputKeyword by remember { mutableStateOf("") }
|
||||
LaunchedEffect(keyword) {
|
||||
if (keyword.isNotEmpty() && keyword != inputKeyword) {
|
||||
inputKeyword = keyword
|
||||
}
|
||||
}
|
||||
|
||||
MyBackHandler(
|
||||
enabled = !isKeywordEmpty,
|
||||
currentScreen = SearchPageDestination
|
||||
) {
|
||||
viewModel.send(SearchUiIntent.SubmitKeyword(""))
|
||||
}
|
||||
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
val initialSortType = remember { SearchThreadSortType.SORT_TYPE_NEWEST }
|
||||
|
|
@ -145,7 +163,7 @@ fun SearchPage(
|
|||
}
|
||||
viewModel.onEvent<SearchUiEvent.KeywordChanged> {
|
||||
inputKeyword = it.keyword
|
||||
emitGlobalEventSuspend(it)
|
||||
if (it.keyword.isNotBlank()) emitGlobalEventSuspend(it)
|
||||
}
|
||||
|
||||
val pages by remember {
|
||||
|
|
@ -213,7 +231,13 @@ fun SearchPage(
|
|||
onKeywordSubmit = {
|
||||
viewModel.send(SearchUiIntent.SubmitKeyword(it))
|
||||
},
|
||||
onBack = { navigator.navigateUp() }
|
||||
onBack = {
|
||||
if (isKeywordEmpty) {
|
||||
navigator.navigateUp()
|
||||
} else {
|
||||
viewModel.send(SearchUiIntent.SubmitKeyword(""))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
@ -224,17 +248,21 @@ fun SearchPage(
|
|||
}
|
||||
}
|
||||
) {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (!isKeywordEmpty) {
|
||||
ProvideNavigator(navigator = navigator) {
|
||||
LazyLoadHorizontalPager(
|
||||
state = pagerState,
|
||||
key = { pages[it].id }
|
||||
key = { pages[it].id },
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
pages[it].content()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Column {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
SearchHistoryList(
|
||||
searchHistories = searchHistories,
|
||||
onSearchHistoryClick = {
|
||||
|
|
@ -248,6 +276,7 @@ fun SearchPage(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
|
|
@ -390,12 +419,10 @@ private fun SearchHistoryList(
|
|||
.weight(1f),
|
||||
style = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
if (hasMore) {
|
||||
if (hasItem) {
|
||||
Text(
|
||||
text = if (!expanded) stringResource(id = R.string.button_expand) else stringResource(
|
||||
id = R.string.button_collapse
|
||||
),
|
||||
modifier = Modifier.clickable(onClick = onToggleExpand),
|
||||
text = stringResource(id = R.string.button_clear_all),
|
||||
modifier = Modifier.clickable(onClick = onClear),
|
||||
style = MaterialTheme.typography.button
|
||||
)
|
||||
}
|
||||
|
|
@ -421,9 +448,9 @@ private fun SearchHistoryList(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (hasItem) {
|
||||
if (hasMore) {
|
||||
Button(
|
||||
onClick = onClear,
|
||||
onClick = onToggleExpand,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
backgroundColor = Color.Transparent,
|
||||
|
|
@ -435,18 +462,21 @@ private fun SearchHistoryList(
|
|||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.CleaningServices,
|
||||
imageVector = if (expanded) Icons.Rounded.ExpandLess else Icons.Rounded.ExpandMore,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.title_clear_search_history),
|
||||
text = stringResource(
|
||||
id = if (expanded) R.string.button_expand_less_history else R.string.button_expand_more_history
|
||||
),
|
||||
style = MaterialTheme.typography.button,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (!hasItem) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -84,10 +84,14 @@ class SearchViewModel :
|
|||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
private fun SearchUiIntent.SubmitKeyword.producePartialChange() =
|
||||
flowOf(SearchPartialChange.SubmitKeyword(keyword))
|
||||
flowOf(SearchPartialChange.SubmitKeyword(keyword.trim()))
|
||||
.onEach {
|
||||
runCatching {
|
||||
SearchHistory(keyword).saveOrUpdate("content = ?", keyword)
|
||||
val trimKeyword = keyword.trim()
|
||||
if (trimKeyword.isNotBlank()) SearchHistory(trimKeyword).saveOrUpdate(
|
||||
"content = ?",
|
||||
trimKeyword
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +123,7 @@ sealed interface SearchPartialChange : PartialChange<SearchUiState> {
|
|||
is Failure -> oldState
|
||||
}
|
||||
|
||||
object Success : ClearSearchHistory()
|
||||
data object Success : ClearSearchHistory()
|
||||
|
||||
data class Failure(
|
||||
val errorMessage: String,
|
||||
|
|
@ -129,13 +133,14 @@ sealed interface SearchPartialChange : PartialChange<SearchUiState> {
|
|||
data class SubmitKeyword(val keyword: String) : SearchPartialChange {
|
||||
override fun reduce(oldState: SearchUiState): SearchUiState {
|
||||
if (keyword.isEmpty()) {
|
||||
return oldState.copy(keyword = keyword)
|
||||
return oldState.copy(isKeywordEmpty = true)
|
||||
}
|
||||
val newSearchHistories = (oldState.searchHistories
|
||||
.filterNot { it.content == keyword } + SearchHistory(content = keyword))
|
||||
.sortedByDescending { it.timestamp }
|
||||
return oldState.copy(
|
||||
keyword = keyword,
|
||||
isKeywordEmpty = false,
|
||||
searchHistories = newSearchHistories.toImmutableList()
|
||||
)
|
||||
}
|
||||
|
|
@ -144,6 +149,7 @@ sealed interface SearchPartialChange : PartialChange<SearchUiState> {
|
|||
|
||||
data class SearchUiState(
|
||||
val keyword: String = "",
|
||||
val isKeywordEmpty: Boolean = true,
|
||||
val searchHistories: ImmutableList<SearchHistory> = persistentListOf(),
|
||||
) : UiState
|
||||
|
||||
|
|
|
|||
|
|
@ -716,4 +716,7 @@
|
|||
<string name="toast_clear_failure">清除失败 %s</string>
|
||||
<string name="title_recommend">推荐</string>
|
||||
<string name="title_fuzzy_match_user">相关用户</string>
|
||||
<string name="button_expand_more_history">展开历史</string>
|
||||
<string name="button_expand_less_history">收起历史</string>
|
||||
<string name="button_clear_all">清除全部</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue