@thelacanians/vue-native-cli 0.4.2 → 0.4.4

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.
Files changed (172) hide show
  1. package/dist/cli.js +43 -23
  2. package/native/android/README.md +205 -0
  3. package/native/android/VueNativeCore/build.gradle.kts +100 -0
  4. package/native/android/VueNativeCore/consumer-rules.pro +12 -0
  5. package/native/android/VueNativeCore/proguard-rules.pro +33 -0
  6. package/native/android/VueNativeCore/src/main/AndroidManifest.xml +17 -0
  7. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/ErrorOverlayView.kt +94 -0
  8. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/HotReloadManager.kt +105 -0
  9. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSPolyfills.kt +652 -0
  10. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSRuntime.kt +207 -0
  11. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +417 -0
  12. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/ComponentRegistry.kt +76 -0
  13. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActionSheetFactory.kt +78 -0
  14. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActivityIndicatorFactory.kt +46 -0
  15. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VAlertDialogFactory.kt +84 -0
  16. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VButtonFactory.kt +73 -0
  17. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VCheckboxFactory.kt +93 -0
  18. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VDropdownFactory.kt +125 -0
  19. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VImageFactory.kt +75 -0
  20. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VInputFactory.kt +210 -0
  21. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VKeyboardAvoidingFactory.kt +31 -0
  22. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +183 -0
  23. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VModalFactory.kt +105 -0
  24. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPickerFactory.kt +57 -0
  25. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPressableFactory.kt +109 -0
  26. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VProgressBarFactory.kt +43 -0
  27. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRadioFactory.kt +103 -0
  28. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRefreshControlFactory.kt +73 -0
  29. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRootFactory.kt +39 -0
  30. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSafeAreaFactory.kt +48 -0
  31. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +105 -0
  32. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSectionListFactory.kt +144 -0
  33. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSegmentedControlFactory.kt +77 -0
  34. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSliderFactory.kt +74 -0
  35. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VStatusBarFactory.kt +52 -0
  36. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSwitchFactory.kt +62 -0
  37. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VTextFactory.kt +53 -0
  38. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VVideoFactory.kt +191 -0
  39. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +48 -0
  40. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VWebViewFactory.kt +90 -0
  41. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/NativeComponentFactory.kt +40 -0
  42. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/VTextNodeView.kt +23 -0
  43. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/GestureHelper.kt +16 -0
  44. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/TouchableView.kt +105 -0
  45. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AnimationModule.kt +292 -0
  46. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AppStateModule.kt +41 -0
  47. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AsyncStorageModule.kt +59 -0
  48. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AudioModule.kt +331 -0
  49. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BackgroundTaskModule.kt +166 -0
  50. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BiometryModule.kt +56 -0
  51. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BluetoothModule.kt +302 -0
  52. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CalendarModule.kt +198 -0
  53. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CameraModule.kt +64 -0
  54. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ClipboardModule.kt +36 -0
  55. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ContactsModule.kt +288 -0
  56. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DatabaseModule.kt +229 -0
  57. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DeviceInfoModule.kt +39 -0
  58. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/FileSystemModule.kt +193 -0
  59. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeolocationModule.kt +68 -0
  60. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HapticsModule.kt +61 -0
  61. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HttpModule.kt +111 -0
  62. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/IAPModule.kt +302 -0
  63. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/KeyboardModule.kt +26 -0
  64. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/LinkingModule.kt +43 -0
  65. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModule.kt +27 -0
  66. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +92 -0
  67. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NetworkModule.kt +75 -0
  68. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NotificationsModule.kt +181 -0
  69. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/OTAModule.kt +255 -0
  70. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PerformanceModule.kt +147 -0
  71. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PermissionsModule.kt +126 -0
  72. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SecureStorageModule.kt +51 -0
  73. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SensorsModule.kt +134 -0
  74. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ShareModule.kt +36 -0
  75. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SocialAuthModule.kt +160 -0
  76. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/WebSocketModule.kt +155 -0
  77. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Styling/StyleEngine.kt +802 -0
  78. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Tags.kt +43 -0
  79. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/VueNativeActivity.kt +169 -0
  80. package/native/android/VueNativeCore/src/main/res/values/ids.xml +8 -0
  81. package/native/android/app/build.gradle.kts +45 -0
  82. package/native/android/app/proguard-rules.pro +5 -0
  83. package/native/android/app/src/main/AndroidManifest.xml +25 -0
  84. package/native/android/app/src/main/assets/.gitkeep +0 -0
  85. package/native/android/app/src/main/kotlin/com/vuenative/example/counter/MainActivity.kt +14 -0
  86. package/native/android/app/src/main/res/layout/activity_main.xml +6 -0
  87. package/native/android/app/src/main/res/values/strings.xml +3 -0
  88. package/native/android/app/src/main/res/values/themes.xml +9 -0
  89. package/native/android/app/src/main/res/xml/network_security_config.xml +8 -0
  90. package/native/android/build.gradle.kts +6 -0
  91. package/native/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  92. package/native/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  93. package/native/android/gradle.properties +4 -0
  94. package/native/android/gradlew +87 -0
  95. package/native/android/gradlew.bat +48 -0
  96. package/native/android/settings.gradle.kts +20 -0
  97. package/native/ios/VueNativeCore/Package.resolved +23 -0
  98. package/native/ios/VueNativeCore/Package.swift +32 -0
  99. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/CertificatePinning.swift +132 -0
  100. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/ErrorOverlayView.swift +92 -0
  101. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/HotReloadManager.swift +147 -0
  102. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSPolyfills.swift +711 -0
  103. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSRuntime.swift +421 -0
  104. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +891 -0
  105. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/VueNativeViewController.swift +88 -0
  106. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/ComponentRegistry.swift +193 -0
  107. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActionSheetFactory.swift +91 -0
  108. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActivityIndicatorFactory.swift +74 -0
  109. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VAlertDialogFactory.swift +150 -0
  110. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VButtonFactory.swift +93 -0
  111. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VCheckboxFactory.swift +114 -0
  112. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VDropdownFactory.swift +112 -0
  113. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VImageFactory.swift +172 -0
  114. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VInputFactory.swift +357 -0
  115. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VKeyboardAvoidingFactory.swift +99 -0
  116. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VListFactory.swift +250 -0
  117. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VModalFactory.swift +112 -0
  118. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPickerFactory.swift +96 -0
  119. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPressableFactory.swift +168 -0
  120. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VProgressBarFactory.swift +39 -0
  121. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRadioFactory.swift +167 -0
  122. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRefreshControlFactory.swift +153 -0
  123. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSafeAreaFactory.swift +56 -0
  124. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VScrollViewFactory.swift +240 -0
  125. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSectionListFactory.swift +248 -0
  126. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSegmentedControlFactory.swift +73 -0
  127. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSliderFactory.swift +63 -0
  128. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VStatusBarFactory.swift +50 -0
  129. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSwitchFactory.swift +108 -0
  130. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +290 -0
  131. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VVideoFactory.swift +246 -0
  132. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +157 -0
  133. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VWebViewFactory.swift +172 -0
  134. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/NativeComponentFactory.swift +53 -0
  135. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +107 -0
  136. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/TouchableView.swift +136 -0
  137. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/UIColor+Hex.swift +80 -0
  138. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AnimationModule.swift +291 -0
  139. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AppStateModule.swift +65 -0
  140. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AsyncStorageModule.swift +68 -0
  141. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AudioModule.swift +366 -0
  142. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BackgroundTaskModule.swift +135 -0
  143. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BiometryModule.swift +61 -0
  144. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BluetoothModule.swift +387 -0
  145. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CalendarModule.swift +161 -0
  146. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CameraModule.swift +318 -0
  147. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ClipboardModule.swift +33 -0
  148. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ContactsModule.swift +173 -0
  149. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DatabaseModule.swift +259 -0
  150. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DeviceInfoModule.swift +34 -0
  151. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/FileSystemModule.swift +233 -0
  152. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeolocationModule.swift +147 -0
  153. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/HapticsModule.swift +50 -0
  154. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/IAPModule.swift +194 -0
  155. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/KeyboardModule.swift +31 -0
  156. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/LinkingModule.swift +42 -0
  157. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModule.swift +28 -0
  158. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +78 -0
  159. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NetworkModule.swift +62 -0
  160. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NotificationsModule.swift +215 -0
  161. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/OTAModule.swift +281 -0
  162. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PerformanceModule.swift +138 -0
  163. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PermissionsModule.swift +190 -0
  164. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SecureStorageModule.swift +118 -0
  165. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SensorsModule.swift +103 -0
  166. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ShareModule.swift +49 -0
  167. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SocialAuthModule.swift +240 -0
  168. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/WebSocketModule.swift +213 -0
  169. package/native/ios/VueNativeCore/Sources/VueNativeCore/Resources/vue-native-placeholder.js +8 -0
  170. package/native/ios/VueNativeCore/Sources/VueNativeCore/Styling/StyleEngine.swift +885 -0
  171. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSRuntimeTests.swift +362 -0
  172. package/package.json +3 -2
