Skip to content

Commit

Permalink
Improve search logic in feature inventory screen (#5232)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/1198194956794324/1208633884628758/f

### Description
Improve the (internal) feature flag inventory screen search logic:
Before:
* searches would filter feature flags that match the search text
After:
* searches filter feature flags that match the search text, but:
  * if match is a top-level features, all sub-features are also considered a match (even if their name doesn't match)
  * if match is a sub-feature, parent feature is also considered a match (even if its name doesn't match)

### Steps to test this PR

_Test_
- [x] install from this branch, open app -> settings -> feature flag inventory
- [x] search for a sub-feature by name
- [x] verify sub-feature and its parent top-level feature are displayed
- [x] search for a top-level feature by name (eg. autofill)
- [x] verify the top-level feature and ALL its sub-features are displayed
- [x] smoke test enable/disable features
  • Loading branch information
aitorvs authored Nov 5, 2024
1 parent 30f3827 commit 21d7919
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,17 @@ internal class ToggleImpl constructor(
private val callback: FeatureTogglesCallback?,
) : Toggle {

override fun equals(other: Any?): Boolean {
if (other !is Toggle) {
return false
}
return this.featureName() == other.featureName()
}

override fun hashCode(): Int {
return this.featureName().hashCode()
}

private fun Toggle.State.evaluateTargetMatching(isExperiment: Boolean): Boolean {
val variant = appVariantProvider.invoke()
// no targets then consider always treated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,25 +117,43 @@ class FeatureToggleInventoryActivity : DuckDuckGoActivity() {
private suspend fun getFeatureViews(): List<View> = withContext(dispatcherProvider.io()) {
val toggles = this@FeatureToggleInventoryActivity.toggles.await()
val match = featureNameFilter.get().lowercase()
val parentFeature = toggles
val parentFeatures = toggles
.filter { it.featureName().parentName == null }
.sortedBy { it.featureName().name.lowercase() }
val subFeatures = toggles
.filter { it.featureName().parentName != null }
.sortedBy { it.featureName().name.lowercase() }

val features = mutableListOf<Toggle>().apply {
for (parent in parentFeature) {
add(parent)
addAll(subFeatures.filter { it.featureName().parentName == parent.featureName().name })
// add parent features that match and all their sub-features
parentFeatures.forEach { parentFeature ->
if (match.isNotBlank()) {
if (parentFeature.featureName().name.lowercase().contains(match)) {
add(parentFeature)
// add also all sub-features
addAll(
subFeatures.filter { it.featureName().parentName == parentFeature.featureName().name },
)
}
} else {
for (parent in parentFeatures) {
add(parent)
addAll(subFeatures.filter { it.featureName().parentName == parent.featureName().name })
}
}
}
}.filter {
if (match.isNotBlank()) {
// Apply search box filter if needed
it.featureName().name.lowercase().contains(match)
} else {
true

// add sub-features that match and their parent feature
subFeatures.forEach { feature ->
if (match.isNotBlank() && feature.featureName().name.lowercase().contains(match)) {
// add its parent too
addAll(
parentFeatures.filter { it.featureName().name == feature.featureName().parentName },
)
add(feature)
}
}
}
}.distinct() // de-dup

val views = features.map { feature ->
OneLineListItem(this@FeatureToggleInventoryActivity).apply {
Expand Down

0 comments on commit 21d7919

Please sign in to comment.