mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-02-06 13:53:02 -05:00
feat(debug): add a toggle to AND/OR all filters. (#2265)
This commit is contained in:
@@ -31,6 +31,7 @@ import org.junit.runner.RunWith
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.geeksville.mesh.ui.debug.FilterMode
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class DebugFiltersTest {
|
||||
@@ -67,13 +68,15 @@ class DebugFiltersTest {
|
||||
var customFilterText by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf("") }
|
||||
com.geeksville.mesh.ui.debug.DebugActiveFilters(
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = { filterTexts = it }
|
||||
onFilterTextsChange = { filterTexts = it },
|
||||
filterMode = FilterMode.OR,
|
||||
onFilterModeChange = {}
|
||||
)
|
||||
com.geeksville.mesh.ui.debug.DebugCustomFilterInput(
|
||||
customFilterText = customFilterText,
|
||||
onCustomFilterTextChange = { customFilterText = it },
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = { filterTexts = it }
|
||||
onFilterTextsChange = { filterTexts = it },
|
||||
)
|
||||
}
|
||||
// Add a custom filter
|
||||
@@ -92,7 +95,9 @@ class DebugFiltersTest {
|
||||
var filterTexts by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(listOf("A", "B")) }
|
||||
com.geeksville.mesh.ui.debug.DebugActiveFilters(
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = { filterTexts = it }
|
||||
onFilterTextsChange = { filterTexts = it },
|
||||
filterMode = FilterMode.OR,
|
||||
onFilterModeChange = {}
|
||||
)
|
||||
}
|
||||
// The active filters label and chips should be visible
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.junit.runner.RunWith
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.geeksville.mesh.ui.debug.FilterMode
|
||||
import com.geeksville.mesh.ui.debug.DebugActiveFilters
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class DebugSearchTest {
|
||||
@@ -137,7 +139,9 @@ class DebugSearchTest {
|
||||
var customFilterText by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf("") }
|
||||
com.geeksville.mesh.ui.debug.DebugActiveFilters(
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = { filterTexts = it }
|
||||
onFilterTextsChange = { filterTexts = it },
|
||||
filterMode = FilterMode.OR,
|
||||
onFilterModeChange = {}
|
||||
)
|
||||
com.geeksville.mesh.ui.debug.DebugCustomFilterInput(
|
||||
customFilterText = customFilterText,
|
||||
@@ -162,7 +166,9 @@ class DebugSearchTest {
|
||||
var filterTexts by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(listOf("A", "B")) }
|
||||
com.geeksville.mesh.ui.debug.DebugActiveFilters(
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = { filterTexts = it }
|
||||
onFilterTextsChange = { filterTexts = it },
|
||||
filterMode = FilterMode.OR,
|
||||
onFilterModeChange = {}
|
||||
)
|
||||
}
|
||||
// The active filters label and chips should be visible
|
||||
|
||||
@@ -108,12 +108,24 @@ internal fun DebugScreen(
|
||||
val filterTexts by viewModel.filterTexts.collectAsStateWithLifecycle()
|
||||
val selectedLogId by viewModel.selectedLogId.collectAsStateWithLifecycle()
|
||||
|
||||
val filteredLogs = remember(logs, filterTexts) {
|
||||
var filterMode by remember { mutableStateOf(FilterMode.OR) }
|
||||
|
||||
val filteredLogs = remember(logs, filterTexts, filterMode) {
|
||||
logs.filter { log ->
|
||||
filterTexts.isEmpty() || filterTexts.any { filterText ->
|
||||
log.logMessage.contains(filterText, ignoreCase = true) ||
|
||||
log.messageType.contains(filterText, ignoreCase = true) ||
|
||||
log.formattedReceivedDate.contains(filterText, ignoreCase = true)
|
||||
if (filterTexts.isEmpty()) {
|
||||
true
|
||||
} else { when (filterMode) {
|
||||
FilterMode.OR -> filterTexts.any { filterText ->
|
||||
log.logMessage.contains(filterText, ignoreCase = true) ||
|
||||
log.messageType.contains(filterText, ignoreCase = true) ||
|
||||
log.formattedReceivedDate.contains(filterText, ignoreCase = true)
|
||||
}
|
||||
FilterMode.AND -> filterTexts.all { filterText ->
|
||||
log.logMessage.contains(filterText, ignoreCase = true) ||
|
||||
log.messageType.contains(filterText, ignoreCase = true) ||
|
||||
log.formattedReceivedDate.contains(filterText, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.toImmutableList()
|
||||
}
|
||||
@@ -136,7 +148,6 @@ internal fun DebugScreen(
|
||||
listState.requestScrollToItem(searchState.allMatches[searchState.currentMatchIndex].logIndex)
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
@@ -156,9 +167,10 @@ internal fun DebugScreen(
|
||||
searchState = searchState,
|
||||
filterTexts = filterTexts,
|
||||
presetFilters = viewModel.presetFilters,
|
||||
filterMode = filterMode,
|
||||
onFilterModeChange = { filterMode = it }
|
||||
)
|
||||
}
|
||||
|
||||
items(filteredLogs, key = { it.uuid }) { log ->
|
||||
DebugItem(
|
||||
modifier = Modifier.animateItem(),
|
||||
@@ -708,7 +720,6 @@ fun DebugMenuActions(
|
||||
contentDescription = "Clear All"
|
||||
)
|
||||
}
|
||||
|
||||
if (showDeleteLogsDialog) {
|
||||
SimpleAlertDialog(
|
||||
title = R.string.debug_clear,
|
||||
|
||||
@@ -215,10 +215,13 @@ internal fun DebugFilterBar(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
internal fun DebugActiveFilters(
|
||||
filterTexts: List<String>,
|
||||
onFilterTextsChange: (List<String>) -> Unit,
|
||||
filterMode: FilterMode,
|
||||
onFilterModeChange: (FilterMode) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
@@ -237,6 +240,20 @@ internal fun DebugActiveFilters(
|
||||
text = stringResource(R.string.debug_active_filters),
|
||||
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||
)
|
||||
TextButton(
|
||||
onClick = {
|
||||
onFilterModeChange(
|
||||
if (filterMode == FilterMode.OR) FilterMode.AND else FilterMode.OR
|
||||
)
|
||||
}
|
||||
) {
|
||||
Text(if (filterMode == FilterMode.OR) {
|
||||
stringResource(R.string.match_any)
|
||||
} else {
|
||||
stringResource(R.string.match_all)
|
||||
}
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
onClick = { onFilterTextsChange(emptyList()) }
|
||||
) {
|
||||
@@ -278,3 +295,5 @@ internal fun DebugActiveFilters(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class FilterMode { OR, AND }
|
||||
|
||||
@@ -163,6 +163,8 @@ internal fun DebugSearchState(
|
||||
onPreviousMatch: () -> Unit,
|
||||
onClearSearch: () -> Unit,
|
||||
onFilterTextsChange: (List<String>) -> Unit,
|
||||
filterMode: FilterMode,
|
||||
onFilterModeChange: (FilterMode) -> Unit,
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
var customFilterText by remember { mutableStateOf("") }
|
||||
@@ -198,7 +200,9 @@ internal fun DebugSearchState(
|
||||
}
|
||||
DebugActiveFilters(
|
||||
filterTexts = filterTexts,
|
||||
onFilterTextsChange = onFilterTextsChange
|
||||
onFilterTextsChange = onFilterTextsChange,
|
||||
filterMode = filterMode,
|
||||
onFilterModeChange = onFilterModeChange
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -209,6 +213,8 @@ fun DebugSearchStateviewModelDefaults(
|
||||
searchState: SearchState,
|
||||
filterTexts: List<String>,
|
||||
presetFilters: List<String>,
|
||||
filterMode: FilterMode,
|
||||
onFilterModeChange: (FilterMode) -> Unit,
|
||||
) {
|
||||
val viewModel: DebugViewModel = hiltViewModel()
|
||||
DebugSearchState(
|
||||
@@ -221,6 +227,8 @@ fun DebugSearchStateviewModelDefaults(
|
||||
onPreviousMatch = viewModel.searchManager::goToPreviousMatch,
|
||||
onClearSearch = viewModel.searchManager::clearSearch,
|
||||
onFilterTextsChange = viewModel.filterManager::setFilterTexts,
|
||||
filterMode = filterMode,
|
||||
onFilterModeChange = onFilterModeChange
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -165,9 +165,11 @@
|
||||
<string name="debug_logs_export">Export Logs</string>
|
||||
<string name="debug_last_messages">500 last messages</string>
|
||||
<string name="debug_filters">Filters</string>
|
||||
<string name="debug_active_filters">Active filters (Match any)</string>
|
||||
<string name="debug_active_filters">Active filters</string>
|
||||
<string name="debug_default_search">Search in logs…</string>
|
||||
<string name="debug_clear">Clear Logs</string>
|
||||
<string name="match_any">Match Any | All</string>
|
||||
<string name="match_all">Match All | Any</string>
|
||||
<string name="debug_clear_logs_confirm">This will remove all log packets and database entries from your device - It is a full reset, and is permanent.</string>
|
||||
<string name="clear">Clear</string>
|
||||
<string name="updating_firmware">Updating firmware, wait up to eight minutes…</string>
|
||||
|
||||
Reference in New Issue
Block a user