Skip to content

Commit c6d400d

Browse files
authored
Add Options builder (#722)
1 parent 475833b commit c6d400d

4 files changed

Lines changed: 83 additions & 19 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The [`Scanner`] may be configured via the following DSL (shown are defaults, whe
2323
val scanner = Scanner {
2424
filters {
2525
match {
26-
name = "My device"
26+
name = Filter.Name.Exact("My device")
2727
}
2828
}
2929
logging {
@@ -293,16 +293,16 @@ specified options, the browser shows the user a list of peripherals matching the
293293
user is then returned (as a [`Peripheral`] object).
294294

295295
```kotlin
296-
val options = Options(
296+
val options = Options {
297297
filters {
298298
match {
299299
name = Filter.Name.Prefix("Example")
300300
}
301-
},
301+
}
302302
optionalServices = listOf(
303303
uuidFrom("f000aa80-0451-4000-b000-000000000000"),
304304
uuidFrom("f000aa81-0451-4000-b000-000000000000"),
305-
),
305+
)
306306
)
307307
val peripheral = scope.requestPeripheral(options).await()
308308
```

kable-core/src/jsMain/kotlin/Bluetooth.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private fun Options.filters(): List<BluetoothLEScanFilterInit> =
103103
if (filterSets?.isNotEmpty() == true) {
104104
filterSets.toBluetoothLEScanFilterInit()
105105
} else {
106-
FiltersBuilder().apply(filters).build().toBluetoothLEScanFilterInit()
106+
filterPredicates.toBluetoothLEScanFilterInit()
107107
}
108108

109109
// Note: Web Bluetooth requires that UUIDs be provided as lowercase strings.

kable-core/src/jsMain/kotlin/Options.kt

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,48 @@ package com.juul.kable
33
import com.benasher44.uuid.Uuid
44

55
/** https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice */
6-
public data class Options(
6+
public fun Options(builder: OptionsBuilder.() -> Unit): Options =
7+
OptionsBuilder().apply(builder).build()
8+
9+
@Deprecated(
10+
message = "Use Options builder instead. See https://github.com/JuulLabs/kable/issues/723 for details.",
11+
replaceWith = ReplaceWith("Options { }"),
12+
)
13+
public fun Options(
14+
filters: List<Filter>? = null,
15+
filterSets: List<FilterSet>? = null,
16+
optionalServices: List<Uuid>? = null,
17+
): Options = Options {
18+
filters {
19+
if (filters != null) {
20+
filters.forEach { filter ->
21+
match {
22+
when (filter) {
23+
is Filter.Name -> name = filter
24+
is Filter.Service -> services = listOf(filter.uuid)
25+
is Filter.ManufacturerData -> manufacturerData = listOf(filter)
26+
is Filter.Address -> { /* no-op */ }
27+
}
28+
}
29+
}
30+
} else if (filterSets != null) {
31+
filterSets.forEach { filterSet ->
32+
match {
33+
name = filterSet.name
34+
services = filterSet.services.map { it.uuid }
35+
manufacturerData = filterSet.manufacturerData
36+
}
37+
}
38+
}
39+
}
40+
this.optionalServices = optionalServices
41+
}
42+
43+
public data class Options internal constructor(
44+
745
@Deprecated(
8-
message = "Replaced with filters builder DSL",
9-
replaceWith = ReplaceWith("filters = { }"),
46+
message = "Replaced with filters builder DSL. See https://github.com/JuulLabs/kable/issues/723 for details.",
47+
replaceWith = ReplaceWith("Options { filters { } }"),
1048
level = DeprecationLevel.WARNING,
1149
)
1250
val filterSets: List<FilterSet>? = null,
@@ -17,17 +55,11 @@ public data class Options(
1755
*
1856
* https://webbluetoothcg.github.io/web-bluetooth/#device-discovery
1957
*/
58+
@Deprecated(
59+
message = "Use Options builder instead. See https://github.com/JuulLabs/kable/issues/723 for details.",
60+
replaceWith = ReplaceWith("Options { optionalServices = listOf() }"),
61+
)
2062
val optionalServices: List<Uuid>? = null,
2163

22-
/**
23-
* Filters to apply when requesting devices. If predicates are non-empty, then only devices
24-
* that match at least one of the predicates will appear in the `requestDevice` picker.
25-
*
26-
* Filtering on Service Data is not supported because it is not implemented:
27-
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/implementation-status.md
28-
*
29-
* Filtering on Manufacturer Data is supported and a good explanation can be found here:
30-
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/data-filters-explainer.md
31-
*/
32-
val filters: FiltersBuilder.() -> Unit = { },
64+
internal val filterPredicates: List<FilterPredicate>,
3365
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.juul.kable
2+
3+
import com.benasher44.uuid.Uuid
4+
5+
public class OptionsBuilder internal constructor() {
6+
7+
private var filterPredicates: List<FilterPredicate> = emptyList()
8+
9+
/**
10+
* Filters to apply when requesting devices. If predicates are non-empty, then only devices
11+
* that match at least one of the predicates will appear in the `requestDevice` picker.
12+
*
13+
* Filtering on Service Data is not supported because it is not implemented:
14+
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/implementation-status.md
15+
*
16+
* Filtering on Manufacturer Data is supported and a good explanation can be found here:
17+
* https://github.com/WebBluetoothCG/web-bluetooth/blob/main/data-filters-explainer.md
18+
*/
19+
public fun filters(builder: FiltersBuilder.() -> Unit) {
20+
filterPredicates = FiltersBuilder().apply(builder).build()
21+
}
22+
23+
/**
24+
* Access is only granted to services listed as [service filters][Filter.Service] in [filters].
25+
* If any additional services need to be accessed, they must be specified in [optionalServices].
26+
*
27+
* https://webbluetoothcg.github.io/web-bluetooth/#device-discovery
28+
*/
29+
public var optionalServices: List<Uuid>? = null
30+
31+
internal fun build() = Options(null, optionalServices, filterPredicates)
32+
}

0 commit comments

Comments
 (0)