react-native-flic2 2.0.0-beta.1 → 2.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -22
- package/ios/Flic2.mm +12 -12
- package/lib/module/NativeFlic2.js.map +1 -1
- package/lib/module/index.js +6 -14
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeFlic2.d.ts +14 -49
- package/lib/typescript/src/NativeFlic2.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +17 -52
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/NativeFlic2.ts +30 -28
- package/src/index.ts +18 -40
- package/android/build.gradle +0 -81
- package/android/gradle.properties +0 -5
- package/android/src/main/AndroidManifest.xml +0 -27
- package/android/src/main/java/com/flic2/Flic2ButtonListener.kt +0 -128
- package/android/src/main/java/com/flic2/Flic2Converter.kt +0 -103
- package/android/src/main/java/com/flic2/Flic2Module.kt +0 -481
- package/android/src/main/java/com/flic2/Flic2Package.kt +0 -33
- package/android/src/main/java/com/flic2/Flic2Service.kt +0 -112
- package/lib/module/index.bak.js +0 -161
- package/lib/module/index.bak.js.map +0 -1
- package/lib/typescript/src/index.bak.d.ts +0 -1
- package/lib/typescript/src/index.bak.d.ts.map +0 -1
- package/src/index.bak.tsx +0 -159
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
package com.flic2
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableArray
|
|
5
|
-
import com.facebook.react.bridge.WritableMap
|
|
6
|
-
import io.flic.flic2libandroid.Flic2Button
|
|
7
|
-
|
|
8
|
-
object Flic2Converter {
|
|
9
|
-
|
|
10
|
-
fun buttonToMap(button: Flic2Button): WritableMap {
|
|
11
|
-
return Arguments.createMap().apply {
|
|
12
|
-
putString("uuid", button.uuid)
|
|
13
|
-
putString("identifier", button.uuid) // Android uses UUID as identifier
|
|
14
|
-
putString("name", button.getName() ?: "")
|
|
15
|
-
putString("nickname", button.getName() ?: "")
|
|
16
|
-
putString("bluetoothAddress", button.getBdAddr() ?: "")
|
|
17
|
-
putString("serialNumber", button.getSerialNumber() ?: "")
|
|
18
|
-
|
|
19
|
-
// Use connection state constants instead of enum
|
|
20
|
-
val connState = button.getConnectionState()
|
|
21
|
-
putInt("state", connectionStateToInt(connState))
|
|
22
|
-
putString("stateName", connectionStateToString(connState))
|
|
23
|
-
|
|
24
|
-
// iOS-only: Return defaults for trigger/latency mode (not supported in Android v1.1.0+)
|
|
25
|
-
putInt("triggerMode", 0)
|
|
26
|
-
putString("triggerModeName", "")
|
|
27
|
-
putInt("latencyMode", 0)
|
|
28
|
-
putString("latencyModeName", "")
|
|
29
|
-
|
|
30
|
-
putInt("pressCount", button.getPressCount())
|
|
31
|
-
putInt("firmwareRevision", button.getFirmwareVersion())
|
|
32
|
-
|
|
33
|
-
// Check if ready by comparing connection state
|
|
34
|
-
val isReady = connState == Flic2Button.CONNECTION_STATE_CONNECTED_READY
|
|
35
|
-
putBoolean("isReady", isReady)
|
|
36
|
-
|
|
37
|
-
// Get battery level from BatteryLevel object
|
|
38
|
-
val batteryLevel = button.getLastKnownBatteryLevel()
|
|
39
|
-
putDouble("batteryVoltage", batteryLevel?.voltage?.toDouble() ?: 0.0)
|
|
40
|
-
|
|
41
|
-
putBoolean("isUnpaired", button.isUnpaired())
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
fun buttonsToArray(buttons: List<Flic2Button>): WritableArray {
|
|
46
|
-
return Arguments.createArray().apply {
|
|
47
|
-
buttons.forEach { button ->
|
|
48
|
-
pushMap(buttonToMap(button))
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private fun connectionStateToInt(state: Int): Int {
|
|
54
|
-
return when (state) {
|
|
55
|
-
Flic2Button.CONNECTION_STATE_DISCONNECTED -> 0
|
|
56
|
-
Flic2Button.CONNECTION_STATE_CONNECTING -> 1
|
|
57
|
-
Flic2Button.CONNECTION_STATE_CONNECTED_STARTING -> 2
|
|
58
|
-
Flic2Button.CONNECTION_STATE_CONNECTED_READY -> 3
|
|
59
|
-
else -> 0
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private fun connectionStateToString(state: Int): String {
|
|
64
|
-
return when (state) {
|
|
65
|
-
Flic2Button.CONNECTION_STATE_DISCONNECTED -> "disconnected"
|
|
66
|
-
Flic2Button.CONNECTION_STATE_CONNECTING -> "connecting"
|
|
67
|
-
Flic2Button.CONNECTION_STATE_CONNECTED_STARTING -> "connected"
|
|
68
|
-
Flic2Button.CONNECTION_STATE_CONNECTED_READY -> "connected"
|
|
69
|
-
else -> "disconnected"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Trigger mode and latency mode are iOS-only features (removed from Android library v1.1.0+)
|
|
74
|
-
|
|
75
|
-
fun scanResultToString(result: Int): String {
|
|
76
|
-
return when (result) {
|
|
77
|
-
0 -> "success"
|
|
78
|
-
1 -> "alreadyRunning"
|
|
79
|
-
2 -> "bluetoothNotActivated"
|
|
80
|
-
3 -> "unknown"
|
|
81
|
-
4 -> "noPublicButtonDiscovered"
|
|
82
|
-
5 -> "alreadyConnectedToAnotherDevice"
|
|
83
|
-
6 -> "connectionTimeout"
|
|
84
|
-
7 -> "invalidVerifier"
|
|
85
|
-
8 -> "blePairingFailedPreviousPairingAlreadyExisting"
|
|
86
|
-
9 -> "blePairingFailedUserCanceled"
|
|
87
|
-
10 -> "blePairingFailedUnknownReason"
|
|
88
|
-
11 -> "appCredentialsDontMatch"
|
|
89
|
-
12 -> "userCanceled"
|
|
90
|
-
13 -> "invalidBluetoothAddress"
|
|
91
|
-
14 -> "genuineCheckFailed"
|
|
92
|
-
15 -> "tooManyApps"
|
|
93
|
-
16 -> "couldNotSetBluetoothNotify"
|
|
94
|
-
17 -> "couldNotDiscoverBluetoothServices"
|
|
95
|
-
18 -> "buttonDisconnectedDuringVerification"
|
|
96
|
-
19 -> "failedToEstablish"
|
|
97
|
-
20 -> "connectionLimitReached"
|
|
98
|
-
21 -> "notInPublicMode"
|
|
99
|
-
else -> "unknown"
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
package com.flic2
|
|
2
|
-
|
|
3
|
-
import android.content.ComponentName
|
|
4
|
-
import android.content.Context
|
|
5
|
-
import android.content.Intent
|
|
6
|
-
import android.content.ServiceConnection
|
|
7
|
-
import android.os.Build
|
|
8
|
-
import android.os.IBinder
|
|
9
|
-
import android.util.Log
|
|
10
|
-
import com.facebook.react.bridge.Arguments
|
|
11
|
-
import com.facebook.react.bridge.Promise
|
|
12
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
13
|
-
import com.facebook.react.bridge.WritableMap
|
|
14
|
-
import com.facebook.react.module.annotations.ReactModule
|
|
15
|
-
import io.flic.flic2libandroid.Flic2Button
|
|
16
|
-
import io.flic.flic2libandroid.Flic2Manager
|
|
17
|
-
import io.flic.flic2libandroid.Flic2ScanCallback
|
|
18
|
-
import kotlinx.coroutines.CoroutineScope
|
|
19
|
-
import kotlinx.coroutines.Dispatchers
|
|
20
|
-
import kotlinx.coroutines.Job
|
|
21
|
-
import kotlinx.coroutines.TimeoutCancellationException
|
|
22
|
-
import kotlinx.coroutines.cancel
|
|
23
|
-
import kotlinx.coroutines.launch
|
|
24
|
-
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
25
|
-
import kotlinx.coroutines.withTimeout
|
|
26
|
-
import kotlin.coroutines.resume
|
|
27
|
-
import kotlin.coroutines.resumeWithException
|
|
28
|
-
|
|
29
|
-
// Custom exception for scan errors with error codes
|
|
30
|
-
class ScanException(val errorCode: String, val code: Int, message: String) : Exception(message)
|
|
31
|
-
|
|
32
|
-
@ReactModule(name = Flic2Module.NAME)
|
|
33
|
-
class Flic2Module(reactContext: ReactApplicationContext) :
|
|
34
|
-
NativeFlic2Spec(reactContext) {
|
|
35
|
-
|
|
36
|
-
private var flic2Service: Flic2Service? = null
|
|
37
|
-
private var serviceBound = false
|
|
38
|
-
private val moduleScope = CoroutineScope(Dispatchers.Main + Job())
|
|
39
|
-
private var scanJob: Job? = null
|
|
40
|
-
private val buttonListeners = mutableMapOf<String, Flic2ButtonEventListener>()
|
|
41
|
-
private var initializePromise: Promise? = null
|
|
42
|
-
|
|
43
|
-
companion object {
|
|
44
|
-
const val NAME = "Flic2"
|
|
45
|
-
private const val TAG = "Flic2Module"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private val serviceConnection = object : ServiceConnection {
|
|
49
|
-
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
50
|
-
Log.d(TAG, "Service connected")
|
|
51
|
-
val binder = service as Flic2Service.Flic2ServiceBinder
|
|
52
|
-
flic2Service = binder.getService()
|
|
53
|
-
serviceBound = true
|
|
54
|
-
|
|
55
|
-
// Set up listeners for existing buttons
|
|
56
|
-
flic2Service?.getManager()?.let { manager ->
|
|
57
|
-
manager.buttons.forEach { button ->
|
|
58
|
-
setupButtonListener(button)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Resolve the initialize promise if pending
|
|
63
|
-
initializePromise?.let { promise ->
|
|
64
|
-
promise.resolve(Arguments.createMap().apply {
|
|
65
|
-
putBoolean("success", true)
|
|
66
|
-
putString("message", "Manager initialized successfully")
|
|
67
|
-
})
|
|
68
|
-
initializePromise = null
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
override fun onServiceDisconnected(name: ComponentName?) {
|
|
73
|
-
Log.d(TAG, "Service disconnected")
|
|
74
|
-
serviceBound = false
|
|
75
|
-
flic2Service = null
|
|
76
|
-
|
|
77
|
-
// Reject any pending initialize promise
|
|
78
|
-
initializePromise?.let { promise ->
|
|
79
|
-
promise.reject("SERVICE_DISCONNECTED", "Service disconnected unexpectedly")
|
|
80
|
-
initializePromise = null
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
override fun getName(): String {
|
|
86
|
-
return NAME
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
override fun invalidate() {
|
|
90
|
-
super.invalidate()
|
|
91
|
-
moduleScope.cancel()
|
|
92
|
-
if (serviceBound) {
|
|
93
|
-
reactApplicationContext.unbindService(serviceConnection)
|
|
94
|
-
serviceBound = false
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// MARK: - Manager Methods
|
|
99
|
-
|
|
100
|
-
override fun initialize(background: Boolean, promise: Promise) {
|
|
101
|
-
try {
|
|
102
|
-
// Store the promise to resolve when service is connected
|
|
103
|
-
initializePromise = promise
|
|
104
|
-
|
|
105
|
-
val intent = Intent(reactApplicationContext, Flic2Service::class.java)
|
|
106
|
-
|
|
107
|
-
// Start service
|
|
108
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
109
|
-
reactApplicationContext.startForegroundService(intent)
|
|
110
|
-
} else {
|
|
111
|
-
reactApplicationContext.startService(intent)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Bind to service - promise will be resolved in onServiceConnected
|
|
115
|
-
val bound = reactApplicationContext.bindService(
|
|
116
|
-
intent,
|
|
117
|
-
serviceConnection,
|
|
118
|
-
Context.BIND_AUTO_CREATE
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
if (!bound) {
|
|
122
|
-
initializePromise = null
|
|
123
|
-
promise.reject("INIT_ERROR", "Failed to bind to service")
|
|
124
|
-
}
|
|
125
|
-
} catch (e: Exception) {
|
|
126
|
-
Log.e(TAG, "Failed to initialize", e)
|
|
127
|
-
initializePromise = null
|
|
128
|
-
promise.reject("INIT_ERROR", "Failed to initialize: ${e.message}", e)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
override fun getButtons(promise: Promise) {
|
|
133
|
-
try {
|
|
134
|
-
val manager = flic2Service?.getManager()
|
|
135
|
-
if (manager == null) {
|
|
136
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
137
|
-
return
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
val buttons = manager.buttons
|
|
141
|
-
val buttonArray = Flic2Converter.buttonsToArray(buttons)
|
|
142
|
-
promise.resolve(buttonArray)
|
|
143
|
-
} catch (e: Exception) {
|
|
144
|
-
Log.e(TAG, "Failed to get buttons", e)
|
|
145
|
-
promise.reject("GET_BUTTONS_ERROR", "Failed to get buttons: ${e.message}", e)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
override fun scanForButtons(promise: Promise) {
|
|
150
|
-
val manager = flic2Service?.getManager()
|
|
151
|
-
if (manager == null) {
|
|
152
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Cancel any existing scan
|
|
157
|
-
scanJob?.cancel()
|
|
158
|
-
|
|
159
|
-
Log.d(TAG, "Starting scan")
|
|
160
|
-
|
|
161
|
-
// Emit started event (matches iOS)
|
|
162
|
-
emitOnScanStatusChange(Arguments.createMap().apply {
|
|
163
|
-
putString("event", "started")
|
|
164
|
-
putString("eventName", "started")
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
manager.startScan(object : Flic2ScanCallback {
|
|
168
|
-
override fun onDiscoveredAlreadyPairedButton(button: Flic2Button) {
|
|
169
|
-
Log.d(TAG, "Discovered already paired button")
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
override fun onDiscovered(bdAddr: String) {
|
|
173
|
-
Log.d(TAG, "Discovered button: $bdAddr")
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
override fun onConnected() {
|
|
177
|
-
Log.d(TAG, "Button connected during scan")
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
override fun onComplete(result: Int, subCode: Int, button: Flic2Button?) {
|
|
181
|
-
Log.d(TAG, "Scan complete: result=$result, button=${button?.uuid}")
|
|
182
|
-
|
|
183
|
-
val resultCode = mapScanResultToCode(result)
|
|
184
|
-
|
|
185
|
-
if (result == Flic2ScanCallback.RESULT_SUCCESS && button != null) {
|
|
186
|
-
// Auto-connect (trigger mode not available in Android v1.1.0+)
|
|
187
|
-
button.connect()
|
|
188
|
-
|
|
189
|
-
setupButtonListener(button)
|
|
190
|
-
|
|
191
|
-
// Emit discovered event as button event (like iOS)
|
|
192
|
-
emitOnButtonEvent(Arguments.createMap().apply {
|
|
193
|
-
putString("uuid", button.uuid)
|
|
194
|
-
putString("event", "discovered")
|
|
195
|
-
putMap("button", Flic2Converter.buttonToMap(button))
|
|
196
|
-
})
|
|
197
|
-
} else {
|
|
198
|
-
val errorCode = Flic2Converter.scanResultToString(result)
|
|
199
|
-
Log.e(TAG, "Scan failed with error code: $errorCode")
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Emit scan completion with result code
|
|
203
|
-
emitOnScanStatusChange(Arguments.createMap().apply {
|
|
204
|
-
putString("event", "completion")
|
|
205
|
-
putString("eventName", "completion")
|
|
206
|
-
putInt("result", resultCode)
|
|
207
|
-
})
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
// Return immediately - scan results will come through events
|
|
212
|
-
promise.resolve(Arguments.createMap().apply {
|
|
213
|
-
putBoolean("success", true)
|
|
214
|
-
putString("message", "Scan started")
|
|
215
|
-
})
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
override fun stopScan(promise: Promise) {
|
|
219
|
-
try {
|
|
220
|
-
val manager = flic2Service?.getManager()
|
|
221
|
-
if (manager == null) {
|
|
222
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
223
|
-
return
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
scanJob?.cancel()
|
|
227
|
-
manager.stopScan()
|
|
228
|
-
|
|
229
|
-
promise.resolve(Arguments.createMap().apply {
|
|
230
|
-
putBoolean("success", true)
|
|
231
|
-
putString("message", "Scan stopped")
|
|
232
|
-
})
|
|
233
|
-
} catch (e: Exception) {
|
|
234
|
-
Log.e(TAG, "Failed to stop scan", e)
|
|
235
|
-
promise.reject("STOP_SCAN_ERROR", "Failed to stop scan: ${e.message}", e)
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
override fun forgetButton(uuid: String, promise: Promise) {
|
|
240
|
-
try {
|
|
241
|
-
val manager = flic2Service?.getManager()
|
|
242
|
-
if (manager == null) {
|
|
243
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
244
|
-
return
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
val button = manager.buttons.find { it.uuid == uuid }
|
|
248
|
-
if (button == null) {
|
|
249
|
-
promise.reject("BUTTON_NOT_FOUND", "Button not found")
|
|
250
|
-
return
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Disconnect before forgetting like iOS
|
|
254
|
-
button.disconnectOrAbortPendingConnection()
|
|
255
|
-
|
|
256
|
-
// Remove listener
|
|
257
|
-
buttonListeners.remove(uuid)
|
|
258
|
-
|
|
259
|
-
// Forget button
|
|
260
|
-
manager.forgetButton(button)
|
|
261
|
-
|
|
262
|
-
promise.resolve(Arguments.createMap().apply {
|
|
263
|
-
putBoolean("success", true)
|
|
264
|
-
putString("message", "Button forgotten")
|
|
265
|
-
})
|
|
266
|
-
} catch (e: Exception) {
|
|
267
|
-
Log.e(TAG, "Failed to forget button", e)
|
|
268
|
-
promise.reject("FORGET_ERROR", "Failed to forget button: ${e.message}", e)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// MARK: - Button Methods
|
|
273
|
-
|
|
274
|
-
override fun connectButton(uuid: String, promise: Promise) {
|
|
275
|
-
try {
|
|
276
|
-
val button = findButton(uuid)
|
|
277
|
-
if (button == null) {
|
|
278
|
-
promise.reject("BUTTON_NOT_FOUND", "Button not found")
|
|
279
|
-
return
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
button.connect()
|
|
283
|
-
|
|
284
|
-
promise.resolve(Arguments.createMap().apply {
|
|
285
|
-
putBoolean("success", true)
|
|
286
|
-
putString("message", "Connection initiated")
|
|
287
|
-
})
|
|
288
|
-
} catch (e: Exception) {
|
|
289
|
-
Log.e(TAG, "Failed to connect button", e)
|
|
290
|
-
promise.reject("CONNECT_ERROR", "Failed to connect: ${e.message}", e)
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
override fun disconnectButton(uuid: String, promise: Promise) {
|
|
295
|
-
try {
|
|
296
|
-
val button = findButton(uuid)
|
|
297
|
-
if (button == null) {
|
|
298
|
-
promise.reject("BUTTON_NOT_FOUND", "Button not found")
|
|
299
|
-
return
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
button.disconnectOrAbortPendingConnection()
|
|
303
|
-
|
|
304
|
-
promise.resolve(Arguments.createMap().apply {
|
|
305
|
-
putBoolean("success", true)
|
|
306
|
-
putString("message", "Disconnection initiated")
|
|
307
|
-
})
|
|
308
|
-
} catch (e: Exception) {
|
|
309
|
-
Log.e(TAG, "Failed to disconnect button", e)
|
|
310
|
-
promise.reject("DISCONNECT_ERROR", "Failed to disconnect: ${e.message}", e)
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
override fun setTriggerMode(uuid: String, mode: Double, promise: Promise) {
|
|
315
|
-
promise.reject(
|
|
316
|
-
"NOT_SUPPORTED_ON_ANDROID",
|
|
317
|
-
"Trigger mode is only supported on iOS. Android Flic2 library v1.1.0+ does not support trigger modes."
|
|
318
|
-
)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
override fun setLatencyMode(uuid: String, mode: Double, promise: Promise) {
|
|
322
|
-
promise.reject(
|
|
323
|
-
"NOT_SUPPORTED_ON_ANDROID",
|
|
324
|
-
"Latency mode is only supported on iOS. Android Flic2 library v1.1.0+ does not support latency modes."
|
|
325
|
-
)
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
override fun setNickname(uuid: String, nickname: String, promise: Promise) {
|
|
329
|
-
try {
|
|
330
|
-
val button = findButton(uuid)
|
|
331
|
-
if (button == null) {
|
|
332
|
-
promise.reject("BUTTON_NOT_FOUND", "Button not found")
|
|
333
|
-
return
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// v1.1.0 uses setName() method instead of property
|
|
337
|
-
button.setName(nickname)
|
|
338
|
-
|
|
339
|
-
promise.resolve(Arguments.createMap().apply {
|
|
340
|
-
putBoolean("success", true)
|
|
341
|
-
putString("message", "Nickname set")
|
|
342
|
-
})
|
|
343
|
-
} catch (e: Exception) {
|
|
344
|
-
Log.e(TAG, "Failed to set nickname", e)
|
|
345
|
-
promise.reject("SET_NICKNAME_ERROR", "Failed to set nickname: ${e.message}", e)
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
override fun connectAllKnownButtons(promise: Promise) {
|
|
350
|
-
try {
|
|
351
|
-
val manager = flic2Service?.getManager()
|
|
352
|
-
if (manager == null) {
|
|
353
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
354
|
-
return
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
val buttons = manager.buttons
|
|
358
|
-
|
|
359
|
-
buttons.forEach { button ->
|
|
360
|
-
Log.d(TAG, "Connecting button: ${button.getName()}")
|
|
361
|
-
// Trigger mode not available in Android v1.1.0+
|
|
362
|
-
button.connect()
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
promise.resolve(Arguments.createMap().apply {
|
|
366
|
-
putBoolean("success", true)
|
|
367
|
-
putString("message", "All buttons connection initiated")
|
|
368
|
-
})
|
|
369
|
-
} catch (e: Exception) {
|
|
370
|
-
Log.e(TAG, "Failed to connect all buttons", e)
|
|
371
|
-
promise.reject("CONNECT_ALL_ERROR", "Failed to connect all buttons: ${e.message}", e)
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
override fun disconnectAllKnownButtons(promise: Promise) {
|
|
376
|
-
try {
|
|
377
|
-
val manager = flic2Service?.getManager()
|
|
378
|
-
if (manager == null) {
|
|
379
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
380
|
-
return
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
val buttons = manager.buttons
|
|
384
|
-
|
|
385
|
-
buttons.forEach { button ->
|
|
386
|
-
Log.d(TAG, "Disconnecting button: ${button.name}")
|
|
387
|
-
button.disconnectOrAbortPendingConnection()
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
promise.resolve(Arguments.createMap().apply {
|
|
391
|
-
putBoolean("success", true)
|
|
392
|
-
putString("message", "All buttons disconnection initiated")
|
|
393
|
-
})
|
|
394
|
-
} catch (e: Exception) {
|
|
395
|
-
Log.e(TAG, "Failed to disconnect all buttons", e)
|
|
396
|
-
promise.reject("DISCONNECT_ALL_ERROR", "Failed to disconnect all buttons: ${e.message}", e)
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
override fun forgetAllButtons(promise: Promise) {
|
|
401
|
-
try {
|
|
402
|
-
val manager = flic2Service?.getManager()
|
|
403
|
-
if (manager == null) {
|
|
404
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
405
|
-
return
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Create a copy of the list to avoid concurrent modification
|
|
409
|
-
val buttons = manager.buttons.toList()
|
|
410
|
-
|
|
411
|
-
buttons.forEach { button ->
|
|
412
|
-
buttonListeners.remove(button.uuid)
|
|
413
|
-
button.disconnectOrAbortPendingConnection()
|
|
414
|
-
manager.forgetButton(button)
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
promise.resolve(Arguments.createMap().apply {
|
|
418
|
-
putBoolean("success", true)
|
|
419
|
-
putString("message", "All buttons forgotten")
|
|
420
|
-
})
|
|
421
|
-
} catch (e: Exception) {
|
|
422
|
-
Log.e(TAG, "Failed to forget all buttons", e)
|
|
423
|
-
promise.reject("FORGET_ALL_ERROR", "Failed to forget all buttons: ${e.message}", e)
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
override fun isScanning(promise: Promise) {
|
|
428
|
-
try {
|
|
429
|
-
val manager = flic2Service?.getManager()
|
|
430
|
-
if (manager == null) {
|
|
431
|
-
promise.reject("NOT_INITIALIZED", "Manager not initialized")
|
|
432
|
-
return
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
val scanning = (scanJob != null && scanJob?.isActive == true)
|
|
436
|
-
promise.resolve(scanning)
|
|
437
|
-
} catch (e: Exception) {
|
|
438
|
-
Log.e(TAG, "Failed to check scanning status", e)
|
|
439
|
-
promise.reject("IS_SCANNING_ERROR", "Failed to check scanning status: ${e.message}", e)
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// MARK: - Helper Methods
|
|
444
|
-
|
|
445
|
-
private fun findButton(uuid: String): Flic2Button? {
|
|
446
|
-
return flic2Service?.getManager()?.buttons?.find { it.uuid == uuid }
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
private fun setupButtonListener(button: Flic2Button) {
|
|
450
|
-
// Remove existing listener if any
|
|
451
|
-
buttonListeners.remove(button.uuid)
|
|
452
|
-
|
|
453
|
-
// Create new listener
|
|
454
|
-
val listener = Flic2ButtonEventListener { event ->
|
|
455
|
-
emitOnButtonEvent(event)
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Add listener to button
|
|
459
|
-
button.addListener(listener)
|
|
460
|
-
|
|
461
|
-
// Store listener reference
|
|
462
|
-
buttonListeners[button.uuid] = listener
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
private fun mapScanResultToCode(result: Int): Int {
|
|
466
|
-
// Map Android library's 9 result codes (0-8) to TypeScript enum codes (0-21) matching iOS
|
|
467
|
-
// Android library only provides these constants, so we map them to the closest equivalent
|
|
468
|
-
return when (result) {
|
|
469
|
-
Flic2ScanCallback.RESULT_SUCCESS -> 0 // SUCCESS
|
|
470
|
-
Flic2ScanCallback.RESULT_FAILED_ALREADY_RUNNING -> 1 // ALREADY_RUNNING
|
|
471
|
-
Flic2ScanCallback.RESULT_FAILED_BLUETOOTH_OFF -> 2 // BLUETOOTH_NOT_ACTIVATED
|
|
472
|
-
Flic2ScanCallback.RESULT_FAILED_SCAN_ERROR -> 3 // UNKNOWN
|
|
473
|
-
Flic2ScanCallback.RESULT_FAILED_NO_NEW_BUTTONS_FOUND -> 4 // NO_PUBLIC_BUTTON_DISCOVERED
|
|
474
|
-
Flic2ScanCallback.RESULT_FAILED_BUTTON_ALREADY_CONNECTED_TO_OTHER_DEVICE -> 5 // ALREADY_CONNECTED_TO_ANOTHER_DEVICE
|
|
475
|
-
Flic2ScanCallback.RESULT_FAILED_CONNECT_TIMED_OUT -> 6 // CONNECTION_TIMEOUT
|
|
476
|
-
Flic2ScanCallback.RESULT_FAILED_VERIFY_TIMED_OUT -> 7 // INVALID_VERIFIER
|
|
477
|
-
Flic2ScanCallback.RESULT_SYSTEM_PAIRING_DIALOG_NOT_ACCEPTED -> 9 // BLE_PAIRING_FAILED_USER_CANCELED
|
|
478
|
-
else -> 3 // UNKNOWN (for any unexpected codes)
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
package com.flic2
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.BaseReactPackage
|
|
4
|
-
import com.facebook.react.bridge.NativeModule
|
|
5
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
-
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
-
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
-
import java.util.HashMap
|
|
9
|
-
|
|
10
|
-
class Flic2Package : BaseReactPackage() {
|
|
11
|
-
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
-
return if (name == Flic2Module.NAME) {
|
|
13
|
-
Flic2Module(reactContext)
|
|
14
|
-
} else {
|
|
15
|
-
null
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
20
|
-
return ReactModuleInfoProvider {
|
|
21
|
-
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
22
|
-
moduleInfos[Flic2Module.NAME] = ReactModuleInfo(
|
|
23
|
-
Flic2Module.NAME,
|
|
24
|
-
Flic2Module.NAME,
|
|
25
|
-
false, // canOverrideExistingModule
|
|
26
|
-
false, // needsEagerInit
|
|
27
|
-
false, // isCxxModule
|
|
28
|
-
true // isTurboModule
|
|
29
|
-
)
|
|
30
|
-
moduleInfos
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|