Skip to content

feat(Sensors): Add search filter to sensor setting allow list dialog#6567

Open
danielgomezrico wants to merge 15 commits intohome-assistant:mainfrom
danielgomezrico:feature/search-sensor-allow-list
Open

feat(Sensors): Add search filter to sensor setting allow list dialog#6567
danielgomezrico wants to merge 15 commits intohome-assistant:mainfrom
danielgomezrico:feature/search-sensor-allow-list

Conversation

@danielgomezrico
Copy link
Copy Markdown

@danielgomezrico danielgomezrico commented Mar 12, 2026

Summary

  • Add a search TextField to SensorDetailSettingDialog so users can quickly filter long app lists (e.g., Last Notification Allow List)
  • Filtering is local to the composable — no ViewModel changes, selections persist across searches
  • Works for all list-type sensor settings (LIST_APPS, LIST_BLUETOOTH, LIST_ZONES, etc.)

Checklist

  • New or updated tests have been added to cover the changes following the testing guidelines.
  • The code follows the project's code style and best_practices.
  • The changes have been thoroughly tested, and edge cases have been considered.
  • Changes are backward compatible whenever feasible. Any breaking changes are documented in the changelog for users and/or in the code for developers depending on the relevance.

Screenshots

Before

No search bar, hard to read and search:
image

After

2026-05-03 21 32 08

Copilot AI review requested due to automatic review settings March 12, 2026 19:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an in-dialog search field to SensorDetailSettingDialog so users can locally filter long list-type sensor setting entries (apps, Bluetooth devices, zones, etc.) without changing ViewModel/state handling.

Changes:

  • Added a search TextField with clear button to filter list-type setting dialog entries.
  • Introduced filterSettingEntries(...) helper to apply case-insensitive filtering.
  • Added unit tests covering filtering behavior and edge cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorDetailView.kt Adds search UI + filtering logic for list dialogs; introduces filterSettingEntries helper
app/src/test/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorDetailSettingDialogFilterTest.kt Adds JUnit tests validating filtering behavior

You can also share your feedback on Copilot code review. Take the survey.

@jpelgrom
Copy link
Copy Markdown
Member

Can you provide screenshots for the change?

Did you consider only showing search when there is a long list? Showing search when there are only 3 items is a bit weird.

This dialog isn't really suited for a large list anyway, I wonder if it should be changed to a different picker like the bottom sheet/dialog we have implemented for entities recently.

