@thelacanians/vue-native-cli 0.4.3 → 0.4.5
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/dist/cli.js +102 -32
- package/native/android/README.md +205 -0
- package/native/android/VueNativeCore/build.gradle.kts +113 -0
- package/native/android/VueNativeCore/consumer-rules.pro +12 -0
- package/native/android/VueNativeCore/proguard-rules.pro +33 -0
- package/native/android/VueNativeCore/src/main/AndroidManifest.xml +17 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/ErrorOverlayView.kt +94 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/HotReloadManager.kt +105 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSPolyfills.kt +652 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSRuntime.kt +207 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +417 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/ComponentRegistry.kt +76 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActionSheetFactory.kt +78 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActivityIndicatorFactory.kt +46 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VAlertDialogFactory.kt +84 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VButtonFactory.kt +73 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VCheckboxFactory.kt +93 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VDropdownFactory.kt +125 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VImageFactory.kt +75 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VInputFactory.kt +210 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VKeyboardAvoidingFactory.kt +31 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +183 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VModalFactory.kt +105 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPickerFactory.kt +57 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPressableFactory.kt +109 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VProgressBarFactory.kt +43 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRadioFactory.kt +103 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRefreshControlFactory.kt +73 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRootFactory.kt +39 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSafeAreaFactory.kt +48 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +105 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSectionListFactory.kt +144 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSegmentedControlFactory.kt +77 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSliderFactory.kt +74 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VStatusBarFactory.kt +52 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSwitchFactory.kt +62 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VTextFactory.kt +53 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VVideoFactory.kt +191 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +48 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VWebViewFactory.kt +90 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/NativeComponentFactory.kt +40 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/VTextNodeView.kt +23 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/GestureHelper.kt +16 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/TouchableView.kt +105 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AnimationModule.kt +292 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AppStateModule.kt +41 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AsyncStorageModule.kt +59 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AudioModule.kt +331 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BackgroundTaskModule.kt +166 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BiometryModule.kt +56 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BluetoothModule.kt +302 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CalendarModule.kt +198 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CameraModule.kt +64 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ClipboardModule.kt +36 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ContactsModule.kt +288 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DatabaseModule.kt +229 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DeviceInfoModule.kt +39 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/FileSystemModule.kt +193 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeolocationModule.kt +68 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HapticsModule.kt +61 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HttpModule.kt +111 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/IAPModule.kt +302 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/KeyboardModule.kt +26 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/LinkingModule.kt +43 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModule.kt +27 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +92 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NetworkModule.kt +75 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NotificationsModule.kt +181 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/OTAModule.kt +255 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PerformanceModule.kt +147 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PermissionsModule.kt +126 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SecureStorageModule.kt +51 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SensorsModule.kt +134 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ShareModule.kt +36 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SocialAuthModule.kt +163 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/WebSocketModule.kt +155 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Styling/StyleEngine.kt +802 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Tags.kt +43 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/VueNativeActivity.kt +169 -0
- package/native/android/VueNativeCore/src/main/res/values/ids.xml +8 -0
- package/native/android/app/build.gradle.kts +45 -0
- package/native/android/app/proguard-rules.pro +5 -0
- package/native/android/app/src/main/AndroidManifest.xml +25 -0
- package/native/android/app/src/main/assets/.gitkeep +0 -0
- package/native/android/app/src/main/kotlin/com/vuenative/example/counter/MainActivity.kt +14 -0
- package/native/android/app/src/main/res/layout/activity_main.xml +6 -0
- package/native/android/app/src/main/res/values/strings.xml +3 -0
- package/native/android/app/src/main/res/values/themes.xml +9 -0
- package/native/android/app/src/main/res/xml/network_security_config.xml +8 -0
- package/native/android/build.gradle.kts +6 -0
- package/native/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/native/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/native/android/gradle.properties +4 -0
- package/native/android/gradlew +87 -0
- package/native/android/gradlew.bat +48 -0
- package/native/android/settings.gradle.kts +20 -0
- package/native/ios/VueNativeCore/Package.resolved +23 -0
- package/native/ios/VueNativeCore/Package.swift +32 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/CertificatePinning.swift +136 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/ErrorOverlayView.swift +89 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/HotReloadManager.swift +147 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSPolyfills.swift +711 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSRuntime.swift +421 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +906 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/VueNativeViewController.swift +88 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/ComponentRegistry.swift +193 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActionSheetFactory.swift +90 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActivityIndicatorFactory.swift +74 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VAlertDialogFactory.swift +149 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VButtonFactory.swift +93 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VCheckboxFactory.swift +114 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VDropdownFactory.swift +112 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VImageFactory.swift +172 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VInputFactory.swift +357 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VKeyboardAvoidingFactory.swift +99 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VListFactory.swift +250 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VModalFactory.swift +109 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPickerFactory.swift +96 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPressableFactory.swift +168 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VProgressBarFactory.swift +39 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRadioFactory.swift +167 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRefreshControlFactory.swift +153 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSafeAreaFactory.swift +56 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VScrollViewFactory.swift +240 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSectionListFactory.swift +248 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSegmentedControlFactory.swift +73 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSliderFactory.swift +63 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VStatusBarFactory.swift +50 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSwitchFactory.swift +108 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +290 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VVideoFactory.swift +250 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +157 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VWebViewFactory.swift +174 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/NativeComponentFactory.swift +53 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/Extensions.swift +31 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +107 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/TouchableView.swift +136 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/UIColor+Hex.swift +80 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AnimationModule.swift +283 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AppStateModule.swift +59 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AsyncStorageModule.swift +68 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AudioModule.swift +371 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BackgroundTaskModule.swift +135 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BiometryModule.swift +61 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BluetoothModule.swift +379 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CalendarModule.swift +154 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CameraModule.swift +315 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ClipboardModule.swift +33 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ContactsModule.swift +173 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DatabaseModule.swift +259 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DeviceInfoModule.swift +34 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/FileSystemModule.swift +233 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeolocationModule.swift +147 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/HapticsModule.swift +50 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/IAPModule.swift +194 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/KeyboardModule.swift +31 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/LinkingModule.swift +42 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModule.swift +28 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +78 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NetworkModule.swift +62 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NotificationsModule.swift +215 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/OTAModule.swift +281 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PerformanceModule.swift +141 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PermissionsModule.swift +190 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SecureStorageModule.swift +118 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SensorsModule.swift +103 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ShareModule.swift +48 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SocialAuthModule.swift +256 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/WebSocketModule.swift +213 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Resources/vue-native-placeholder.js +8 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Styling/StyleEngine.swift +885 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSRuntimeTests.swift +362 -0
- package/package.json +3 -2
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BluetoothModule.kt
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
package com.vuenative.core
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.bluetooth.*
|
|
5
|
+
import android.bluetooth.le.*
|
|
6
|
+
import android.content.Context
|
|
7
|
+
import android.content.pm.PackageManager
|
|
8
|
+
import android.os.Build
|
|
9
|
+
import android.os.Handler
|
|
10
|
+
import android.os.Looper
|
|
11
|
+
import android.util.Base64
|
|
12
|
+
import androidx.core.content.ContextCompat
|
|
13
|
+
import java.util.UUID
|
|
14
|
+
|
|
15
|
+
class BluetoothModule : NativeModule {
|
|
16
|
+
override val moduleName = "Bluetooth"
|
|
17
|
+
|
|
18
|
+
private var context: Context? = null
|
|
19
|
+
private var bridge: NativeBridge? = null
|
|
20
|
+
private var bluetoothAdapter: BluetoothAdapter? = null
|
|
21
|
+
private var scanner: BluetoothLeScanner? = null
|
|
22
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
23
|
+
|
|
24
|
+
private val discoveredDevices = mutableMapOf<String, BluetoothDevice>()
|
|
25
|
+
private val gattConnections = mutableMapOf<String, BluetoothGatt>()
|
|
26
|
+
private val connectCallbacks = mutableMapOf<String, (Any?, String?) -> Unit>()
|
|
27
|
+
private val readCallbacks = mutableMapOf<String, (Any?, String?) -> Unit>()
|
|
28
|
+
private val writeCallbacks = mutableMapOf<String, (Any?, String?) -> Unit>()
|
|
29
|
+
|
|
30
|
+
override fun initialize(context: Context, bridge: NativeBridge) {
|
|
31
|
+
this.context = context
|
|
32
|
+
this.bridge = bridge
|
|
33
|
+
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager
|
|
34
|
+
bluetoothAdapter = bluetoothManager?.adapter
|
|
35
|
+
scanner = bluetoothAdapter?.bluetoothLeScanner
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
|
|
39
|
+
when (method) {
|
|
40
|
+
"startScan" -> {
|
|
41
|
+
if (!hasBluetoothPermission()) {
|
|
42
|
+
callback(null, "Bluetooth permission not granted")
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
val serviceUUIDs = (args.getOrNull(0) as? List<*>)?.filterIsInstance<String>()
|
|
46
|
+
startScan(serviceUUIDs)
|
|
47
|
+
callback(null, null)
|
|
48
|
+
}
|
|
49
|
+
"stopScan" -> {
|
|
50
|
+
stopScan()
|
|
51
|
+
callback(null, null)
|
|
52
|
+
}
|
|
53
|
+
"connect" -> {
|
|
54
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run {
|
|
55
|
+
callback(null, "Missing deviceId"); return
|
|
56
|
+
}
|
|
57
|
+
connect(deviceId, callback)
|
|
58
|
+
}
|
|
59
|
+
"disconnect" -> {
|
|
60
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run {
|
|
61
|
+
callback(null, "Missing deviceId"); return
|
|
62
|
+
}
|
|
63
|
+
disconnect(deviceId, callback)
|
|
64
|
+
}
|
|
65
|
+
"readCharacteristic" -> {
|
|
66
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run { callback(null, "Missing deviceId"); return }
|
|
67
|
+
val serviceUUID = args.getOrNull(1)?.toString() ?: run { callback(null, "Missing serviceUUID"); return }
|
|
68
|
+
val charUUID = args.getOrNull(2)?.toString() ?: run { callback(null, "Missing charUUID"); return }
|
|
69
|
+
readCharacteristic(deviceId, serviceUUID, charUUID, callback)
|
|
70
|
+
}
|
|
71
|
+
"writeCharacteristic" -> {
|
|
72
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run { callback(null, "Missing deviceId"); return }
|
|
73
|
+
val serviceUUID = args.getOrNull(1)?.toString() ?: run { callback(null, "Missing serviceUUID"); return }
|
|
74
|
+
val charUUID = args.getOrNull(2)?.toString() ?: run { callback(null, "Missing charUUID"); return }
|
|
75
|
+
val dataBase64 = args.getOrNull(3)?.toString() ?: run { callback(null, "Missing data"); return }
|
|
76
|
+
writeCharacteristic(deviceId, serviceUUID, charUUID, dataBase64, callback)
|
|
77
|
+
}
|
|
78
|
+
"subscribeToCharacteristic" -> {
|
|
79
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run { callback(null, "Missing deviceId"); return }
|
|
80
|
+
val serviceUUID = args.getOrNull(1)?.toString() ?: run { callback(null, "Missing serviceUUID"); return }
|
|
81
|
+
val charUUID = args.getOrNull(2)?.toString() ?: run { callback(null, "Missing charUUID"); return }
|
|
82
|
+
subscribeToCharacteristic(deviceId, serviceUUID, charUUID, callback)
|
|
83
|
+
}
|
|
84
|
+
"unsubscribeFromCharacteristic" -> {
|
|
85
|
+
val deviceId = args.getOrNull(0)?.toString() ?: run { callback(null, "Missing deviceId"); return }
|
|
86
|
+
val serviceUUID = args.getOrNull(1)?.toString() ?: run { callback(null, "Missing serviceUUID"); return }
|
|
87
|
+
val charUUID = args.getOrNull(2)?.toString() ?: run { callback(null, "Missing charUUID"); return }
|
|
88
|
+
unsubscribeFromCharacteristic(deviceId, serviceUUID, charUUID, callback)
|
|
89
|
+
}
|
|
90
|
+
"getState" -> {
|
|
91
|
+
val state = when {
|
|
92
|
+
bluetoothAdapter == null -> "unsupported"
|
|
93
|
+
bluetoothAdapter?.isEnabled != true -> "poweredOff"
|
|
94
|
+
else -> "poweredOn"
|
|
95
|
+
}
|
|
96
|
+
callback(state, null)
|
|
97
|
+
}
|
|
98
|
+
else -> callback(null, "Unknown method: $method")
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private fun hasBluetoothPermission(): Boolean {
|
|
103
|
+
val ctx = context ?: return false
|
|
104
|
+
return if (Build.VERSION.SDK_INT >= 31) {
|
|
105
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
|
|
106
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
|
|
107
|
+
} else {
|
|
108
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Suppress("MissingPermission")
|
|
113
|
+
private fun startScan(serviceUUIDs: List<String>?) {
|
|
114
|
+
val filters = serviceUUIDs?.map { uuid ->
|
|
115
|
+
ScanFilter.Builder().setServiceUuid(android.os.ParcelUuid(UUID.fromString(uuid))).build()
|
|
116
|
+
}
|
|
117
|
+
val settings = ScanSettings.Builder()
|
|
118
|
+
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
|
119
|
+
.build()
|
|
120
|
+
scanner?.startScan(filters, settings, scanCallback)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Suppress("MissingPermission")
|
|
124
|
+
private fun stopScan() {
|
|
125
|
+
scanner?.stopScan(scanCallback)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@Suppress("MissingPermission")
|
|
129
|
+
private fun connect(deviceId: String, callback: (Any?, String?) -> Unit) {
|
|
130
|
+
val device = discoveredDevices[deviceId]
|
|
131
|
+
if (device == null) {
|
|
132
|
+
callback(null, "Device not found: $deviceId")
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
connectCallbacks[deviceId] = callback
|
|
136
|
+
device.connectGatt(context, false, gattCallback)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@Suppress("MissingPermission")
|
|
140
|
+
private fun disconnect(deviceId: String, callback: (Any?, String?) -> Unit) {
|
|
141
|
+
val gatt = gattConnections[deviceId]
|
|
142
|
+
if (gatt == null) {
|
|
143
|
+
callback(null, "Device not connected: $deviceId")
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
gatt.disconnect()
|
|
147
|
+
gatt.close()
|
|
148
|
+
gattConnections.remove(deviceId)
|
|
149
|
+
callback(null, null)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@Suppress("MissingPermission")
|
|
153
|
+
private fun readCharacteristic(deviceId: String, serviceUUID: String, charUUID: String, callback: (Any?, String?) -> Unit) {
|
|
154
|
+
val gatt = gattConnections[deviceId] ?: run { callback(null, "Device not connected"); return }
|
|
155
|
+
val char = findCharacteristic(gatt, serviceUUID, charUUID) ?: run { callback(null, "Characteristic not found"); return }
|
|
156
|
+
val key = "$deviceId:$serviceUUID:$charUUID"
|
|
157
|
+
readCallbacks[key] = callback
|
|
158
|
+
gatt.readCharacteristic(char)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@Suppress("MissingPermission")
|
|
162
|
+
private fun writeCharacteristic(deviceId: String, serviceUUID: String, charUUID: String, dataBase64: String, callback: (Any?, String?) -> Unit) {
|
|
163
|
+
val gatt = gattConnections[deviceId] ?: run { callback(null, "Device not connected"); return }
|
|
164
|
+
val char = findCharacteristic(gatt, serviceUUID, charUUID) ?: run { callback(null, "Characteristic not found"); return }
|
|
165
|
+
val data = Base64.decode(dataBase64, Base64.DEFAULT)
|
|
166
|
+
val key = "$deviceId:$serviceUUID:$charUUID"
|
|
167
|
+
writeCallbacks[key] = callback
|
|
168
|
+
char.value = data
|
|
169
|
+
gatt.writeCharacteristic(char)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@Suppress("MissingPermission")
|
|
173
|
+
private fun subscribeToCharacteristic(deviceId: String, serviceUUID: String, charUUID: String, callback: (Any?, String?) -> Unit) {
|
|
174
|
+
val gatt = gattConnections[deviceId] ?: run { callback(null, "Device not connected"); return }
|
|
175
|
+
val char = findCharacteristic(gatt, serviceUUID, charUUID) ?: run { callback(null, "Characteristic not found"); return }
|
|
176
|
+
gatt.setCharacteristicNotification(char, true)
|
|
177
|
+
val descriptor = char.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
|
|
178
|
+
descriptor?.let {
|
|
179
|
+
it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
|
180
|
+
gatt.writeDescriptor(it)
|
|
181
|
+
}
|
|
182
|
+
callback(null, null)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@Suppress("MissingPermission")
|
|
186
|
+
private fun unsubscribeFromCharacteristic(deviceId: String, serviceUUID: String, charUUID: String, callback: (Any?, String?) -> Unit) {
|
|
187
|
+
val gatt = gattConnections[deviceId] ?: run { callback(null, "Device not connected"); return }
|
|
188
|
+
val char = findCharacteristic(gatt, serviceUUID, charUUID) ?: run { callback(null, "Characteristic not found"); return }
|
|
189
|
+
gatt.setCharacteristicNotification(char, false)
|
|
190
|
+
callback(null, null)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private fun findCharacteristic(gatt: BluetoothGatt, serviceUUID: String, charUUID: String): BluetoothGattCharacteristic? {
|
|
194
|
+
val service = gatt.getService(UUID.fromString(serviceUUID)) ?: return null
|
|
195
|
+
return service.getCharacteristic(UUID.fromString(charUUID))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private val scanCallback = object : ScanCallback() {
|
|
199
|
+
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
|
200
|
+
val device = result.device
|
|
201
|
+
@Suppress("MissingPermission")
|
|
202
|
+
val name = device.name ?: ""
|
|
203
|
+
val id = device.address
|
|
204
|
+
discoveredDevices[id] = device
|
|
205
|
+
mainHandler.post {
|
|
206
|
+
bridge?.dispatchGlobalEvent("ble:deviceFound", mapOf(
|
|
207
|
+
"id" to id,
|
|
208
|
+
"name" to name,
|
|
209
|
+
"rssi" to result.rssi,
|
|
210
|
+
))
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private val gattCallback = object : BluetoothGattCallback() {
|
|
216
|
+
@Suppress("MissingPermission")
|
|
217
|
+
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
|
218
|
+
val deviceId = gatt.device.address
|
|
219
|
+
mainHandler.post {
|
|
220
|
+
when (newState) {
|
|
221
|
+
BluetoothProfile.STATE_CONNECTED -> {
|
|
222
|
+
gattConnections[deviceId] = gatt
|
|
223
|
+
gatt.discoverServices()
|
|
224
|
+
val payload = mapOf("id" to deviceId, "name" to (gatt.device.name ?: ""))
|
|
225
|
+
bridge?.dispatchGlobalEvent("ble:connected", payload)
|
|
226
|
+
connectCallbacks.remove(deviceId)?.invoke(payload, null)
|
|
227
|
+
}
|
|
228
|
+
BluetoothProfile.STATE_DISCONNECTED -> {
|
|
229
|
+
gattConnections.remove(deviceId)
|
|
230
|
+
gatt.close()
|
|
231
|
+
bridge?.dispatchGlobalEvent("ble:disconnected", mapOf("id" to deviceId))
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
|
238
|
+
// Services are now available for read/write/subscribe
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
|
|
242
|
+
val deviceId = gatt.device.address
|
|
243
|
+
val serviceUUID = characteristic.service.uuid.toString()
|
|
244
|
+
val charUUID = characteristic.uuid.toString()
|
|
245
|
+
val key = "$deviceId:$serviceUUID:$charUUID"
|
|
246
|
+
val valueBase64 = Base64.encodeToString(characteristic.value ?: ByteArray(0), Base64.NO_WRAP)
|
|
247
|
+
mainHandler.post {
|
|
248
|
+
val cb = readCallbacks.remove(key)
|
|
249
|
+
if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
250
|
+
cb?.invoke(mapOf(
|
|
251
|
+
"value" to valueBase64,
|
|
252
|
+
"characteristicUUID" to charUUID,
|
|
253
|
+
"serviceUUID" to serviceUUID,
|
|
254
|
+
), null)
|
|
255
|
+
} else {
|
|
256
|
+
cb?.invoke(null, "Read failed with status: $status")
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
|
|
262
|
+
val deviceId = gatt.device.address
|
|
263
|
+
val serviceUUID = characteristic.service.uuid.toString()
|
|
264
|
+
val charUUID = characteristic.uuid.toString()
|
|
265
|
+
val key = "$deviceId:$serviceUUID:$charUUID"
|
|
266
|
+
mainHandler.post {
|
|
267
|
+
val cb = writeCallbacks.remove(key)
|
|
268
|
+
if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
269
|
+
cb?.invoke(null, null)
|
|
270
|
+
} else {
|
|
271
|
+
cb?.invoke(null, "Write failed with status: $status")
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
|
|
277
|
+
val deviceId = gatt.device.address
|
|
278
|
+
val serviceUUID = characteristic.service.uuid.toString()
|
|
279
|
+
val charUUID = characteristic.uuid.toString()
|
|
280
|
+
val valueBase64 = Base64.encodeToString(characteristic.value ?: ByteArray(0), Base64.NO_WRAP)
|
|
281
|
+
mainHandler.post {
|
|
282
|
+
bridge?.dispatchGlobalEvent("ble:characteristicChanged", mapOf(
|
|
283
|
+
"deviceId" to deviceId,
|
|
284
|
+
"serviceUUID" to serviceUUID,
|
|
285
|
+
"characteristicUUID" to charUUID,
|
|
286
|
+
"value" to valueBase64,
|
|
287
|
+
))
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
override fun destroy() {
|
|
293
|
+
@Suppress("MissingPermission")
|
|
294
|
+
scanner?.stopScan(scanCallback)
|
|
295
|
+
gattConnections.values.forEach {
|
|
296
|
+
@Suppress("MissingPermission")
|
|
297
|
+
it.disconnect()
|
|
298
|
+
it.close()
|
|
299
|
+
}
|
|
300
|
+
gattConnections.clear()
|
|
301
|
+
}
|
|
302
|
+
}
|
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CalendarModule.kt
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
package com.vuenative.core
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.ContentValues
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.pm.PackageManager
|
|
7
|
+
import android.net.Uri
|
|
8
|
+
import android.provider.CalendarContract
|
|
9
|
+
import androidx.core.content.ContextCompat
|
|
10
|
+
|
|
11
|
+
class CalendarModule : NativeModule {
|
|
12
|
+
override val moduleName = "Calendar"
|
|
13
|
+
|
|
14
|
+
private var context: Context? = null
|
|
15
|
+
|
|
16
|
+
override fun initialize(context: Context, bridge: NativeBridge) {
|
|
17
|
+
this.context = context.applicationContext
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
|
|
21
|
+
val ctx = context ?: run { callback(null, "Not initialized"); return }
|
|
22
|
+
|
|
23
|
+
when (method) {
|
|
24
|
+
"requestAccess" -> {
|
|
25
|
+
val granted = ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_CALENDAR) ==
|
|
26
|
+
PackageManager.PERMISSION_GRANTED
|
|
27
|
+
callback(mapOf("granted" to granted), null)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
"getEvents" -> {
|
|
31
|
+
val startMs = (args.getOrNull(0) as? Number)?.toLong() ?: run {
|
|
32
|
+
callback(null, "Missing startDate"); return
|
|
33
|
+
}
|
|
34
|
+
val endMs = (args.getOrNull(1) as? Number)?.toLong() ?: run {
|
|
35
|
+
callback(null, "Missing endDate"); return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!hasCalendarReadPermission(ctx)) {
|
|
39
|
+
callback(null, "Calendar read permission not granted"); return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
val events = mutableListOf<Map<String, Any?>>()
|
|
44
|
+
val projection = arrayOf(
|
|
45
|
+
CalendarContract.Events._ID,
|
|
46
|
+
CalendarContract.Events.TITLE,
|
|
47
|
+
CalendarContract.Events.DTSTART,
|
|
48
|
+
CalendarContract.Events.DTEND,
|
|
49
|
+
CalendarContract.Events.ALL_DAY,
|
|
50
|
+
CalendarContract.Events.CALENDAR_ID,
|
|
51
|
+
CalendarContract.Events.DESCRIPTION,
|
|
52
|
+
CalendarContract.Events.EVENT_LOCATION,
|
|
53
|
+
)
|
|
54
|
+
val selection = "${CalendarContract.Events.DTSTART} >= ? AND ${CalendarContract.Events.DTEND} <= ?"
|
|
55
|
+
val selectionArgs = arrayOf(startMs.toString(), endMs.toString())
|
|
56
|
+
|
|
57
|
+
ctx.contentResolver.query(
|
|
58
|
+
CalendarContract.Events.CONTENT_URI,
|
|
59
|
+
projection, selection, selectionArgs, "${CalendarContract.Events.DTSTART} ASC"
|
|
60
|
+
)?.use { cursor ->
|
|
61
|
+
while (cursor.moveToNext()) {
|
|
62
|
+
events.add(mapOf(
|
|
63
|
+
"id" to cursor.getLong(0).toString(),
|
|
64
|
+
"title" to (cursor.getString(1) ?: ""),
|
|
65
|
+
"startDate" to cursor.getLong(2),
|
|
66
|
+
"endDate" to cursor.getLong(3),
|
|
67
|
+
"isAllDay" to (cursor.getInt(4) == 1),
|
|
68
|
+
"calendarId" to cursor.getLong(5).toString(),
|
|
69
|
+
"notes" to (cursor.getString(6) ?: ""),
|
|
70
|
+
"location" to (cursor.getString(7) ?: ""),
|
|
71
|
+
))
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
callback(events, null)
|
|
75
|
+
} catch (e: Exception) {
|
|
76
|
+
callback(null, e.message)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
"createEvent" -> {
|
|
81
|
+
val title = args.getOrNull(0)?.toString() ?: run {
|
|
82
|
+
callback(null, "Missing title"); return
|
|
83
|
+
}
|
|
84
|
+
val startMs = (args.getOrNull(1) as? Number)?.toLong() ?: run {
|
|
85
|
+
callback(null, "Missing startDate"); return
|
|
86
|
+
}
|
|
87
|
+
val endMs = (args.getOrNull(2) as? Number)?.toLong() ?: run {
|
|
88
|
+
callback(null, "Missing endDate"); return
|
|
89
|
+
}
|
|
90
|
+
val notes = args.getOrNull(3)?.toString()
|
|
91
|
+
val calendarId = args.getOrNull(4)?.toString()
|
|
92
|
+
|
|
93
|
+
if (!hasCalendarWritePermission(ctx)) {
|
|
94
|
+
callback(null, "Calendar write permission not granted"); return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
val values = ContentValues().apply {
|
|
99
|
+
put(CalendarContract.Events.TITLE, title)
|
|
100
|
+
put(CalendarContract.Events.DTSTART, startMs)
|
|
101
|
+
put(CalendarContract.Events.DTEND, endMs)
|
|
102
|
+
put(CalendarContract.Events.EVENT_TIMEZONE, java.util.TimeZone.getDefault().id)
|
|
103
|
+
if (notes != null) put(CalendarContract.Events.DESCRIPTION, notes)
|
|
104
|
+
if (calendarId != null) {
|
|
105
|
+
put(CalendarContract.Events.CALENDAR_ID, calendarId.toLong())
|
|
106
|
+
} else {
|
|
107
|
+
put(CalendarContract.Events.CALENDAR_ID, getDefaultCalendarId(ctx))
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
val uri: Uri? = ctx.contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)
|
|
111
|
+
val eventId = uri?.lastPathSegment ?: ""
|
|
112
|
+
callback(mapOf("eventId" to eventId), null)
|
|
113
|
+
} catch (e: Exception) {
|
|
114
|
+
callback(null, e.message)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
"deleteEvent" -> {
|
|
119
|
+
val eventId = args.getOrNull(0)?.toString() ?: run {
|
|
120
|
+
callback(null, "Missing eventId"); return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!hasCalendarWritePermission(ctx)) {
|
|
124
|
+
callback(null, "Calendar write permission not granted"); return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
val uri = CalendarContract.Events.CONTENT_URI.buildUpon().appendPath(eventId).build()
|
|
129
|
+
ctx.contentResolver.delete(uri, null, null)
|
|
130
|
+
callback(null, null)
|
|
131
|
+
} catch (e: Exception) {
|
|
132
|
+
callback(null, e.message)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
"getCalendars" -> {
|
|
137
|
+
if (!hasCalendarReadPermission(ctx)) {
|
|
138
|
+
callback(null, "Calendar read permission not granted"); return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
val calendars = mutableListOf<Map<String, Any?>>()
|
|
143
|
+
val projection = arrayOf(
|
|
144
|
+
CalendarContract.Calendars._ID,
|
|
145
|
+
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
|
|
146
|
+
CalendarContract.Calendars.CALENDAR_COLOR,
|
|
147
|
+
CalendarContract.Calendars.ACCOUNT_TYPE,
|
|
148
|
+
)
|
|
149
|
+
ctx.contentResolver.query(
|
|
150
|
+
CalendarContract.Calendars.CONTENT_URI,
|
|
151
|
+
projection, null, null, null
|
|
152
|
+
)?.use { cursor ->
|
|
153
|
+
while (cursor.moveToNext()) {
|
|
154
|
+
val color = cursor.getInt(2)
|
|
155
|
+
calendars.add(mapOf(
|
|
156
|
+
"id" to cursor.getLong(0).toString(),
|
|
157
|
+
"title" to (cursor.getString(1) ?: ""),
|
|
158
|
+
"color" to String.format("#%06X", 0xFFFFFF and color),
|
|
159
|
+
"type" to (cursor.getString(3) ?: "local"),
|
|
160
|
+
))
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
callback(calendars, null)
|
|
164
|
+
} catch (e: Exception) {
|
|
165
|
+
callback(null, e.message)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
else -> callback(null, "Unknown method: $method")
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private fun hasCalendarReadPermission(ctx: Context): Boolean =
|
|
174
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED
|
|
175
|
+
|
|
176
|
+
private fun hasCalendarWritePermission(ctx: Context): Boolean =
|
|
177
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED
|
|
178
|
+
|
|
179
|
+
private fun getDefaultCalendarId(ctx: Context): Long {
|
|
180
|
+
ctx.contentResolver.query(
|
|
181
|
+
CalendarContract.Calendars.CONTENT_URI,
|
|
182
|
+
arrayOf(CalendarContract.Calendars._ID),
|
|
183
|
+
"${CalendarContract.Calendars.IS_PRIMARY} = 1",
|
|
184
|
+
null, null
|
|
185
|
+
)?.use { cursor ->
|
|
186
|
+
if (cursor.moveToFirst()) return cursor.getLong(0)
|
|
187
|
+
}
|
|
188
|
+
// Fallback: first available calendar
|
|
189
|
+
ctx.contentResolver.query(
|
|
190
|
+
CalendarContract.Calendars.CONTENT_URI,
|
|
191
|
+
arrayOf(CalendarContract.Calendars._ID),
|
|
192
|
+
null, null, null
|
|
193
|
+
)?.use { cursor ->
|
|
194
|
+
if (cursor.moveToFirst()) return cursor.getLong(0)
|
|
195
|
+
}
|
|
196
|
+
return 1L
|
|
197
|
+
}
|
|
198
|
+
}
|
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CameraModule.kt
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package com.vuenative.core
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CameraModule — backs the useCamera() composable.
|
|
7
|
+
*
|
|
8
|
+
* Camera capture (launchCamera, launchImageLibrary, captureVideo) requires Activity-level
|
|
9
|
+
* startActivityForResult / registerForActivityResult hook. This stub ensures
|
|
10
|
+
* the module exists so JS composables can import it without crashing.
|
|
11
|
+
*
|
|
12
|
+
* QR code scanning is implemented using the device camera and ZXing/ML Kit
|
|
13
|
+
* when available. The host Activity must provide the implementation.
|
|
14
|
+
*
|
|
15
|
+
* To enable camera in your app:
|
|
16
|
+
* 1. Override onActivityResult in your VueNativeActivity subclass.
|
|
17
|
+
* 2. Register a concrete CameraModule implementation that stores the Activity reference.
|
|
18
|
+
*
|
|
19
|
+
* Methods:
|
|
20
|
+
* - launchCamera(options) -- photo capture
|
|
21
|
+
* - launchImageLibrary(options) -- photo picker
|
|
22
|
+
* - captureVideo(options) -- video capture with options: quality, maxDuration, frontCamera
|
|
23
|
+
* - scanQRCode() -- start QR code scanning, emits camera:qrDetected events
|
|
24
|
+
* - stopQRScan() -- stop QR code scanning
|
|
25
|
+
*/
|
|
26
|
+
class CameraModule : NativeModule {
|
|
27
|
+
override val moduleName = "Camera"
|
|
28
|
+
private var bridge: NativeBridge? = null
|
|
29
|
+
|
|
30
|
+
override fun initialize(context: Context, bridge: NativeBridge) {
|
|
31
|
+
this.bridge = bridge
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override fun invoke(
|
|
35
|
+
method: String,
|
|
36
|
+
args: List<Any?>,
|
|
37
|
+
bridge: NativeBridge,
|
|
38
|
+
callback: (Any?, String?) -> Unit
|
|
39
|
+
) {
|
|
40
|
+
when (method) {
|
|
41
|
+
"launchCamera", "launchImageLibrary", "captureVideo" -> {
|
|
42
|
+
callback(
|
|
43
|
+
null,
|
|
44
|
+
"Camera.$method requires Activity integration. " +
|
|
45
|
+
"Register a CameraModule subclass with your VueNativeActivity that " +
|
|
46
|
+
"implements $method via registerForActivityResult."
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
"scanQRCode" -> {
|
|
50
|
+
callback(
|
|
51
|
+
null,
|
|
52
|
+
"Camera.scanQRCode requires Activity integration and ML Kit dependency. " +
|
|
53
|
+
"Add com.google.mlkit:barcode-scanning to your app's build.gradle and " +
|
|
54
|
+
"register a CameraModule subclass that implements QR scanning."
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
"stopQRScan" -> {
|
|
58
|
+
// No-op in stub
|
|
59
|
+
callback(null, null)
|
|
60
|
+
}
|
|
61
|
+
else -> callback(null, "Unknown Camera method: $method")
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ClipboardModule.kt
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.vuenative.core
|
|
2
|
+
|
|
3
|
+
import android.content.ClipData
|
|
4
|
+
import android.content.ClipboardManager
|
|
5
|
+
import android.content.Context
|
|
6
|
+
|
|
7
|
+
class ClipboardModule : NativeModule {
|
|
8
|
+
override val moduleName = "Clipboard"
|
|
9
|
+
private var clipboard: ClipboardManager? = null
|
|
10
|
+
|
|
11
|
+
override fun initialize(context: Context, bridge: NativeBridge) {
|
|
12
|
+
clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
|
|
16
|
+
val cb = clipboard ?: run { callback(null, "Clipboard not available"); return }
|
|
17
|
+
when (method) {
|
|
18
|
+
"setString", "setContent" -> {
|
|
19
|
+
val text = args.getOrNull(0)?.toString() ?: ""
|
|
20
|
+
cb.setPrimaryClip(ClipData.newPlainText("VueNative", text))
|
|
21
|
+
callback(null, null)
|
|
22
|
+
}
|
|
23
|
+
"getString", "getContent" -> {
|
|
24
|
+
val clip = cb.primaryClip
|
|
25
|
+
val text = if (clip != null && clip.itemCount > 0) {
|
|
26
|
+
clip.getItemAt(0)?.text?.toString()
|
|
27
|
+
} else null
|
|
28
|
+
callback(text, null)
|
|
29
|
+
}
|
|
30
|
+
"hasString" -> {
|
|
31
|
+
callback(cb.hasPrimaryClip(), null)
|
|
32
|
+
}
|
|
33
|
+
else -> callback(null, "Unknown method: $method")
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|