Skip to content

Commit

Permalink
Add Options builder (#722)
Browse files Browse the repository at this point in the history
  • Loading branch information
twyatt authored Jul 29, 2024
1 parent 475833b commit c6d400d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 19 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The [`Scanner`] may be configured via the following DSL (shown are defaults, whe
val scanner = Scanner {
filters {
match {
name = "My device"
name = Filter.Name.Exact("My device")
}
}
logging {
Expand Down Expand Up @@ -293,16 +293,16 @@ specified options, the browser shows the user a list of peripherals matching the
user is then returned (as a [`Peripheral`] object).

```kotlin
val options = Options(
val options = Options {
filters {
match {
name = Filter.Name.Prefix("Example")
}
},
}
optionalServices = listOf(
uuidFrom("f000aa80-0451-4000-b000-000000000000"),
uuidFrom("f000aa81-0451-4000-b000-000000000000"),
),
)
)
val peripheral = scope.requestPeripheral(options).await()
```
Expand Down
2 changes: 1 addition & 1 deletion kable-core/src/jsMain/kotlin/Bluetooth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private fun Options.filters(): List<BluetoothLEScanFilterInit> =
if (filterSets?.isNotEmpty() == true) {
filterSets.toBluetoothLEScanFilterInit()
} else {
FiltersBuilder().apply(filters).build().toBluetoothLEScanFilterInit()
filterPredicates.toBluetoothLEScanFilterInit()
}

// Note: Web Bluetooth requires that UUIDs be provided as lowercase strings.
Expand Down
60 changes: 46 additions & 14 deletions kable-core/src/jsMain/kotlin/Options.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,48 @@ package com.juul.kable
import com.benasher44.uuid.Uuid

/** https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice */
public data class Options(
public fun Options(builder: OptionsBuilder.() -> Unit): Options =
OptionsBuilder().apply(builder).build()

@Deprecated(
message = "Use Options builder instead. See https://github.com/JuulLabs/kable/issues/723 for details.",
replaceWith = ReplaceWith("Options { }"),
)
public fun Options(
filters: List<Filter>? = null,
filterSets: List<FilterSet>? = null,
optionalServices: List<Uuid>? = null,
): Options = Options {
filters {
if (filters != null) {
filters.forEach { filter ->
match {
when (filter) {
is Filter.Name -> name = filter
is Filter.Service -> services = listOf(filter.uuid)
is Filter.ManufacturerData -> manufacturerData = listOf(filter)
is Filter.Address -> { /* no-op */ }
}
}
}
} else if (filterSets != null) {
filterSets.forEach { filterSet ->
match {
name = filterSet.name
services = filterSet.services.map { it.uuid }
manufacturerData = filterSet.manufacturerData
}
}
}
}
this.optionalServices = optionalServices
}

public data class Options internal constructor(

@Deprecated(
message = "Replaced with filters builder DSL",
replaceWith = ReplaceWith("filters = { }"),
message = "Replaced with filters builder DSL. See https://github.com/JuulLabs/kable/issues/723 for details.",
replaceWith = ReplaceWith("Options { filters { } }"),
level = DeprecationLevel.WARNING,
)
val filterSets: List<FilterSet>? = null,
Expand All @@ -17,17 +55,11 @@ public data class Options(
*
* https://webbluetoothcg.github.io/web-bluetooth/#device-discovery
*/
@Deprecated(
message = "Use Options builder instead. See https://github.com/JuulLabs/kable/issues/723 for details.",
replaceWith = ReplaceWith("Options { optionalServices = listOf() }"),
)
val optionalServices: List<Uuid>? = null,

/**
* Filters to apply when requesting devices. If predicates are non-empty, then only devices
* that match at least one of the predicates will appear in the `requestDevice` picker.
*
* Filtering on Service Data is not supported because it is not implemented:
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/implementation-status.md
*
* Filtering on Manufacturer Data is supported and a good explanation can be found here:
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/data-filters-explainer.md
*/
val filters: FiltersBuilder.() -> Unit = { },
internal val filterPredicates: List<FilterPredicate>,
)
32 changes: 32 additions & 0 deletions kable-core/src/jsMain/kotlin/OptionsBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.juul.kable

import com.benasher44.uuid.Uuid

public class OptionsBuilder internal constructor() {

private var filterPredicates: List<FilterPredicate> = emptyList()

/**
* Filters to apply when requesting devices. If predicates are non-empty, then only devices
* that match at least one of the predicates will appear in the `requestDevice` picker.
*
* Filtering on Service Data is not supported because it is not implemented:
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/implementation-status.md
*
* Filtering on Manufacturer Data is supported and a good explanation can be found here:
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/data-filters-explainer.md
*/
public fun filters(builder: FiltersBuilder.() -> Unit) {
filterPredicates = FiltersBuilder().apply(builder).build()
}

/**
* Access is only granted to services listed as [service filters][Filter.Service] in [filters].
* If any additional services need to be accessed, they must be specified in [optionalServices].
*
* https://webbluetoothcg.github.io/web-bluetooth/#device-discovery
*/
public var optionalServices: List<Uuid>? = null

internal fun build() = Options(null, optionalServices, filterPredicates)
}

0 comments on commit c6d400d

Please sign in to comment.