@@ -0,0 +1,331 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.media.MediaPlayer
5
+ import android.media.MediaRecorder
6
+ import android.os.Build
7
+ import android.os.Handler
8
+ import android.os.Looper
9
+ import java.io.File
10
+ import java.util.UUID
11
+
12
+ /**
13
+ * AudioModule — backs the useAudio() composable.
14
+ *
15
+ * Playback: MediaPlayer (play, pause, resume, stop, seek, setVolume)
16
+ * Recording: MediaRecorder (startRecording, stopRecording, pauseRecording, resumeRecording)
17
+ * Events: audio:progress, audio:complete, audio:error
18
+ */
19
+ class AudioModule : NativeModule {
20
+ override val moduleName = "Audio"
21
+
22
+ private var player: MediaPlayer? = null
23
+ private var recorder: MediaRecorder? = null
24
+ private var recordingPath: String? = null
25
+ private var bridge: NativeBridge? = null
26
+ private var context: Context? = null
27
+ private var isPlaying = false
28
+
29
+ private val handler = Handler(Looper.getMainLooper())
30
+ private var progressRunnable: Runnable? = null
31
+
32
+ override fun initialize(context: Context, bridge: NativeBridge) {
33
+ this.context = context
34
+ this.bridge = bridge
35
+ }
36
+
37
+ override fun invoke(
38
+ method: String,
39
+ args: List<Any?>,
40
+ bridge: NativeBridge,
41
+ callback: (Any?, String?) -> Unit
42
+ ) {
43
+ when (method) {
44
+ "play" -> {
45
+ val uri = args.getOrNull(0)?.toString() ?: ""
46
+ @Suppress("UNCHECKED_CAST")
47
+ val options = (args.getOrNull(1) as? Map<String, Any?>) ?: emptyMap()
48
+ play(uri, options, callback)
49
+ }
50
+ "pause" -> pause(callback)
51
+ "resume" -> resume(callback)
52
+ "stop" -> stop(callback)
53
+ "seek" -> {
54
+ val position = when (val v = args.getOrNull(0)) {
55
+ is Number -> v.toDouble()
56
+ else -> 0.0
57
+ }
58
+ seek(position, callback)
59
+ }
60
+ "setVolume" -> {
61
+ val volume = when (val v = args.getOrNull(0)) {
62
+ is Number -> v.toFloat()
63
+ else -> 1.0f
64
+ }
65
+ setVolume(volume, callback)
66
+ }
67
+ "startRecording" -> {
68
+ @Suppress("UNCHECKED_CAST")
69
+ val options = (args.getOrNull(0) as? Map<String, Any?>) ?: emptyMap()
70
+ startRecording(options, callback)
71
+ }
72
+ "stopRecording" -> stopRecording(callback)
73
+ "pauseRecording" -> pauseRecording(callback)
74
+ "resumeRecording" -> resumeRecording(callback)
75
+ "getStatus" -> getStatus(callback)
76
+ else -> callback(null, "AudioModule: Unknown method '$method'")
77
+ }
78
+ }
79
+
80
+ // MARK: - Playback
81
+
82
+ private fun play(uri: String, options: Map<String, Any?>, callback: (Any?, String?) -> Unit) {
83
+ handler.post {
84
+ try {
85
+ stopProgressReporting()
86
+ player?.release()
87
+ player = null
88
+
89
+ val mp = MediaPlayer()
90
+ mp.setDataSource(uri)
91
+
92
+ val volume = (options["volume"] as? Number)?.toFloat() ?: 1.0f
93
+ val loop = options["loop"] as? Boolean ?: false
94
+
95
+ mp.setVolume(volume, volume)
96
+ mp.isLooping = loop
97
+
98
+ mp.setOnPreparedListener {
99
+ it.start()
100
+ isPlaying = true
101
+ startProgressReporting()
102
+ callback(mapOf(
103
+ "duration" to it.duration.toDouble() / 1000.0,
104
+ "currentTime" to 0.0
105
+ ), null)
106
+ }
107
+
108
+ mp.setOnCompletionListener {
109
+ isPlaying = false
110
+ stopProgressReporting()
111
+ bridge?.sendGlobalEvent("audio:complete", emptyMap())
112
+ }
113
+
114
+ mp.setOnErrorListener { _, what, extra ->
115
+ isPlaying = false
116
+ stopProgressReporting()
117
+ val msg = "MediaPlayer error: what=$what extra=$extra"
118
+ bridge?.sendGlobalEvent("audio:error", mapOf("message" to msg))
119
+ true
120
+ }
121
+
122
+ player = mp
123
+ mp.prepareAsync()
124
+ } catch (e: Exception) {
125
+ callback(null, "Failed to play audio: ${e.message}")
126
+ }
127
+ }
128
+ }
129
+
130
+ private fun pause(callback: (Any?, String?) -> Unit) {
131
+ handler.post {
132
+ player?.pause()
133
+ isPlaying = false
134
+ stopProgressReporting()
135
+ callback(null, null)
136
+ }
137
+ }
138
+
139
+ private fun resume(callback: (Any?, String?) -> Unit) {
140
+ handler.post {
141
+ player?.start()
142
+ isPlaying = true
143
+ startProgressReporting()
144
+ callback(null, null)
145
+ }
146
+ }
147
+
148
+ private fun stop(callback: (Any?, String?) -> Unit) {
149
+ handler.post {
150
+ stopProgressReporting()
151
+ player?.release()
152
+ player = null
153
+ isPlaying = false
154
+ callback(null, null)
155
+ }
156
+ }
157
+
158
+ private fun seek(position: Double, callback: (Any?, String?) -> Unit) {
159
+ handler.post {
160
+ val ms = (position * 1000).toInt()
161
+ player?.seekTo(ms)
162
+ callback(null, null)
163
+ }
164
+ }
165
+
166
+ private fun setVolume(volume: Float, callback: (Any?, String?) -> Unit) {
167
+ handler.post {
168
+ val v = volume.coerceIn(0f, 1f)
169
+ player?.setVolume(v, v)
170
+ callback(null, null)
171
+ }
172
+ }
173
+
174
+ // MARK: - Progress Reporting
175
+
176
+ private fun startProgressReporting() {
177
+ stopProgressReporting()
178
+ val runnable = object : Runnable {
179
+ override fun run() {
180
+ val mp = player ?: return
181
+ if (isPlaying) {
182
+ bridge?.sendGlobalEvent("audio:progress", mapOf(
183
+ "currentTime" to mp.currentPosition.toDouble() / 1000.0,
184
+ "duration" to mp.duration.toDouble() / 1000.0
185
+ ))
186
+ handler.postDelayed(this, 250)
187
+ }
188
+ }
189
+ }
190
+ progressRunnable = runnable
191
+ handler.postDelayed(runnable, 250)
192
+ }
193
+
194
+ private fun stopProgressReporting() {
195
+ progressRunnable?.let { handler.removeCallbacks(it) }
196
+ progressRunnable = null
197
+ }
198
+
199
+ // MARK: - Recording
200
+
201
+ private fun startRecording(options: Map<String, Any?>, callback: (Any?, String?) -> Unit) {
202
+ handler.post {
203
+ try {
204
+ val ctx = context ?: run {
205
+ callback(null, "No context available")
206
+ return@post
207
+ }
208
+
209
+ val quality = options["quality"]?.toString() ?: "medium"
210
+ val format = options["format"]?.toString() ?: "m4a"
211
+
212
+ val ext = if (format == "wav") "wav" else "m4a"
213
+ val file = File(ctx.cacheDir, "${UUID.randomUUID()}.$ext")
214
+ recordingPath = file.absolutePath
215
+
216
+ val mr = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
217
+ MediaRecorder(ctx)
218
+ } else {
219
+ @Suppress("DEPRECATION")
220
+ MediaRecorder()
221
+ }
222
+
223
+ mr.setAudioSource(MediaRecorder.AudioSource.MIC)
224
+
225
+ if (format == "wav") {
226
+ // WAV not directly supported by MediaRecorder — use 3GPP as fallback
227
+ mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
228
+ mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
229
+ } else {
230
+ mr.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
231
+ mr.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
232
+ when (quality) {
233
+ "low" -> {
234
+ mr.setAudioSamplingRate(22050)
235
+ mr.setAudioEncodingBitRate(32000)
236
+ }
237
+ "high" -> {
238
+ mr.setAudioSamplingRate(44100)
239
+ mr.setAudioEncodingBitRate(128000)
240
+ }
241
+ else -> {
242
+ mr.setAudioSamplingRate(44100)
243
+ mr.setAudioEncodingBitRate(64000)
244
+ }
245
+ }
246
+ }
247
+
248
+ mr.setOutputFile(file.absolutePath)
249
+ mr.prepare()
250
+ mr.start()
251
+ recorder = mr
252
+
253
+ callback(mapOf("uri" to "file://${file.absolutePath}"), null)
254
+ } catch (e: Exception) {
255
+ callback(null, "Failed to start recording: ${e.message}")
256
+ }
257
+ }
258
+ }
259
+
260
+ private fun stopRecording(callback: (Any?, String?) -> Unit) {
261
+ handler.post {
262
+ val mr = recorder
263
+ val path = recordingPath
264
+ if (mr == null || path == null) {
265
+ callback(null, "No active recording")
266
+ return@post
267
+ }
268
+ try {
269
+ mr.stop()
270
+ mr.release()
271
+ recorder = null
272
+
273
+ // Get duration by briefly opening the file with MediaPlayer
274
+ val mp = MediaPlayer()
275
+ mp.setDataSource(path)
276
+ mp.prepare()
277
+ val duration = mp.duration.toDouble() / 1000.0
278
+ mp.release()
279
+
280
+ callback(mapOf(
281
+ "uri" to "file://$path",
282
+ "duration" to duration
283
+ ), null)
284
+ } catch (e: Exception) {
285
+ callback(null, "Failed to stop recording: ${e.message}")
286
+ }
287
+ }
288
+ }
289
+
290
+ private fun pauseRecording(callback: (Any?, String?) -> Unit) {
291
+ handler.post {
292
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
293
+ recorder?.pause()
294
+ }
295
+ callback(null, null)
296
+ }
297
+ }
298
+
299
+ private fun resumeRecording(callback: (Any?, String?) -> Unit) {
300
+ handler.post {
301
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
302
+ recorder?.resume()
303
+ }
304
+ callback(null, null)
305
+ }
306
+ }
307
+
308
+ // MARK: - Status
309
+
310
+ private fun getStatus(callback: (Any?, String?) -> Unit) {
311
+ handler.post {
312
+ val status = mutableMapOf<String, Any>(
313
+ "isPlaying" to isPlaying,
314
+ "isRecording" to (recorder != null)
315
+ )
316
+ player?.let {
317
+ status["currentTime"] = it.currentPosition.toDouble() / 1000.0
318
+ status["duration"] = it.duration.toDouble() / 1000.0
319
+ }
320
+ callback(status, null)
321
+ }
322
+ }
323
+
324
+ override fun destroy() {
325
+ stopProgressReporting()
326
+ player?.release()
327
+ player = null
328
+ recorder?.release()
329
+ recorder = null
330
+ }
331
+ }
@@ -0,0 +1,166 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import androidx.work.*
6
+ import java.util.concurrent.TimeUnit
7
+
8
+ /**
9
+ * Native module for scheduling background tasks using WorkManager.
10
+ *
11
+ * Methods:
12
+ * - scheduleTask(taskId, type, options) — schedule a one-time or periodic task
13
+ * - cancelTask(taskId) — cancel a specific task
14
+ * - cancelAllTasks() — cancel all scheduled tasks
15
+ * - completeTask(taskId) — no-op on Android (Worker handles completion)
16
+ * - registerTask(taskId) — no-op on Android (registration is automatic)
17
+ *
18
+ * Events:
19
+ * - background:taskExecute — fired when a background task runs, payload: { taskId }
20
+ */
21
+ class BackgroundTaskModule : NativeModule {
22
+ override val moduleName = "BackgroundTask"
23
+ private var appContext: Context? = null
24
+ private var bridgeRef: NativeBridge? = null
25
+
26
+ override fun initialize(context: Context, bridge: NativeBridge) {
27
+ appContext = context.applicationContext
28
+ bridgeRef = bridge
29
+ // Store bridge reference for the worker
30
+ VueNativeWorker.bridgeRef = bridge
31
+ }
32
+
33
+ override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
34
+ val ctx = appContext ?: run { callback(null, "BackgroundTask not initialized"); return }
35
+
36
+ when (method) {
37
+ "scheduleTask" -> {
38
+ val taskId = args.getOrNull(0)?.toString()
39
+ ?: run { callback(null, "scheduleTask: missing taskId"); return }
40
+ val type = args.getOrNull(1)?.toString() ?: "refresh"
41
+ val options = args.getOrNull(2) as? Map<*, *> ?: emptyMap<String, Any>()
42
+ scheduleTask(ctx, taskId, type, options, callback)
43
+ }
44
+ "cancelTask" -> {
45
+ val taskId = args.getOrNull(0)?.toString()
46
+ ?: run { callback(null, "cancelTask: missing taskId"); return }
47
+ WorkManager.getInstance(ctx).cancelUniqueWork(taskId)
48
+ callback(null, null)
49
+ }
50
+ "cancelAllTasks" -> {
51
+ WorkManager.getInstance(ctx).cancelAllWork()
52
+ callback(null, null)
53
+ }
54
+ "completeTask" -> {
55
+ // On Android, WorkManager Workers handle their own completion
56
+ callback(null, null)
57
+ }
58
+ "registerTask" -> {
59
+ // No-op on Android — registration happens at schedule time
60
+ callback(null, null)
61
+ }
62
+ else -> callback(null, "BackgroundTaskModule: Unknown method '$method'")
63
+ }
64
+ }
65
+
66
+ private fun scheduleTask(
67
+ ctx: Context,
68
+ taskId: String,
69
+ type: String,
70
+ options: Map<*, *>,
71
+ callback: (Any?, String?) -> Unit
72
+ ) {
73
+ try {
74
+ val constraintsBuilder = Constraints.Builder()
75
+
76
+ val requiresNetwork = options["requiresNetworkConnectivity"] as? Boolean ?: false
77
+ if (requiresNetwork) {
78
+ constraintsBuilder.setRequiredNetworkType(NetworkType.CONNECTED)
79
+ }
80
+
81
+ val requiresCharging = options["requiresExternalPower"] as? Boolean ?: false
82
+ if (requiresCharging) {
83
+ constraintsBuilder.setRequiresCharging(true)
84
+ }
85
+
86
+ val constraints = constraintsBuilder.build()
87
+
88
+ val inputData = Data.Builder()
89
+ .putString("taskId", taskId)
90
+ .build()
91
+
92
+ if (type == "processing") {
93
+ // Periodic work for long-running/processing tasks
94
+ val intervalMinutes = (options["interval"] as? Number)?.toLong() ?: 15L
95
+ val request = PeriodicWorkRequestBuilder<VueNativeWorker>(
96
+ intervalMinutes, TimeUnit.MINUTES
97
+ )
98
+ .setConstraints(constraints)
99
+ .setInputData(inputData)
100
+ .addTag("vue-native-bg-$taskId")
101
+ .build()
102
+
103
+ WorkManager.getInstance(ctx).enqueueUniquePeriodicWork(
104
+ taskId,
105
+ ExistingPeriodicWorkPolicy.REPLACE,
106
+ request
107
+ )
108
+ } else {
109
+ // One-time work for refresh tasks
110
+ val requestBuilder = OneTimeWorkRequestBuilder<VueNativeWorker>()
111
+ .setConstraints(constraints)
112
+ .setInputData(inputData)
113
+ .addTag("vue-native-bg-$taskId")
114
+
115
+ val delayMs = (options["earliestBeginDate"] as? Number)?.toLong()
116
+ if (delayMs != null) {
117
+ val now = System.currentTimeMillis()
118
+ val delay = delayMs - now
119
+ if (delay > 0) {
120
+ requestBuilder.setInitialDelay(delay, TimeUnit.MILLISECONDS)
121
+ }
122
+ }
123
+
124
+ WorkManager.getInstance(ctx).enqueueUniqueWork(
125
+ taskId,
126
+ ExistingWorkPolicy.REPLACE,
127
+ requestBuilder.build()
128
+ )
129
+ }
130
+
131
+ callback(null, null)
132
+ } catch (e: Exception) {
133
+ callback(null, "Failed to schedule task: ${e.message}")
134
+ }
135
+ }
136
+
137
+ override fun destroy() {
138
+ VueNativeWorker.bridgeRef = null
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Worker that fires background:taskExecute events back to the JS bridge.
144
+ */
145
+ class VueNativeWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
146
+ companion object {
147
+ @Volatile
148
+ var bridgeRef: NativeBridge? = null
149
+ }
150
+
151
+ override fun doWork(): Result {
152
+ val taskId = inputData.getString("taskId") ?: return Result.failure()
153
+
154
+ try {
155
+ bridgeRef?.dispatchGlobalEvent(
156
+ "background:taskExecute",
157
+ mapOf("taskId" to taskId)
158
+ )
159
+ } catch (e: Exception) {
160
+ Log.e("VueNative", "BackgroundTask execution failed", e)
161
+ return Result.failure()
162
+ }
163
+
164
+ return Result.success()
165
+ }
166
+ }
@@ -0,0 +1,56 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import androidx.biometric.BiometricManager
5
+
6
+ /**
7
+ * BiometryModule — backs the useBiometry() composable.
8
+ *
9
+ * Full biometric prompt (authenticate) requires an Activity/Fragment context
10
+ * and a BiometricPrompt instance. The authenticate() method here returns an
11
+ * informative error so developers know to wire it up in a screen component.
12
+ * getSupportedBiometry() works without UI.
13
+ */
14
+ class BiometryModule : NativeModule {
15
+ override val moduleName = "Biometry"
16
+ private var context: Context? = null
17
+
18
+ override fun initialize(context: Context, bridge: NativeBridge) {
19
+ this.context = context
20
+ }
21
+
22
+ override fun invoke(
23
+ method: String,
24
+ args: List<Any?>,
25
+ bridge: NativeBridge,
26
+ callback: (Any?, String?) -> Unit
27
+ ) {
28
+ when (method) {
29
+ "getSupportedBiometry" -> {
30
+ val ctx = context ?: run { callback("none", null); return }
31
+ val biometricManager = BiometricManager.from(ctx)
32
+ val result = when (biometricManager.canAuthenticate(
33
+ BiometricManager.Authenticators.BIOMETRIC_STRONG
34
+ )) {
35
+ BiometricManager.BIOMETRIC_SUCCESS -> "faceID" // Android doesn't distinguish
36
+ BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> "none"
37
+ BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> "none"
38
+ BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> "biometric" // HW present, not enrolled
39
+ else -> "none"
40
+ }
41
+ callback(result, null)
42
+ }
43
+ "authenticate" -> {
44
+ // BiometricPrompt requires a FragmentActivity reference.
45
+ // To use biometry in a screen component, call bridge.invokeNativeModule
46
+ // from an Activity subclass that overrides authenticate() via BiometricPrompt.
47
+ callback(
48
+ null,
49
+ "Biometry.authenticate requires Activity context. " +
50
+ "Override VueNativeActivity.onAuthenticateRequest() to provide BiometricPrompt."
51
+ )
52
+ }
53
+ else -> callback(null, "Unknown method: $method")
54
+ }
55
+ }
56
+ }