@@ -50,6 +50,7 @@ import androidx.compose.material.icons.outlined.ExpandLess
5050import androidx.compose.material.icons.outlined.ExpandMore
5151import androidx.compose.material.icons.outlined.KeyboardArrowLeft
5252import androidx.compose.material.icons.outlined.KeyboardArrowRight
53+ import androidx.compose.material.icons.outlined.Search
5354import androidx.compose.material3.AlertDialog
5455import androidx.compose.material3.CircularProgressIndicator
5556import androidx.compose.material3.DropdownMenu
@@ -283,9 +284,18 @@ private fun aliases_tab(
283284 var pending_delete by remember { mutableStateOf<Pair <String , String >? > (null ) }
284285 var pending_domain_address_delete by remember { mutableStateOf<Triple <String , String , String >? > (null ) }
285286 var alias_view by remember { mutableStateOf(0 ) }
287+ var alias_query by remember { mutableStateOf(" " ) }
286288 val colors = AsterMaterial .colors
287289 val show_custom = state.custom_domain_addresses.isNotEmpty()
288290 val alias_view_effective = if (show_custom) alias_view else 0
291+ val query = alias_query.trim()
292+ val filtered_aliases = if (query.isEmpty()) state.aliases else state.aliases.filter {
293+ it.address.contains(query, ignoreCase = true ) ||
294+ it.encrypted_display_name?.contains(query, ignoreCase = true ) == true
295+ }
296+ val filtered_custom_addresses = if (query.isEmpty()) state.custom_domain_addresses else state.custom_domain_addresses.filter {
297+ it.address.contains(query, ignoreCase = true )
298+ }
289299
290300 Row (
291301 modifier = Modifier .fillMaxWidth(),
@@ -295,7 +305,7 @@ private fun aliases_tab(
295305 Text (
296306 text = stringResource(
297307 R .string.aliases_count,
298- if (alias_view_effective == 1 ) state.custom_domain_addresses. size else state.aliases .size,
308+ if (alias_view_effective == 1 ) filtered_custom_addresses. size else filtered_aliases .size,
299309 ),
300310 color = colors.text_tertiary,
301311 fontSize = 13 .sp,
@@ -310,6 +320,35 @@ private fun aliases_tab(
310320 v_gap(AsterSpacing .sm)
311321 }
312322
323+ val search_source_size = if (alias_view_effective == 1 ) state.custom_domain_addresses.size else state.aliases.size
324+ if (search_source_size > 0 ) {
325+ OutlinedTextField (
326+ value = alias_query,
327+ onValueChange = { alias_query = it },
328+ placeholder = { Text (stringResource(R .string.search_aliases), fontSize = 14 .sp) },
329+ leadingIcon = {
330+ Icon (
331+ imageVector = Icons .Outlined .Search ,
332+ contentDescription = null ,
333+ tint = colors.text_muted,
334+ modifier = Modifier .size(20 .dp),
335+ )
336+ },
337+ trailingIcon = if (alias_query.isEmpty()) null else {
338+ {
339+ AsterIconButton (
340+ icon = Icons .Outlined .Cancel ,
341+ content_description = stringResource(R .string.cancel),
342+ onClick = { alias_query = " " },
343+ )
344+ }
345+ },
346+ singleLine = true ,
347+ modifier = Modifier .fillMaxWidth(),
348+ )
349+ v_gap(AsterSpacing .sm)
350+ }
351+
313352 if (alias_view_effective == 0 ) {
314353 if (state.is_loading && state.aliases.isEmpty()) {
315354 Box (
@@ -325,14 +364,18 @@ private fun aliases_tab(
325364 subtitle = state.error ? : stringResource(R .string.no_aliases_subtitle),
326365 )
327366 }
367+ } else if (filtered_aliases.isEmpty()) {
368+ AsterCard (modifier = Modifier .fillMaxWidth()) {
369+ detail_row(title = stringResource(R .string.no_results_found))
370+ }
328371 } else {
329372 val page_size = 100
330- val page_count = (state.aliases .size + page_size - 1 ) / page_size
331- var alias_page by remember(state.aliases .size) { mutableStateOf(0 ) }
373+ val page_count = (filtered_aliases .size + page_size - 1 ) / page_size
374+ var alias_page by remember(query, filtered_aliases .size) { mutableStateOf(0 ) }
332375 val current_page = alias_page.coerceIn(0 , (page_count - 1 ).coerceAtLeast(0 ))
333376 val page_from = current_page * page_size
334- val page_to = minOf(page_from + page_size, state.aliases .size)
335- val page_items = state.aliases .subList(page_from, page_to)
377+ val page_to = minOf(page_from + page_size, filtered_aliases .size)
378+ val page_items = filtered_aliases .subList(page_from, page_to)
336379
337380 AsterCard (modifier = Modifier .fillMaxWidth()) {
338381 page_items.forEachIndexed { idx, alias ->
@@ -408,14 +451,20 @@ private fun aliases_tab(
408451 }
409452 }
410453
411- if (alias_view_effective == 1 ) {
454+ if (alias_view_effective == 1 && filtered_custom_addresses.isEmpty()) {
455+ AsterCard (modifier = Modifier .fillMaxWidth()) {
456+ detail_row(title = stringResource(R .string.no_results_found))
457+ }
458+ }
459+
460+ if (alias_view_effective == 1 && filtered_custom_addresses.isNotEmpty()) {
412461 val cd_page_size = 100
413- val cd_page_count = (state.custom_domain_addresses .size + cd_page_size - 1 ) / cd_page_size
414- var cd_page by remember(state.custom_domain_addresses .size) { mutableStateOf(0 ) }
462+ val cd_page_count = (filtered_custom_addresses .size + cd_page_size - 1 ) / cd_page_size
463+ var cd_page by remember(query, filtered_custom_addresses .size) { mutableStateOf(0 ) }
415464 val cd_current_page = cd_page.coerceIn(0 , (cd_page_count - 1 ).coerceAtLeast(0 ))
416465 val cd_from = cd_current_page * cd_page_size
417- val cd_to = minOf(cd_from + cd_page_size, state.custom_domain_addresses .size)
418- val cd_items = state.custom_domain_addresses .subList(cd_from, cd_to)
466+ val cd_to = minOf(cd_from + cd_page_size, filtered_custom_addresses .size)
467+ val cd_items = filtered_custom_addresses .subList(cd_from, cd_to)
419468 AsterCard (modifier = Modifier .fillMaxWidth()) {
420469 cd_items.forEachIndexed { idx, addr ->
421470 Column (
0 commit comments