Skip to content

Commit 23d930b

Browse files
committed
Added JSBluetooth.devices
1 parent 8d5a12b commit 23d930b

File tree

5 files changed

+113
-25
lines changed

5 files changed

+113
-25
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// CodingKey.swift
3+
//
4+
//
5+
// Created by Alsey Coleman Miller on 5/30/20.
6+
//
7+
8+
internal extension Sequence where Element == CodingKey {
9+
10+
/// KVC path string for current coding path.
11+
var path: String {
12+
return reduce("", { $0 + "\($0.isEmpty ? "" : ".")" + $1.stringValue })
13+
}
14+
}
15+
16+
internal extension CodingKey {
17+
18+
static var sanitizedName: String {
19+
20+
let rawName = String(reflecting: self)
21+
var elements = rawName.split(separator: ".")
22+
guard elements.count > 2
23+
else { return rawName }
24+
elements.removeFirst()
25+
// FIXME: Needs Foundation for String extensions
26+
//elements.removeAll { $0.contains("(unknown context") }
27+
return elements.reduce("", { $0 + ($0.isEmpty ? "" : ".") + $1 })
28+
}
29+
}

Sources/JavaScriptKit/JS Types/JSBluetooth.swift

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public final class JSBluetooth: JSType {
2424

2525
// MARK: - Accessors
2626

27+
/**
28+
Returns a Promise that resolved to a Boolean indicating whether the user-agent has the ability to support Bluetooth. Some user-agents let the user configure an option that affects what is returned by this value. If this option is set, that is the value returned by this method.
29+
*/
2730
public var isAvailable: JSPromise<Bool> {
2831
guard let function = jsObject.getAvailability.function
2932
else { fatalError("Invalid function \(#function)") }
@@ -33,38 +36,77 @@ public final class JSBluetooth: JSType {
3336
return promise
3437
}
3538

39+
/**
40+
Returns a `Promise` that resolved to an array of `BluetoothDevice` which the origin already obtained permission for via a call to `Bluetooth.requestDevice()`.
41+
*/
42+
public var devices: JSPromise<[JSBluetoothDevice]> {
43+
guard let function = jsObject.getDevices.function
44+
else { fatalError("Invalid function \(#function)") }
45+
let result = function.apply(this: jsObject)
46+
guard let promise = result.object.flatMap({ JSPromise<[JSBluetoothDevice]>($0) })
47+
else { fatalError("Invalid object \(result)") }
48+
return promise
49+
}
50+
3651
// MARK: - Methods
3752

3853
/// Returns a Promise to a BluetoothDevice object with the specified options.
3954
/// If there is no chooser UI, this method returns the first device matching the criteria.
4055
///
4156
/// - Returns: A Promise to a `BluetoothDevice` object.
42-
public func requestDevice(//filters: [] = [],
43-
//services: [] = [],
44-
acceptAllDevices: Bool = true) -> JSPromise<JSBluetoothDevice> {
45-
46-
enum Option: String {
47-
case filters
48-
case optionalServices
49-
case acceptAllDevices
50-
}
57+
public func requestDevice() -> JSPromise<JSBluetoothDevice> {
58+
let options = RequestDeviceOptions(filters: nil, optionalServices: nil, acceptAllDevices: true)
59+
return requestDevice(options: options)
60+
}
61+
62+
/// Returns a Promise to a BluetoothDevice object with the specified options.
63+
/// If there is no chooser UI, this method returns the first device matching the criteria.
64+
///
65+
/// - Returns: A Promise to a `BluetoothDevice` object.
66+
internal func requestDevice(options: RequestDeviceOptions) -> JSPromise<JSBluetoothDevice> {
5167

5268
// Bluetooth.requestDevice([options])
5369
// .then(function(bluetoothDevice) { ... })
5470

5571
guard let function = jsObject.requestDevice.function
5672
else { fatalError("Invalid function \(#function)") }
57-
58-
// FIXME: Improve, support all options
59-
let options = JSObject()
60-
options[Option.acceptAllDevices.rawValue] = acceptAllDevices.jsValue()
61-
options[Option.optionalServices.rawValue] = ["device_information"].jsValue()
62-
6373
let result = function.apply(this: jsObject, arguments: options)
64-
6574
guard let promise = result.object.flatMap({ JSPromise<JSBluetoothDevice>($0) })
6675
else { fatalError("Invalid object \(result)") }
67-
6876
return promise
6977
}
7078
}
79+
80+
// MARK: - Supporting Types
81+
82+
public extension JSBluetooth {
83+
84+
struct ScanFilter: Equatable, Hashable, Codable {
85+
86+
public var services: [String]?
87+
88+
public var name: String?
89+
90+
public var namePrefix: String?
91+
92+
public init(services: [String]? = nil,
93+
name: String? = nil,
94+
namePrefix: String? = nil) {
95+
self.services = services
96+
self.name = name
97+
self.namePrefix = namePrefix
98+
}
99+
}
100+
}
101+
102+
internal extension JSBluetooth {
103+
104+
struct RequestDeviceOptions: Encodable, JSValueConvertible {
105+
106+
var filters: [ScanFilter]?
107+
108+
var optionalServices: [String]?
109+
110+
var acceptAllDevices: Bool?
111+
}
112+
}

Sources/JavaScriptKit/JSDecoder.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ public struct JSDecoder {
33

44
// MARK: - Properties
55

6-
public var userInfo: [CodingUserInfoKey: Any] = [:]
6+
/// Any contextual information set by the user for encoding.
7+
public var userInfo = [CodingUserInfoKey : Any]()
8+
9+
/// Logging handler
10+
public var log: ((String) -> ())?
711

812
// MARK: - Initialization
913

Sources/JavaScriptKit/JSValueConstructible.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,10 @@ extension UInt64: JSValueConstructible {
8585
value.number.map(Self.init)
8686
}
8787
}
88+
89+
extension Array: JSValueConstructible where Element: JSValueConstructible {
90+
91+
public static func construct(from value: JSValue) -> Self? {
92+
return value.array?.compactMap { Element.construct(from: $0) }
93+
}
94+
}

Sources/JavaScriptKit/JSValueConvertible.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,7 @@ extension Dictionary: JSValueConvertible where Value == JSValueConvertible, Key
8383
}
8484
}
8585

86-
extension Array where Element: JSValueConvertible {
87-
public func jsValue() -> JSValue {
88-
Swift.Array<JSValueConvertible>.jsValue(self)()
89-
}
90-
}
91-
92-
extension Array: JSValueConvertible where Element == JSValueConvertible {
86+
extension Array: JSValueConvertible where Element: JSValueConvertible {
9387
public func jsValue() -> JSValue {
9488
return .object(JSArray(self).jsObject)
9589
}
@@ -192,3 +186,15 @@ extension Array where Element: JSValueConvertible {
192186
Swift.Array<JSValueConvertible>.withRawJSValues(self)(body)
193187
}
194188
}
189+
190+
extension JSValueConvertible where Self: Encodable {
191+
192+
func jsValue() -> JSValue {
193+
let encoder = JSEncoder()
194+
do { return try encoder.encode(self) }
195+
catch {
196+
JSConsole.error(error)
197+
return .undefined
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)