@thelacanians/vue-native-cli 0.4.3 → 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.
- package/dist/cli.js +34 -17
- package/native/android/README.md +205 -0
- package/native/android/VueNativeCore/build.gradle.kts +100 -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 +160 -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 +132 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/ErrorOverlayView.swift +92 -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 +891 -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 +91 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActivityIndicatorFactory.swift +74 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VAlertDialogFactory.swift +150 -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 +112 -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 +246 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +157 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VWebViewFactory.swift +172 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/NativeComponentFactory.swift +53 -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 +291 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AppStateModule.swift +65 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AsyncStorageModule.swift +68 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AudioModule.swift +366 -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 +387 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CalendarModule.swift +161 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CameraModule.swift +318 -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 +138 -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 +49 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SocialAuthModule.swift +240 -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
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#if canImport(UIKit)
|
|
2
|
+
import UIKit
|
|
3
|
+
import AVFoundation
|
|
4
|
+
import Photos
|
|
5
|
+
import CoreLocation
|
|
6
|
+
import UserNotifications
|
|
7
|
+
|
|
8
|
+
/// Native module for checking and requesting system permissions.
|
|
9
|
+
///
|
|
10
|
+
/// Supported permissions: "camera", "microphone", "photos", "location",
|
|
11
|
+
/// "locationAlways", "notifications"
|
|
12
|
+
///
|
|
13
|
+
/// Status strings: "granted", "denied", "restricted", "limited", "notDetermined"
|
|
14
|
+
final class PermissionsModule: NativeModule {
|
|
15
|
+
var moduleName: String { "Permissions" }
|
|
16
|
+
|
|
17
|
+
func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
18
|
+
switch method {
|
|
19
|
+
case "check":
|
|
20
|
+
guard let permission = args.first as? String else {
|
|
21
|
+
callback(nil, "PermissionsModule: missing permission name"); return
|
|
22
|
+
}
|
|
23
|
+
checkPermission(permission, callback: callback)
|
|
24
|
+
case "request":
|
|
25
|
+
guard let permission = args.first as? String else {
|
|
26
|
+
callback(nil, "PermissionsModule: missing permission name"); return
|
|
27
|
+
}
|
|
28
|
+
requestPermission(permission, callback: callback)
|
|
29
|
+
default:
|
|
30
|
+
callback(nil, "PermissionsModule: Unknown method '\(method)'")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// MARK: - Check
|
|
35
|
+
|
|
36
|
+
private func checkPermission(_ permission: String, callback: @escaping (Any?, String?) -> Void) {
|
|
37
|
+
switch permission {
|
|
38
|
+
case "camera":
|
|
39
|
+
callback(statusString(avStatus: AVCaptureDevice.authorizationStatus(for: .video)), nil)
|
|
40
|
+
case "microphone":
|
|
41
|
+
callback(statusString(avStatus: AVCaptureDevice.authorizationStatus(for: .audio)), nil)
|
|
42
|
+
case "photos":
|
|
43
|
+
callback(statusString(photoStatus: PHPhotoLibrary.authorizationStatus(for: .readWrite)), nil)
|
|
44
|
+
case "location", "locationAlways":
|
|
45
|
+
// CLLocationManager.authorizationStatus() instance method must be called on main thread.
|
|
46
|
+
DispatchQueue.main.async {
|
|
47
|
+
let mgr = CLLocationManager()
|
|
48
|
+
callback(self.statusString(locationStatus: mgr.authorizationStatus), nil)
|
|
49
|
+
}
|
|
50
|
+
case "notifications":
|
|
51
|
+
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
|
52
|
+
callback(self.statusString(notifStatus: settings.authorizationStatus), nil)
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
callback("notDetermined", nil)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// MARK: - Request
|
|
60
|
+
|
|
61
|
+
private func requestPermission(_ permission: String, callback: @escaping (Any?, String?) -> Void) {
|
|
62
|
+
switch permission {
|
|
63
|
+
case "camera":
|
|
64
|
+
AVCaptureDevice.requestAccess(for: .video) { granted in
|
|
65
|
+
callback(granted ? "granted" : "denied", nil)
|
|
66
|
+
}
|
|
67
|
+
case "microphone":
|
|
68
|
+
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
|
69
|
+
callback(granted ? "granted" : "denied", nil)
|
|
70
|
+
}
|
|
71
|
+
case "photos":
|
|
72
|
+
PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
|
|
73
|
+
callback(self.statusString(photoStatus: status), nil)
|
|
74
|
+
}
|
|
75
|
+
case "location":
|
|
76
|
+
// LocationPermissionRequester is @MainActor — must dispatch to main.
|
|
77
|
+
DispatchQueue.main.async {
|
|
78
|
+
LocationPermissionRequester.shared.request(always: false, callback: callback)
|
|
79
|
+
}
|
|
80
|
+
case "locationAlways":
|
|
81
|
+
DispatchQueue.main.async {
|
|
82
|
+
LocationPermissionRequester.shared.request(always: true, callback: callback)
|
|
83
|
+
}
|
|
84
|
+
case "notifications":
|
|
85
|
+
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
|
|
86
|
+
callback(granted ? "granted" : "denied", nil)
|
|
87
|
+
}
|
|
88
|
+
default:
|
|
89
|
+
callback("notDetermined", nil)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// MARK: - Status helpers
|
|
94
|
+
|
|
95
|
+
private func statusString(avStatus: AVAuthorizationStatus) -> String {
|
|
96
|
+
switch avStatus {
|
|
97
|
+
case .authorized: return "granted"
|
|
98
|
+
case .denied: return "denied"
|
|
99
|
+
case .restricted: return "restricted"
|
|
100
|
+
case .notDetermined: return "notDetermined"
|
|
101
|
+
@unknown default: return "notDetermined"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private func statusString(photoStatus: PHAuthorizationStatus) -> String {
|
|
106
|
+
switch photoStatus {
|
|
107
|
+
case .authorized: return "granted"
|
|
108
|
+
case .denied: return "denied"
|
|
109
|
+
case .restricted: return "restricted"
|
|
110
|
+
case .notDetermined: return "notDetermined"
|
|
111
|
+
case .limited: return "limited"
|
|
112
|
+
@unknown default: return "notDetermined"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private func statusString(locationStatus: CLAuthorizationStatus) -> String {
|
|
117
|
+
switch locationStatus {
|
|
118
|
+
case .authorizedWhenInUse, .authorizedAlways: return "granted"
|
|
119
|
+
case .denied: return "denied"
|
|
120
|
+
case .restricted: return "restricted"
|
|
121
|
+
case .notDetermined: return "notDetermined"
|
|
122
|
+
@unknown default: return "notDetermined"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private func statusString(notifStatus: UNAuthorizationStatus) -> String {
|
|
127
|
+
switch notifStatus {
|
|
128
|
+
case .authorized, .provisional, .ephemeral: return "granted"
|
|
129
|
+
case .denied: return "denied"
|
|
130
|
+
case .notDetermined: return "notDetermined"
|
|
131
|
+
@unknown default: return "notDetermined"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func invokeSync(method: String, args: [Any]) -> Any? { nil }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// MARK: - Location permission helper
|
|
139
|
+
|
|
140
|
+
/// CLLocationManager must be created and used on the main thread.
|
|
141
|
+
/// This helper lives on @MainActor and drives the one-shot request flow.
|
|
142
|
+
@MainActor
|
|
143
|
+
private final class LocationPermissionRequester: NSObject, CLLocationManagerDelegate {
|
|
144
|
+
static let shared = LocationPermissionRequester()
|
|
145
|
+
|
|
146
|
+
private var manager: CLLocationManager?
|
|
147
|
+
private var pendingCallback: ((Any?, String?) -> Void)?
|
|
148
|
+
|
|
149
|
+
func request(always: Bool, callback: @escaping (Any?, String?) -> Void) {
|
|
150
|
+
// If already determined, return immediately without showing the system dialog.
|
|
151
|
+
let probe = CLLocationManager()
|
|
152
|
+
let current = probe.authorizationStatus
|
|
153
|
+
if current != .notDetermined {
|
|
154
|
+
callback(statusString(current), nil)
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
pendingCallback = callback
|
|
158
|
+
let mgr = CLLocationManager()
|
|
159
|
+
mgr.delegate = self
|
|
160
|
+
manager = mgr
|
|
161
|
+
if always {
|
|
162
|
+
mgr.requestAlwaysAuthorization()
|
|
163
|
+
} else {
|
|
164
|
+
mgr.requestWhenInUseAuthorization()
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private func statusString(_ status: CLAuthorizationStatus) -> String {
|
|
169
|
+
switch status {
|
|
170
|
+
case .authorizedWhenInUse, .authorizedAlways: return "granted"
|
|
171
|
+
case .denied: return "denied"
|
|
172
|
+
case .restricted: return "restricted"
|
|
173
|
+
case .notDetermined: return "notDetermined"
|
|
174
|
+
@unknown default: return "notDetermined"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// nonisolated because CLLocationManagerDelegate methods arrive on arbitrary threads;
|
|
179
|
+
// we hop back to @MainActor via Task for state access.
|
|
180
|
+
nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
181
|
+
Task { @MainActor in
|
|
182
|
+
let status = manager.authorizationStatus
|
|
183
|
+
guard let cb = self.pendingCallback else { return }
|
|
184
|
+
self.pendingCallback = nil
|
|
185
|
+
self.manager = nil
|
|
186
|
+
cb(self.statusString(status), nil)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
#endif
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#if canImport(UIKit)
|
|
2
|
+
import Foundation
|
|
3
|
+
import Security
|
|
4
|
+
|
|
5
|
+
/// Native module providing secure key-value storage backed by iOS Keychain.
|
|
6
|
+
///
|
|
7
|
+
/// Methods:
|
|
8
|
+
/// - get(key: String) -> String?
|
|
9
|
+
/// - set(key: String, value: String)
|
|
10
|
+
/// - remove(key: String)
|
|
11
|
+
/// - clear()
|
|
12
|
+
final class SecureStorageModule: NativeModule {
|
|
13
|
+
let moduleName = "SecureStorage"
|
|
14
|
+
|
|
15
|
+
private let service = "com.vuenative.securestorage"
|
|
16
|
+
|
|
17
|
+
func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
18
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
19
|
+
guard let self = self else { return }
|
|
20
|
+
switch method {
|
|
21
|
+
case "get":
|
|
22
|
+
guard let key = args.first as? String else {
|
|
23
|
+
callback(nil, "get: missing key")
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
let query: [String: Any] = [
|
|
27
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
28
|
+
kSecAttrService as String: self.service,
|
|
29
|
+
kSecAttrAccount as String: key,
|
|
30
|
+
kSecReturnData as String: true,
|
|
31
|
+
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
32
|
+
]
|
|
33
|
+
var result: AnyObject?
|
|
34
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
35
|
+
if status == errSecSuccess, let data = result as? Data,
|
|
36
|
+
let value = String(data: data, encoding: .utf8) {
|
|
37
|
+
callback(value, nil)
|
|
38
|
+
} else if status == errSecItemNotFound {
|
|
39
|
+
callback(nil, nil)
|
|
40
|
+
} else {
|
|
41
|
+
callback(nil, "get: Keychain error \(status)")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
case "set":
|
|
45
|
+
guard args.count >= 2,
|
|
46
|
+
let key = args[0] as? String,
|
|
47
|
+
let value = args[1] as? String else {
|
|
48
|
+
callback(nil, "set: missing key or value")
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
guard let data = value.data(using: .utf8) else {
|
|
52
|
+
callback(nil, "set: failed to encode value")
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Try to update first
|
|
57
|
+
let searchQuery: [String: Any] = [
|
|
58
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
59
|
+
kSecAttrService as String: self.service,
|
|
60
|
+
kSecAttrAccount as String: key,
|
|
61
|
+
]
|
|
62
|
+
let updateAttributes: [String: Any] = [
|
|
63
|
+
kSecValueData as String: data,
|
|
64
|
+
]
|
|
65
|
+
let updateStatus = SecItemUpdate(searchQuery as CFDictionary, updateAttributes as CFDictionary)
|
|
66
|
+
|
|
67
|
+
if updateStatus == errSecItemNotFound {
|
|
68
|
+
// Item doesn't exist yet, add it
|
|
69
|
+
var addQuery = searchQuery
|
|
70
|
+
addQuery[kSecValueData as String] = data
|
|
71
|
+
let addStatus = SecItemAdd(addQuery as CFDictionary, nil)
|
|
72
|
+
if addStatus == errSecSuccess {
|
|
73
|
+
callback(nil, nil)
|
|
74
|
+
} else {
|
|
75
|
+
callback(nil, "set: Keychain add error \(addStatus)")
|
|
76
|
+
}
|
|
77
|
+
} else if updateStatus == errSecSuccess {
|
|
78
|
+
callback(nil, nil)
|
|
79
|
+
} else {
|
|
80
|
+
callback(nil, "set: Keychain update error \(updateStatus)")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
case "remove":
|
|
84
|
+
guard let key = args.first as? String else {
|
|
85
|
+
callback(nil, "remove: missing key")
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
let query: [String: Any] = [
|
|
89
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
90
|
+
kSecAttrService as String: self.service,
|
|
91
|
+
kSecAttrAccount as String: key,
|
|
92
|
+
]
|
|
93
|
+
let status = SecItemDelete(query as CFDictionary)
|
|
94
|
+
if status == errSecSuccess || status == errSecItemNotFound {
|
|
95
|
+
callback(nil, nil)
|
|
96
|
+
} else {
|
|
97
|
+
callback(nil, "remove: Keychain error \(status)")
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
case "clear":
|
|
101
|
+
let query: [String: Any] = [
|
|
102
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
103
|
+
kSecAttrService as String: self.service,
|
|
104
|
+
]
|
|
105
|
+
let status = SecItemDelete(query as CFDictionary)
|
|
106
|
+
if status == errSecSuccess || status == errSecItemNotFound {
|
|
107
|
+
callback(nil, nil)
|
|
108
|
+
} else {
|
|
109
|
+
callback(nil, "clear: Keychain error \(status)")
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
default:
|
|
113
|
+
callback(nil, "SecureStorageModule: Unknown method '\(method)'")
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
#endif
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#if canImport(UIKit)
|
|
2
|
+
import CoreMotion
|
|
3
|
+
import Foundation
|
|
4
|
+
|
|
5
|
+
/// Native module for accelerometer and gyroscope sensor data.
|
|
6
|
+
/// Dispatches continuous events via bridge.dispatchGlobalEvent.
|
|
7
|
+
final class SensorsModule: NativeModule {
|
|
8
|
+
let moduleName = "Sensors"
|
|
9
|
+
|
|
10
|
+
private let motionManager = CMMotionManager()
|
|
11
|
+
private weak var bridge: NativeBridge?
|
|
12
|
+
private let queue = OperationQueue()
|
|
13
|
+
|
|
14
|
+
init(bridge: NativeBridge) {
|
|
15
|
+
self.bridge = bridge
|
|
16
|
+
queue.name = "vue-native.sensors"
|
|
17
|
+
queue.maxConcurrentOperationCount = 1
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
21
|
+
switch method {
|
|
22
|
+
case "startAccelerometer":
|
|
23
|
+
let interval = (args.first as? Double ?? 100) / 1000.0
|
|
24
|
+
startAccelerometer(interval: interval, callback: callback)
|
|
25
|
+
case "stopAccelerometer":
|
|
26
|
+
stopAccelerometer(callback: callback)
|
|
27
|
+
case "startGyroscope":
|
|
28
|
+
let interval = (args.first as? Double ?? 100) / 1000.0
|
|
29
|
+
startGyroscope(interval: interval, callback: callback)
|
|
30
|
+
case "stopGyroscope":
|
|
31
|
+
stopGyroscope(callback: callback)
|
|
32
|
+
case "isAvailable":
|
|
33
|
+
let sensorType = args.first as? String ?? "accelerometer"
|
|
34
|
+
let available: Bool
|
|
35
|
+
switch sensorType {
|
|
36
|
+
case "gyroscope":
|
|
37
|
+
available = motionManager.isGyroAvailable
|
|
38
|
+
default:
|
|
39
|
+
available = motionManager.isAccelerometerAvailable
|
|
40
|
+
}
|
|
41
|
+
callback(["available": available], nil)
|
|
42
|
+
default:
|
|
43
|
+
callback(nil, "SensorsModule: unknown method '\(method)'")
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// MARK: - Accelerometer
|
|
48
|
+
|
|
49
|
+
private func startAccelerometer(interval: TimeInterval, callback: @escaping (Any?, String?) -> Void) {
|
|
50
|
+
guard motionManager.isAccelerometerAvailable else {
|
|
51
|
+
callback(nil, "Accelerometer not available on this device")
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
motionManager.accelerometerUpdateInterval = interval
|
|
55
|
+
motionManager.startAccelerometerUpdates(to: queue) { [weak self] data, error in
|
|
56
|
+
guard let data = data, let bridge = self?.bridge else { return }
|
|
57
|
+
if error != nil { return }
|
|
58
|
+
DispatchQueue.main.async {
|
|
59
|
+
bridge.dispatchGlobalEvent("sensor:accelerometer", payload: [
|
|
60
|
+
"x": data.acceleration.x,
|
|
61
|
+
"y": data.acceleration.y,
|
|
62
|
+
"z": data.acceleration.z,
|
|
63
|
+
"timestamp": data.timestamp,
|
|
64
|
+
])
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
callback(nil, nil)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private func stopAccelerometer(callback: @escaping (Any?, String?) -> Void) {
|
|
71
|
+
motionManager.stopAccelerometerUpdates()
|
|
72
|
+
callback(nil, nil)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// MARK: - Gyroscope
|
|
76
|
+
|
|
77
|
+
private func startGyroscope(interval: TimeInterval, callback: @escaping (Any?, String?) -> Void) {
|
|
78
|
+
guard motionManager.isGyroAvailable else {
|
|
79
|
+
callback(nil, "Gyroscope not available on this device")
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
motionManager.gyroUpdateInterval = interval
|
|
83
|
+
motionManager.startGyroUpdates(to: queue) { [weak self] data, error in
|
|
84
|
+
guard let data = data, let bridge = self?.bridge else { return }
|
|
85
|
+
if error != nil { return }
|
|
86
|
+
DispatchQueue.main.async {
|
|
87
|
+
bridge.dispatchGlobalEvent("sensor:gyroscope", payload: [
|
|
88
|
+
"x": data.rotationRate.x,
|
|
89
|
+
"y": data.rotationRate.y,
|
|
90
|
+
"z": data.rotationRate.z,
|
|
91
|
+
"timestamp": data.timestamp,
|
|
92
|
+
])
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
callback(nil, nil)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private func stopGyroscope(callback: @escaping (Any?, String?) -> Void) {
|
|
99
|
+
motionManager.stopGyroUpdates()
|
|
100
|
+
callback(nil, nil)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
#endif
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#if canImport(UIKit)
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
final class ShareModule: NativeModule {
|
|
5
|
+
var moduleName: String { "Share" }
|
|
6
|
+
|
|
7
|
+
func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
8
|
+
switch method {
|
|
9
|
+
case "share":
|
|
10
|
+
guard let content = args.first as? [String: Any] else {
|
|
11
|
+
callback(nil, "Invalid content")
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
var items: [Any] = []
|
|
15
|
+
if let message = content["message"] as? String { items.append(message) }
|
|
16
|
+
if let urlStr = content["url"] as? String, let u = URL(string: urlStr) { items.append(u) }
|
|
17
|
+
if items.isEmpty { callback(nil, "No shareable content"); return }
|
|
18
|
+
|
|
19
|
+
DispatchQueue.main.async {
|
|
20
|
+
let vc = UIActivityViewController(activityItems: items, applicationActivities: nil)
|
|
21
|
+
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
|
22
|
+
let rootVC = windowScene.windows.first?.rootViewController {
|
|
23
|
+
// iPad popover support
|
|
24
|
+
if let popover = vc.popoverPresentationController {
|
|
25
|
+
popover.sourceView = rootVC.view
|
|
26
|
+
popover.sourceRect = CGRect(
|
|
27
|
+
x: rootVC.view.bounds.midX,
|
|
28
|
+
y: rootVC.view.bounds.midY,
|
|
29
|
+
width: 0,
|
|
30
|
+
height: 0
|
|
31
|
+
)
|
|
32
|
+
popover.permittedArrowDirections = []
|
|
33
|
+
}
|
|
34
|
+
rootVC.present(vc, animated: true)
|
|
35
|
+
vc.completionWithItemsHandler = { _, completed, _, _ in
|
|
36
|
+
callback(["shared": completed], nil)
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
callback(nil, "No root view controller")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
default:
|
|
43
|
+
callback(nil, "Unknown method: \(method)")
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func invokeSync(method: String, args: [Any]) -> Any? { nil }
|
|
48
|
+
}
|
|
49
|
+
#endif
|