Both comments generated by Copilot are valid, please address them (try doing it yourself without AI to understand the change you're making).

Add a search TextField to `SensorDetailSettingDialog` so users can
quickly find apps in long lists (e.g., Last Notification Allow List).
Filtering is local to the composable; selections persist across searches.
@danielgomezrico danielgomezrico force-pushed the feature/search-sensor-allow-list branch from 41b5f66 to 2baef1b Compare March 13, 2026 22:51
@danielgomezrico danielgomezrico changed the title feat(sensors): add search filter to sensor setting allow list dialog feat(Sensors): Add search filter to sensor setting allow list dialog Mar 13, 2026
@danielgomezrico
Copy link
Copy Markdown
Author

danielgomezrico commented Mar 13, 2026

Can you provide screenshots for the change?

Sure! updated.

Did you consider only showing search when there is a long list? Showing search when there are only 3 items is a bit weird.

Oh that Idea is cool I will adapt it for that case

This dialog isn't really suited for a large list anyway, I wonder if it should be changed to a different picker like the
bottom sheet/dialog we have implemented for entities recently.

It makes total sense, but in the mean while it would help, the list of apps could be pretty long and having to search in that dialog is pretty hard.

… lists

Show search only when entries > 10. Extract SettingSearchField composable
for readability.
@TimoPtr
Copy link
Copy Markdown
Member

TimoPtr commented Mar 16, 2026

I'm aligned with @jpelgrom I would prefer to see a bottom sheet here. You already have the needed components to do so. You can check the Entity picker like @jpelgrom suggested.

You might also want to merge main in your branch since we've fixed some issue with ktlint recently.

@TimoPtr TimoPtr marked this pull request as draft March 16, 2026 09:15
@danielgomezrico
Copy link
Copy Markdown
Author

I'm aligned with @jpelgrom I would prefer to see a bottom sheet here. You already have the needed components to do so. You can check the Entity picker like @jpelgrom suggested.

You might also want to merge main in your branch since we've fixed some issue with ktlint recently.

Got it, Ill check if I can make it for this case.

One thing I've noticed is that these types of dialogs are used in other places; should the bottom sheet be limited to this case?

@jpelgrom
Copy link
Copy Markdown
Member

One thing I've noticed is that these types of dialogs are used in other places; should the bottom sheet be limited to this case?

Just this specific dialog, with a long list of apps that you may want to search. Replacing all other dialogs makes this PR too big and also doesn't make sense as a pattern when there are only 2-3 options.

@danielgomezrico
Copy link
Copy Markdown
Author

@jpelgrom @TimoPtr I made the update to show it in a bottom sheet, WDYT?

@TimoPtr
Copy link
Copy Markdown
Member

TimoPtr commented Mar 25, 2026

@danielgomezrico could you address the lint issue and when you are ready put the PR in ready for review.

@danielgomezrico danielgomezrico marked this pull request as ready for review March 29, 2026 14:02
@TimoPtr TimoPtr marked this pull request as draft March 30, 2026 08:01
Ktlint function-signature rule requires single-line when signature fits within max_line_length (120 chars).
@danielgomezrico danielgomezrico marked this pull request as ready for review April 2, 2026 23:51
@danielgomezrico
Copy link
Copy Markdown
Author

@TimoPtr can you help me aproving the CI 🙏🏻 ?

Copy link
Copy Markdown
Member

@TimoPtr TimoPtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UX needs to be adjust the rest of the comments are mostly to adjust with the project guidelines.

@home-assistant
Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@home-assistant home-assistant Bot marked this pull request as draft April 13, 2026 13:44
- Extract HASearchField to :common, replacing duplicated search fields in
  EntityPicker and SensorDetailSettingSheet
- Replace rememberStandardBottomSheetState (intended for BottomSheetScaffold)
  with rememberModalBottomSheetState(skipPartiallyExpanded = true) so the sheet
  no longer blinks before fully expanding; drop the LaunchedEffect.expand()
  workaround
- Extract parseSettingLabel helper used by both BottomSheetSettingRow and
  SensorDetailSettingRow
- Rename consumeFlingNestedScrollConnection to nestedScrollFlingGuard, demote
  rememberFilteredSettingEntries to private, and simplify the row toggle logic
…ate immutability

- joinSelectedValues: pin behavior on empty/single/multi values, bracket
  stripping (bug-for-bug parity with legacy code), and unicode pass-through
- parseSettingLabel: split semantics, parens stripping, multi-newline limit,
  and edge cases
- SettingDialogState immutability: prove state.copy(setting = setting.copy(...))
  produces a new SensorSetting and leaves the original instance untouched
Verifies that empty queries propagate immediately while non-empty queries are
delayed by the configured debounce, that rapid updates coalesce to the latest
value, and that cancellation drops pending emissions.
@danielgomezrico danielgomezrico requested a review from TimoPtr May 4, 2026 02:34
…-allow-list

# Conflicts:
#	app/src/main/kotlin/io/homeassistant/companion/android/util/compose/entity/EntityPicker.kt
ktlint function-signature rule prefers single-line when within max line
length.
*/
@Composable
private fun rememberFilteredSettingEntries(
entries: List<Pair<String, String>>,
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fee247f — wrapped entries in a file-local @Immutable internal data class SettingEntries(val items: List<Pair<String, String>>) at the composable boundary. rememberFilteredSettingEntries now takes SettingEntries; SettingDialogState and filterSettingEntries keep their plain types. Avoided pulling in kotlinx-collections-immutable since it isn't used anywhere else in the repo. Pinned by new SettingEntriesTest.

*/
@Composable
private fun rememberFilteredSettingEntries(
entries: List<Pair<String, String>>,
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fee247f — wrapped entries in a file-local @Immutable internal data class SettingEntries(val items: List<Pair<String, String>>) at the composable boundary. rememberFilteredSettingEntries now takes SettingEntries; SettingDialogState and filterSettingEntries keep their plain types. Avoided pulling in kotlinx-collections-immutable since it isn't used anywhere else in the repo. Pinned by new SettingEntriesTest.

onClick: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
val (primaryText, secondaryText) = parseSettingLabel(label)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fee247fparseSettingLabel is genuinely an internal production helper shared between SensorDetailSettingSheet and SensorDetailSettingRow (in SensorDetailView.kt), so the @VisibleForTesting annotation was the wrong contract. Dropped the annotation, kept it internal. Existing ParseSettingLabelTest still exercises it without modification.

onClick: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
val (primaryText, secondaryText) = parseSettingLabel(label)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fee247fparseSettingLabel is genuinely an internal production helper shared between SensorDetailSettingSheet and SensorDetailSettingRow (in SensorDetailView.kt), so the @VisibleForTesting annotation was the wrong contract. Dropped the annotation, kept it internal. Existing ParseSettingLabelTest still exercises it without modification.

…bleForTesting

- Wrap setting entries in `@Immutable SettingEntries` data class at the
  composable boundary so the Compose Compiler can infer parameter
  stability for `rememberFilteredSettingEntries` (lint id 6307/6309).
- Drop `@VisibleForTesting` from `parseSettingLabel`; it is genuinely
  shared production helper consumed by `SensorDetailView.kt` (lint id
  6306/6308). Function stays `internal`.
- Add `SettingEntriesTest` exercising the new wrapper so a future
  regression of the stability fix fails loudly.
@danielgomezrico danielgomezrico marked this pull request as ready for review May 4, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants