Skip to content

Commit

Permalink
refactor: Replace SearchBox
Browse files Browse the repository at this point in the history
  • Loading branch information
jing332 committed Aug 30, 2023
1 parent af4898a commit abcec2a
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.github.jing332.tts_server_android.compose.systts.replace

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.jing332.tts_server_android.data.appDb
Expand All @@ -12,27 +15,37 @@ import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.launch

internal class ManagerViewModel : ViewModel() {
private var allList = listOf<GroupWithReplaceRule>()

private val _list = MutableStateFlow<List<GroupWithReplaceRule>>(emptyList())
val list: MutableStateFlow<List<GroupWithReplaceRule>>
get() = _list

var searchType by mutableStateOf(SearchType.GROUP_NAME)
var searchText by mutableStateOf("")

init {
viewModelScope.launch(Dispatchers.IO) {
appDb.replaceRuleDao.updateAllOrder()
appDb.replaceRuleDao.flowAllGroupWithReplaceRules().conflate().collectLatest {
_list.value = it
allList = it
updateSearchResult()
}
}
}

fun updateSearchResult(text: String, type: SearchType) {
if (list.value.isEmpty() || text.isBlank()) {
_list.value = appDb.replaceRuleDao.allGroupWithReplaceRules()
fun updateSearchResult(
text: String = searchText,
type: SearchType = searchType,
src: List<GroupWithReplaceRule> = allList
) {
if (src.isEmpty() || text.isBlank()) {
_list.value = src
return
}

val resultList = mutableListOf<GroupWithReplaceRule>()
list.value.forEach {
src.forEach {
val subList = mutableListOf<ReplaceRule>()
val groupWithRules = GroupWithReplaceRule(it.group, subList)
resultList.add(groupWithRules)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ package com.github.jing332.tts_server_android.compose.systts.replace

import android.os.Bundle
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.AddCard
Expand All @@ -21,6 +26,7 @@ import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
Expand All @@ -29,9 +35,9 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
Expand Down Expand Up @@ -107,59 +113,64 @@ internal fun ManagerScreen(vm: ManagerViewModel = viewModel(), finish: () -> Uni
}



val models by vm.list.collectAsStateWithLifecycle()
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
title = {
var type by rememberSaveable { mutableStateOf(SearchType.NAME) }
var text by rememberSaveable { mutableStateOf("") }
LaunchedEffect(text, type) {
vm.updateSearchResult(text, type)
LaunchedEffect(vm.searchText, vm.searchType) {
vm.updateSearchResult()
}
Row(
modifier = Modifier
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surfaceContainer)
) {
SearchTextField(
modifier = Modifier.weight(1f),
value = vm.searchText,
onValueChange = { vm.searchText = it },
searchType = vm.searchType,
onSearchTypeChange = { vm.searchType = it }
)
var showAddOptions by remember { mutableStateOf(false) }
IconButton(onClick = { showAddOptions = true }) {
Icon(Icons.Default.Add, stringResource(id = R.string.add_config))
DropdownMenu(
expanded = showAddOptions,
onDismissRequest = { showAddOptions = false }) {
DropdownMenuItem(
text = { Text(stringResource(id = R.string.add_config)) },
onClick = {
showAddOptions = false
navigateToEdit()
},
leadingIcon = {
Icon(Icons.Default.PlaylistAdd, null)
}
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.add_group)) },
onClick = {
showAddOptions = false
showAddGroupDialog = true
},
leadingIcon = {
Icon(Icons.Default.AddCard, null)
}
)
}
}
}
SearchTextField(
value = text,
onValueChange = { text = it },
searchType = type,
onSearchTypeChange = { type = it }
)
},
navigationIcon = {
IconButton(onClick = finish) {
Icon(Icons.Default.ArrowBack, stringResource(id = R.string.nav_back))
}
},
actions = {
var showAddOptions by remember { mutableStateOf(false) }
IconButton(onClick = { showAddOptions = true }) {
Icon(Icons.Default.Add, stringResource(id = R.string.add_config))
DropdownMenu(
expanded = showAddOptions,
onDismissRequest = { showAddOptions = false }) {
DropdownMenuItem(
text = { Text(stringResource(id = R.string.add_config)) },
onClick = {
showAddOptions = false
navigateToEdit()
},
leadingIcon = {
Icon(Icons.Default.PlaylistAdd, null)
}
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.add_group)) },
onClick = {
showAddOptions = false
showAddGroupDialog = true
},
leadingIcon = {
Icon(Icons.Default.AddCard, null)
}
)
}
}


var showOptions by remember { mutableStateOf(false) }
IconButton(onClick = { showOptions = true }) {
Expand Down Expand Up @@ -256,7 +267,7 @@ internal fun ManagerScreen(vm: ManagerViewModel = viewModel(), finish: () -> Uni
onEdit = { showGroupEditDialog = g },
onDelete = { appDb.replaceRuleDao.delete(*groupWithRules.list.toTypedArray()) },
onExport = { showExportSheet = listOf(groupWithRules) },
onSort = { showSortDialog = groupWithRules.list}
onSort = { showSortDialog = groupWithRules.list }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@ package com.github.jing332.tts_server_android.compose.systts.replace

import android.os.Parcelable
import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountTree
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
Expand All @@ -31,79 +38,88 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.github.jing332.tts_server_android.R
import com.github.jing332.tts_server_android.compose.theme.AppTheme
import com.github.jing332.tts_server_android.compose.widgets.DenseTextField
import kotlinx.parcelize.Parcelize

@Parcelize
enum class SearchType(@StringRes val strId: Int) : Parcelable {
GROUP_NAME(R.string.group_name),
internal enum class SearchType(@StringRes val strId: Int) : Parcelable {
NAME(R.string.display_name),
PATTERN(R.string.replace_rule),
REPLACEMENT(R.string.systts_replace_as),
REPLACEMENT(R.string.replacement),
GROUP_NAME(R.string.group_name),
}

@Composable
fun SearchTextField(
internal fun SearchTextField(
modifier: Modifier = Modifier,
value: String,
onValueChange: (String) -> Unit,
searchType: SearchType,
onSearchTypeChange: (SearchType) -> Unit
) {
TextField(
value = value,
onValueChange = onValueChange,
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
),
singleLine = true,
leadingIcon = {
var showTypeOptions by remember { mutableStateOf(false) }
IconButton(onClick = { showTypeOptions = true }) {
Icon(
Icons.Default.AccountTree, stringResource(id = R.string.type)
)
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.titleMedium) {
DenseTextField(
modifier = modifier,
value = value,
onValueChange = onValueChange,
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
),
shape = MaterialTheme.shapes.extraLarge,
placeholder = { Text(stringResource(id = R.string.search_filter)) },
singleLine = true,
leadingIcon = {
var showTypeOptions by remember { mutableStateOf(false) }
IconButton(onClick = { showTypeOptions = true }) {
Icon(
Icons.Default.AccountTree, stringResource(id = R.string.type)
)

DropdownMenu(
expanded = showTypeOptions,
onDismissRequest = { showTypeOptions = false }) {
DropdownMenu(
expanded = showTypeOptions,
onDismissRequest = { showTypeOptions = false }) {

@Composable
fun RadioMenuItem(
isSelected: Boolean,
title: @Composable () -> Unit,
onClick: () -> Unit
) {
DropdownMenuItem(
modifier = Modifier.semantics {
role = Role.RadioButton
},
text = title,
onClick = {
showTypeOptions = false
onClick()
},
leadingIcon = {
RadioButton(
modifier = Modifier.focusable(false),
selected = isSelected,
onClick = null
)
}
)
}
@Composable
fun RadioMenuItem(
isSelected: Boolean,
title: @Composable () -> Unit,
onClick: () -> Unit
) {
DropdownMenuItem(
modifier = Modifier.semantics {
role = Role.RadioButton
},
text = title,
onClick = {
showTypeOptions = false
onClick()
},
leadingIcon = {
RadioButton(
modifier = Modifier.focusable(false),
selected = isSelected,
onClick = null
)
}
)
}

SearchType.values().forEach {
RadioMenuItem(
isSelected = it == searchType,
title = { Text(stringResource(id = it.strId)) },
onClick = { onSearchTypeChange(it) }
)
}
SearchType.values().forEach {
RadioMenuItem(
isSelected = it == searchType,
title = { Text(stringResource(id = it.strId)) },
onClick = { onSearchTypeChange(it) }
)
}

}
}
}
}
)
)
}
}

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal enum class SortType(@StringRes val strId: Int) {
CREATE_TIME(R.string.created_time_id),
NAME(R.string.display_name),
PATTERN(R.string.replace_rule),
REPLACEMENT(R.string.systts_replace_as),
REPLACEMENT(R.string.replacement),

ENABLED(R.string.enabled),
USE_REGEX(R.string.systts_replace_use_regex),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ private fun Screen(
Icon(Icons.Filled.Abc, stringResource(R.string.systts_replace_insert_pinyin))
}
})
OutlinedTextField(label = { Text(stringResource(R.string.systts_replace_as)) },
OutlinedTextField(label = { Text(stringResource(R.string.replacement)) },
value = replacementTextFieldValue,
onValueChange = {
replacementTextFieldValue = it
Expand Down
Loading

0 comments on commit abcec2a

Please sign in to comment.