Skip to content

Commit

Permalink
Merge pull request #149 from NordicSemiconductor/improvement/filters
Browse files Browse the repository at this point in the history
Allowing filtering with filter selected and unselected
  • Loading branch information
philips77 authored Jun 25, 2024
2 parents 2db509e + a703553 commit cd9558d
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package no.nordicsemi.android.kotlin.ble.app.client

import android.os.ParcelUuid
import androidx.compose.material3.MaterialTheme
import androidx.hilt.navigation.compose.hiltViewModel
import no.nordicsemi.android.common.navigation.createDestination
import no.nordicsemi.android.common.navigation.createSimpleDestination
Expand All @@ -26,10 +25,10 @@ val ScannerDestination = defineDestination(ScannerDestinationId) {
val uuid = ParcelUuid(BlinkySpecifications.UUID_SERVICE_DEVICE)
val filters = listOf(
WithServiceUuid("Blinky", uuid, true),
OnlyNearby(rssi = -50 /* dBm */, initiallyEnabled = false),
OnlyWithNames(initiallyEnabled = true),
CustomFilter("Nordic", false) {
it.device.name?.contains("nordic", ignoreCase = true) == true
OnlyNearby(rssi = -50 /* dBm */, initiallySelected = false),
OnlyWithNames(initiallySelected = true),
CustomFilter("Nordic", false) { isFilterSelected, result ->
!isFilterSelected || result.device.name?.contains("nordic", ignoreCase = true) == true
}
)
ScannerScreen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ import no.nordicsemi.android.kotlin.ble.ui.scanner.view.ScannerAppBar
/**
* Based scanner filter class.
* @property title The title to be shown on the chip.
* @property initiallyEnabled Initial state of the filter.
* @property initiallySelected Initial state of the filter.
* @property filter The predicate applied to scanned devices.
*/
sealed class Filter(
open val title: String,
open val initiallyEnabled: Boolean,
val filter: (BleScanResults) -> Boolean,
open val initiallySelected: Boolean,
open val filter: (isFilterSelected: Boolean, result: BleScanResults) -> Boolean,
)

/**
Expand All @@ -65,11 +65,13 @@ sealed class Filter(
data class OnlyNearby(
override val title: String = "Nearby",
val rssi: Int = -50, // dBm
override val initiallyEnabled: Boolean = true,
override val initiallySelected: Boolean = true,
): Filter(
title = title,
initiallyEnabled = initiallyEnabled,
filter = { it.highestRssi >= rssi }
initiallySelected = initiallySelected,
filter = { isFilterSelected, result ->
!isFilterSelected || result.highestRssi >= rssi
}
)

/**
Expand All @@ -78,11 +80,13 @@ data class OnlyNearby(
*/
data class OnlyWithNames(
override val title: String = "Named",
override val initiallyEnabled: Boolean = true,
override val initiallySelected: Boolean = true,
) : Filter(
title = title,
initiallyEnabled = initiallyEnabled,
filter = { it.device.hasName || it.advertisedName?.isNotEmpty() == true }
initiallySelected = initiallySelected,
filter = { isFilterSelected, result ->
!isFilterSelected || result.device.hasName || result.advertisedName?.isNotEmpty() == true
}
)

/**
Expand All @@ -93,23 +97,25 @@ data class OnlyWithNames(
data class WithServiceUuid(
override val title: String,
val uuid: ParcelUuid,
override val initiallyEnabled: Boolean = true,
override val initiallySelected: Boolean = true,
): Filter(
title = title,
initiallyEnabled = initiallyEnabled,
filter = { it.device.isBonded || it.lastScanResult?.scanRecord?.serviceUuids?.contains(uuid) == true }
initiallySelected = initiallySelected,
filter = { isFilterSelected, result ->
!isFilterSelected || result.device.isBonded || result.lastScanResult?.scanRecord?.serviceUuids?.contains(uuid) == true
}
)

/**
* Custom filter.
*
* The filter shows only devices that match the given predicate.
* @property predicate The predicate to be applied to scanned devices.
*/
data class CustomFilter(
override val title: String,
override val initiallyEnabled: Boolean,
val predicate: (BleScanResults) -> Boolean,
): Filter(title, initiallyEnabled, predicate)
override val initiallySelected: Boolean,
override val filter: (isFilterSelected: Boolean, result: BleScanResults) -> Boolean,
): Filter(title, initiallySelected, filter)

@Composable
fun ScannerScreen(
Expand Down Expand Up @@ -156,13 +162,19 @@ fun ScannerScreen(
) {
// Show the "All" filter only when UUID was set.
val uuidFilter = if (uuid != null ) listOf(
WithServiceUuid("Service", uuid, true),
CustomFilter(
title = stringResource(id = R.string.filter_uuid),
initiallySelected = false,
filter = { isFilterSelected, result ->
isFilterSelected || result.device.isBonded || result.lastScanResult?.scanRecord?.serviceUuids?.contains(uuid) == true
}
),
) else emptyList()

// Nearby and Name filters were always visible.
val otherFilters = listOf(
OnlyNearby(rssi = -50 /* dBm */, initiallyEnabled = false),
OnlyWithNames(initiallyEnabled = true),
OnlyNearby(rssi = -50 /* dBm */, initiallySelected = false),
OnlyWithNames(initiallySelected = true),
)

ScannerScreen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ fun ScannerView(
) { isLocationRequiredAndDisabled ->
val viewModel = hiltViewModel<ScannerViewModel>()
LaunchedEffect(key1 = Unit) {
print("Launch effect")
viewModel.setFilters(filters)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@ internal class ScannerViewModel @Inject constructor(
private fun List<BleScanResults>.applyFilters(config: List<ScanFilterState>) =
filter { result ->
config.all {
!it.selected || it.predicate(result)
it.predicate(it.selected, result)
}
}

fun setFilters(filters: List<Filter>) {
this.filters = filters
this._filterConfig.update {
filters.map {
ScanFilterState(it.title, it.initiallyEnabled, it.filter)
ScanFilterState(it.title, it.initiallySelected, it.filter)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import no.nordicsemi.android.kotlin.ble.ui.scanner.R
internal data class ScanFilterState(
val title: String,
val selected: Boolean,
val predicate: (BleScanResults) -> Boolean,
val predicate: (isFilterSelected: Boolean, result: BleScanResults) -> Boolean,
)

@Composable
Expand Down Expand Up @@ -95,17 +95,17 @@ private fun FilterViewPreview() {
ScanFilterState(
title = stringResource(id = R.string.filter_uuid),
selected = true,
predicate = { true },
predicate = { selected,_ -> selected },
),
ScanFilterState(
title = stringResource(id = R.string.filter_nearby),
selected = false,
predicate = { true },
predicate = { selected,_ -> selected },
),
ScanFilterState(
title = stringResource(id = R.string.filter_name),
selected = true,
predicate = { true },
predicate = { selected,_ -> selected },
),
),
onChanged = {},
Expand Down

0 comments on commit cd9558d

Please sign in to comment.