@use-voltra/ios-client 1.4.0 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -0
- package/Voltra.podspec +28 -0
- package/build/commonjs/VoltraModule.js +13 -0
- package/build/commonjs/VoltraModule.js.map +1 -0
- package/build/commonjs/components/VoltraLiveActivityPreview.js +30 -0
- package/build/commonjs/components/VoltraLiveActivityPreview.js.map +1 -0
- package/build/commonjs/components/VoltraView.js +50 -0
- package/build/commonjs/components/VoltraView.js.map +1 -0
- package/build/commonjs/components/VoltraWidgetPreview.js +58 -0
- package/build/commonjs/components/VoltraWidgetPreview.js.map +1 -0
- package/build/commonjs/events.js +32 -0
- package/build/commonjs/events.js.map +1 -0
- package/build/commonjs/helpers.js +26 -0
- package/build/commonjs/helpers.js.map +1 -0
- package/build/commonjs/index.js +226 -0
- package/build/commonjs/index.js.map +1 -0
- package/build/commonjs/live-activity/api.js +168 -0
- package/build/commonjs/live-activity/api.js.map +1 -0
- package/build/commonjs/logger.js +39 -0
- package/build/commonjs/logger.js.map +1 -0
- package/build/commonjs/native/NativeVoltra.js +15 -0
- package/build/commonjs/native/NativeVoltra.js.map +1 -0
- package/build/commonjs/native/VoltraRNNativeComponent.ts +9 -0
- package/build/commonjs/package.json +1 -0
- package/build/commonjs/preload.js +54 -0
- package/build/commonjs/preload.js.map +1 -0
- package/build/commonjs/types.js +2 -0
- package/build/commonjs/types.js.map +1 -0
- package/build/commonjs/utils/assertRunningOnApple.js +16 -0
- package/build/commonjs/utils/assertRunningOnApple.js.map +1 -0
- package/build/commonjs/utils/helpers.js +19 -0
- package/build/commonjs/utils/helpers.js.map +1 -0
- package/build/commonjs/utils/index.js +28 -0
- package/build/commonjs/utils/index.js.map +1 -0
- package/build/commonjs/utils/useUpdateOnHMR.js +25 -0
- package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -0
- package/build/commonjs/widgets/server-credentials.js +18 -0
- package/build/commonjs/widgets/server-credentials.js.map +1 -0
- package/build/commonjs/widgets/widget-api.js +55 -0
- package/build/commonjs/widgets/widget-api.js.map +1 -0
- package/build/module/VoltraModule.js +4 -0
- package/build/module/VoltraModule.js.map +1 -0
- package/build/module/components/VoltraLiveActivityPreview.js +25 -0
- package/build/module/components/VoltraLiveActivityPreview.js.map +1 -0
- package/build/module/components/VoltraView.js +44 -0
- package/build/module/components/VoltraView.js.map +1 -0
- package/build/module/components/VoltraWidgetPreview.js +53 -0
- package/build/module/components/VoltraWidgetPreview.js.map +1 -0
- package/build/module/events.js +28 -0
- package/build/module/events.js.map +1 -0
- package/build/module/helpers.js +21 -0
- package/build/module/helpers.js.map +1 -0
- package/build/module/index.js +17 -0
- package/build/module/index.js.map +1 -0
- package/build/module/live-activity/api.js +158 -0
- package/build/module/live-activity/api.js.map +1 -0
- package/build/module/logger.js +35 -0
- package/build/module/logger.js.map +1 -0
- package/build/module/native/NativeVoltra.js +11 -0
- package/build/module/native/NativeVoltra.js.map +1 -0
- package/build/module/native/VoltraRNNativeComponent.ts +9 -0
- package/build/module/package.json +1 -0
- package/build/module/preload.js +48 -0
- package/build/module/preload.js.map +1 -0
- package/build/module/types.js +2 -0
- package/build/module/types.js.map +1 -0
- package/build/module/utils/assertRunningOnApple.js +11 -0
- package/build/module/utils/assertRunningOnApple.js.map +1 -0
- package/build/module/utils/helpers.js +4 -0
- package/build/module/utils/helpers.js.map +1 -0
- package/build/module/utils/index.js +5 -0
- package/build/module/utils/index.js.map +1 -0
- package/build/module/utils/useUpdateOnHMR.js +20 -0
- package/build/module/utils/useUpdateOnHMR.js.map +1 -0
- package/build/module/widgets/server-credentials.js +13 -0
- package/build/module/widgets/server-credentials.js.map +1 -0
- package/build/module/widgets/widget-api.js +45 -0
- package/build/module/widgets/widget-api.js.map +1 -0
- package/build/typescript/commonjs/VoltraModule.d.ts +3 -0
- package/build/typescript/commonjs/VoltraModule.d.ts.map +1 -0
- package/build/typescript/commonjs/components/VoltraLiveActivityPreview.d.ts.map +1 -0
- package/build/typescript/commonjs/components/VoltraView.d.ts.map +1 -0
- package/build/typescript/commonjs/components/VoltraWidgetPreview.d.ts.map +1 -0
- package/build/typescript/commonjs/events.d.ts.map +1 -0
- package/build/typescript/commonjs/helpers.d.ts.map +1 -0
- package/build/{types → typescript/commonjs}/index.d.ts +5 -0
- package/build/typescript/commonjs/index.d.ts.map +1 -0
- package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -0
- package/build/typescript/commonjs/logger.d.ts.map +1 -0
- package/build/typescript/commonjs/native/NativeVoltra.d.ts +100 -0
- package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -0
- package/build/typescript/commonjs/native/VoltraRNNativeComponent.d.ts +8 -0
- package/build/typescript/commonjs/native/VoltraRNNativeComponent.d.ts.map +1 -0
- package/build/typescript/commonjs/package.json +1 -0
- package/build/typescript/commonjs/preload.d.ts.map +1 -0
- package/build/typescript/commonjs/types.d.ts.map +1 -0
- package/build/typescript/commonjs/utils/assertRunningOnApple.d.ts.map +1 -0
- package/build/typescript/commonjs/utils/helpers.d.ts.map +1 -0
- package/build/typescript/commonjs/utils/index.d.ts.map +1 -0
- package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -0
- package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -0
- package/build/typescript/commonjs/widgets/widget-api.d.ts.map +1 -0
- package/build/typescript/module/VoltraModule.d.ts +3 -0
- package/build/typescript/module/VoltraModule.d.ts.map +1 -0
- package/build/typescript/module/components/VoltraLiveActivityPreview.d.ts +7 -0
- package/build/typescript/module/components/VoltraLiveActivityPreview.d.ts.map +1 -0
- package/build/typescript/module/components/VoltraView.d.ts +12 -0
- package/build/typescript/module/components/VoltraView.d.ts.map +1 -0
- package/build/typescript/module/components/VoltraWidgetPreview.d.ts +9 -0
- package/build/typescript/module/components/VoltraWidgetPreview.d.ts.map +1 -0
- package/build/typescript/module/events.d.ts +33 -0
- package/build/typescript/module/events.d.ts.map +1 -0
- package/build/typescript/module/helpers.d.ts +3 -0
- package/build/typescript/module/helpers.d.ts.map +1 -0
- package/build/typescript/module/index.d.ts +18 -0
- package/build/typescript/module/index.d.ts.map +1 -0
- package/build/typescript/module/live-activity/api.d.ts +35 -0
- package/build/typescript/module/live-activity/api.d.ts.map +1 -0
- package/build/typescript/module/logger.d.ts +16 -0
- package/build/typescript/module/logger.d.ts.map +1 -0
- package/build/typescript/module/native/NativeVoltra.d.ts +100 -0
- package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -0
- package/build/typescript/module/native/VoltraRNNativeComponent.d.ts +8 -0
- package/build/typescript/module/native/VoltraRNNativeComponent.d.ts.map +1 -0
- package/build/typescript/module/package.json +1 -0
- package/build/typescript/module/preload.d.ts +6 -0
- package/build/typescript/module/preload.d.ts.map +1 -0
- package/build/typescript/module/types.d.ts +2 -0
- package/build/typescript/module/types.d.ts.map +1 -0
- package/build/typescript/module/utils/assertRunningOnApple.d.ts +2 -0
- package/build/typescript/module/utils/assertRunningOnApple.d.ts.map +1 -0
- package/build/{esm/utils/helpers.js → typescript/module/utils/helpers.d.ts} +1 -1
- package/build/typescript/module/utils/helpers.d.ts.map +1 -0
- package/build/{esm/utils/index.js → typescript/module/utils/index.d.ts} +1 -1
- package/build/typescript/module/utils/index.d.ts.map +1 -0
- package/build/typescript/module/utils/useUpdateOnHMR.d.ts +5 -0
- package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -0
- package/build/typescript/module/widgets/server-credentials.d.ts +5 -0
- package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -0
- package/build/typescript/module/widgets/widget-api.d.ts +11 -0
- package/build/typescript/module/widgets/widget-api.d.ts.map +1 -0
- package/expo-plugin/app.plugin.js +3 -0
- package/expo-plugin/build/cjs/constants.js +23 -0
- package/expo-plugin/build/cjs/constants.js.map +1 -0
- package/expo-plugin/build/cjs/index.js +51 -0
- package/expo-plugin/build/cjs/index.js.map +1 -0
- package/expo-plugin/build/cjs/ios/eas.js +28 -0
- package/expo-plugin/build/cjs/ios/eas.js.map +1 -0
- package/expo-plugin/build/cjs/ios/entitlements.js +46 -0
- package/expo-plugin/build/cjs/ios/entitlements.js.map +1 -0
- package/expo-plugin/build/cjs/ios/index.js +39 -0
- package/expo-plugin/build/cjs/ios/index.js.map +1 -0
- package/expo-plugin/build/cjs/ios/infoPlist.js +51 -0
- package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -0
- package/expo-plugin/build/cjs/ios/pushNotifications.js +22 -0
- package/expo-plugin/build/cjs/ios/pushNotifications.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/eas.js +66 -0
- package/expo-plugin/build/cjs/ios-widget/eas.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/assets.js +199 -0
- package/expo-plugin/build/cjs/ios-widget/files/assets.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/entitlements.js +77 -0
- package/expo-plugin/build/cjs/ios-widget/files/entitlements.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/index.js +92 -0
- package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +91 -0
- package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/swift.js +443 -0
- package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/fonts.js +151 -0
- package/expo-plugin/build/cjs/ios-widget/fonts.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/index.js +46 -0
- package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/podfile.js +41 -0
- package/expo-plugin/build/cjs/ios-widget/podfile.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +99 -0
- package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +247 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js +91 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/groups.js +79 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/groups.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/index.js +155 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js +71 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js +74 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/target.js +113 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/target.js.map +1 -0
- package/expo-plugin/build/cjs/utils/fileDiscovery.js +120 -0
- package/expo-plugin/build/cjs/utils/fileDiscovery.js.map +1 -0
- package/expo-plugin/build/cjs/utils/urlScheme.js +40 -0
- package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -0
- package/expo-plugin/build/cjs/validation.js +55 -0
- package/expo-plugin/build/cjs/validation.js.map +1 -0
- package/expo-plugin/build/esm/constants.js +20 -0
- package/expo-plugin/build/esm/constants.js.map +1 -0
- package/expo-plugin/build/esm/index.js +49 -0
- package/expo-plugin/build/esm/index.js.map +1 -0
- package/expo-plugin/build/esm/ios/eas.js +24 -0
- package/expo-plugin/build/esm/ios/eas.js.map +1 -0
- package/expo-plugin/build/esm/ios/entitlements.js +42 -0
- package/expo-plugin/build/esm/ios/entitlements.js.map +1 -0
- package/expo-plugin/build/esm/ios/index.js +34 -0
- package/expo-plugin/build/esm/ios/index.js.map +1 -0
- package/expo-plugin/build/esm/ios/infoPlist.js +47 -0
- package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -0
- package/expo-plugin/build/esm/ios/pushNotifications.js +18 -0
- package/expo-plugin/build/esm/ios/pushNotifications.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/eas.js +62 -0
- package/expo-plugin/build/esm/ios-widget/eas.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/assets.js +163 -0
- package/expo-plugin/build/esm/ios-widget/files/assets.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/entitlements.js +37 -0
- package/expo-plugin/build/esm/ios-widget/files/entitlements.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/index.js +55 -0
- package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +55 -0
- package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/swift.js +403 -0
- package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/fonts.js +111 -0
- package/expo-plugin/build/esm/ios-widget/fonts.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/index.js +42 -0
- package/expo-plugin/build/esm/ios-widget/index.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/podfile.js +37 -0
- package/expo-plugin/build/esm/ios-widget/podfile.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/widgetPlist.js +92 -0
- package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +210 -0
- package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js +87 -0
- package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/groups.js +75 -0
- package/expo-plugin/build/esm/ios-widget/xcode/groups.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/index.js +118 -0
- package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js +68 -0
- package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/productFile.js +70 -0
- package/expo-plugin/build/esm/ios-widget/xcode/productFile.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/target.js +108 -0
- package/expo-plugin/build/esm/ios-widget/xcode/target.js.map +1 -0
- package/expo-plugin/build/esm/utils/fileDiscovery.js +83 -0
- package/expo-plugin/build/esm/utils/fileDiscovery.js.map +1 -0
- package/expo-plugin/build/esm/utils/urlScheme.js +37 -0
- package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -0
- package/expo-plugin/build/esm/validation.js +51 -0
- package/expo-plugin/build/esm/validation.js.map +1 -0
- package/expo-plugin/build/types/constants.d.ts +13 -0
- package/expo-plugin/build/types/constants.d.ts.map +1 -0
- package/expo-plugin/build/types/index.d.ts +10 -0
- package/expo-plugin/build/types/index.d.ts.map +1 -0
- package/expo-plugin/build/types/ios/eas.d.ts +12 -0
- package/expo-plugin/build/types/ios/eas.d.ts.map +1 -0
- package/expo-plugin/build/types/ios/entitlements.d.ts +14 -0
- package/expo-plugin/build/types/ios/entitlements.d.ts.map +1 -0
- package/expo-plugin/build/types/ios/index.d.ts +19 -0
- package/expo-plugin/build/types/ios/index.d.ts.map +1 -0
- package/expo-plugin/build/types/ios/infoPlist.d.ts +21 -0
- package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -0
- package/expo-plugin/build/types/ios/pushNotifications.d.ts +10 -0
- package/expo-plugin/build/types/ios/pushNotifications.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/eas.d.ts +15 -0
- package/expo-plugin/build/types/ios-widget/eas.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/assets.d.ts +13 -0
- package/expo-plugin/build/types/ios-widget/files/assets.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/entitlements.d.ts +17 -0
- package/expo-plugin/build/types/ios-widget/files/entitlements.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/index.d.ts +24 -0
- package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +10 -0
- package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/swift.d.ts +24 -0
- package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/fonts.d.ts +22 -0
- package/expo-plugin/build/types/ios-widget/fonts.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/index.d.ts +31 -0
- package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/podfile.d.ts +9 -0
- package/expo-plugin/build/types/ios-widget/podfile.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts +20 -0
- package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +25 -0
- package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts +20 -0
- package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts +15 -0
- package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +20 -0
- package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts +15 -0
- package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts +14 -0
- package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/target.d.ts +42 -0
- package/expo-plugin/build/types/ios-widget/xcode/target.d.ts.map +1 -0
- package/expo-plugin/build/types/types.d.ts +74 -0
- package/expo-plugin/build/types/types.d.ts.map +1 -0
- package/expo-plugin/build/types/utils/fileDiscovery.d.ts +15 -0
- package/expo-plugin/build/types/utils/fileDiscovery.d.ts.map +1 -0
- package/expo-plugin/build/types/utils/urlScheme.d.ts +10 -0
- package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -0
- package/expo-plugin/build/types/validation.d.ts +4 -0
- package/expo-plugin/build/types/validation.d.ts.map +1 -0
- package/expo-plugin/jest.config.js +18 -0
- package/expo-plugin/src/constants.ts +25 -0
- package/expo-plugin/src/index.ts +72 -0
- package/expo-plugin/src/ios/eas.ts +33 -0
- package/expo-plugin/src/ios/entitlements.ts +59 -0
- package/expo-plugin/src/ios/index.ts +47 -0
- package/expo-plugin/src/ios/infoPlist.ts +63 -0
- package/expo-plugin/src/ios/pushNotifications.ts +22 -0
- package/expo-plugin/src/ios-widget/eas.ts +79 -0
- package/expo-plugin/src/ios-widget/files/assets.ts +201 -0
- package/expo-plugin/src/ios-widget/files/entitlements.ts +48 -0
- package/expo-plugin/src/ios-widget/files/index.ts +74 -0
- package/expo-plugin/src/ios-widget/files/infoPlist.ts +57 -0
- package/expo-plugin/src/ios-widget/files/swift.node.test.ts +22 -0
- package/expo-plugin/src/ios-widget/files/swift.ts +476 -0
- package/expo-plugin/src/ios-widget/fonts.ts +132 -0
- package/expo-plugin/src/ios-widget/index.ts +73 -0
- package/expo-plugin/src/ios-widget/podfile.ts +44 -0
- package/expo-plugin/src/ios-widget/widgetPlist.ts +115 -0
- package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +301 -0
- package/expo-plugin/src/ios-widget/xcode/configurationList.ts +127 -0
- package/expo-plugin/src/ios-widget/xcode/groups.ts +101 -0
- package/expo-plugin/src/ios-widget/xcode/index.ts +149 -0
- package/expo-plugin/src/ios-widget/xcode/mainAppSettings.ts +95 -0
- package/expo-plugin/src/ios-widget/xcode/productFile.ts +91 -0
- package/expo-plugin/src/ios-widget/xcode/target.ts +148 -0
- package/expo-plugin/src/types.ts +89 -0
- package/expo-plugin/src/utils/fileDiscovery.ts +96 -0
- package/expo-plugin/src/utils/urlScheme.ts +45 -0
- package/expo-plugin/src/validation.node.test.ts +19 -0
- package/expo-plugin/src/validation.ts +63 -0
- package/expo-plugin/tsconfig.base.json +17 -0
- package/expo-plugin/tsconfig.cjs.json +9 -0
- package/expo-plugin/tsconfig.esm.json +9 -0
- package/expo-plugin/tsconfig.jest.json +8 -0
- package/expo-plugin/tsconfig.typecheck.json +12 -0
- package/expo-plugin/tsconfig.types.json +10 -0
- package/ios/Package.swift +68 -0
- package/ios/Tests/JSGradientParserTests.swift +201 -0
- package/ios/Tests/VoltraSharedTests/SmokeTests.swift +8 -0
- package/ios/VoltraWidget.podspec +30 -0
- package/ios/app/NativeVoltra.h +5 -0
- package/ios/app/NativeVoltra.mm +211 -0
- package/ios/app/VoltraActivity.swift +5 -0
- package/ios/app/VoltraImagePreload.swift +154 -0
- package/ios/app/VoltraLiveActivityManager.swift +228 -0
- package/ios/app/VoltraLiveActivityService.swift +306 -0
- package/ios/app/VoltraModule.swift +215 -0
- package/ios/app/VoltraModuleImpl.swift +331 -0
- package/ios/app/VoltraOptions.swift +27 -0
- package/ios/app/VoltraViewComponentView.h +10 -0
- package/ios/app/VoltraViewComponentView.mm +67 -0
- package/ios/app/VoltraViewRoot.swift +63 -0
- package/ios/app/VoltraWidgetService.swift +154 -0
- package/ios/shared/BrotliCompression.swift +81 -0
- package/ios/shared/ComponentTypeID.swift +117 -0
- package/ios/shared/Data+hexString.swift +8 -0
- package/ios/shared/Date+toTimerInterval.swift +25 -0
- package/ios/shared/JSONValue.swift +128 -0
- package/ios/shared/ShortNames.swift +180 -0
- package/ios/shared/VoltraAttributes.swift +58 -0
- package/ios/shared/VoltraConfig.swift +18 -0
- package/ios/shared/VoltraConstants.swift +45 -0
- package/ios/shared/VoltraElement.swift +153 -0
- package/ios/shared/VoltraEvent.swift +72 -0
- package/ios/shared/VoltraEventBus.swift +80 -0
- package/ios/shared/VoltraImageStore.swift +119 -0
- package/ios/shared/VoltraInitialStateLocale.swift +54 -0
- package/ios/shared/VoltraInteractionIntent.swift +39 -0
- package/ios/shared/VoltraKeychainHelper.swift +178 -0
- package/ios/shared/VoltraLiveActivityPayload.swift +113 -0
- package/ios/shared/VoltraLogger.swift +30 -0
- package/ios/shared/VoltraNode.swift +194 -0
- package/ios/shared/VoltraPayloadMigrator.swift +63 -0
- package/ios/shared/VoltraPersistentEventQueue.swift +67 -0
- package/ios/shared/VoltraRefreshIntent.swift +29 -0
- package/ios/shared/VoltraRegion.swift +37 -0
- package/ios/shared/VoltraWidgetDefaults.swift +114 -0
- package/ios/shared/VoltraWidgetServerFetcher.swift +166 -0
- package/ios/target/VoltraHomeWidget.swift +508 -0
- package/ios/target/VoltraWidget.swift +158 -0
- package/ios/ui/Extensions/View.modifiers.swift +28 -0
- package/ios/ui/Extensions/VoltraNode+Parameters.swift +18 -0
- package/ios/ui/Generated/Parameters/.generated +8 -0
- package/ios/ui/Generated/Parameters/ButtonParameters.swift +15 -0
- package/ios/ui/Generated/Parameters/ChartParameters.swift +33 -0
- package/ios/ui/Generated/Parameters/CircularProgressViewParameters.swift +59 -0
- package/ios/ui/Generated/Parameters/ComponentParameters.swift +12 -0
- package/ios/ui/Generated/Parameters/DividerParameters.swift +12 -0
- package/ios/ui/Generated/Parameters/GaugeParameters.swift +54 -0
- package/ios/ui/Generated/Parameters/GlassContainerParameters.swift +15 -0
- package/ios/ui/Generated/Parameters/GroupBoxParameters.swift +12 -0
- package/ios/ui/Generated/Parameters/HStackParameters.swift +34 -0
- package/ios/ui/Generated/Parameters/ImageParameters.swift +29 -0
- package/ios/ui/Generated/Parameters/LabelParameters.swift +18 -0
- package/ios/ui/Generated/Parameters/LinearGradientParameters.swift +27 -0
- package/ios/ui/Generated/Parameters/LinearProgressViewParameters.swift +64 -0
- package/ios/ui/Generated/Parameters/LinkParameters.swift +15 -0
- package/ios/ui/Generated/Parameters/MaskParameters.swift +12 -0
- package/ios/ui/Generated/Parameters/SpacerParameters.swift +15 -0
- package/ios/ui/Generated/Parameters/SymbolParameters.swift +59 -0
- package/ios/ui/Generated/Parameters/TextParameters.swift +18 -0
- package/ios/ui/Generated/Parameters/TimerParameters.swift +54 -0
- package/ios/ui/Generated/Parameters/ToggleParameters.swift +24 -0
- package/ios/ui/Generated/Parameters/VStackParameters.swift +34 -0
- package/ios/ui/Generated/Parameters/ViewParameters.swift +12 -0
- package/ios/ui/Generated/Parameters/ZStackParameters.swift +15 -0
- package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +43 -0
- package/ios/ui/Helpers/VoltraProgressDriver.swift +52 -0
- package/ios/ui/Layout/FlexContainerHelper.swift +114 -0
- package/ios/ui/Layout/VoltraFlexStackLayout.swift +417 -0
- package/ios/ui/Protocols/VoltraView.swift +29 -0
- package/ios/ui/Style/BackgroundValue.swift +27 -0
- package/ios/ui/Style/CompositeStyle.swift +81 -0
- package/ios/ui/Style/DecorationStyle.swift +207 -0
- package/ios/ui/Style/FlexEnvironment.swift +35 -0
- package/ios/ui/Style/FontVariant.swift +4 -0
- package/ios/ui/Style/GlassEffect.swift +6 -0
- package/ios/ui/Style/JSColorParser.swift +517 -0
- package/ios/ui/Style/JSGradientParser.swift +674 -0
- package/ios/ui/Style/JSStyleParser.swift +223 -0
- package/ios/ui/Style/LayoutStyle.swift +184 -0
- package/ios/ui/Style/Overflow.swift +4 -0
- package/ios/ui/Style/RenderingStyle.swift +33 -0
- package/ios/ui/Style/StyleConverter.swift +202 -0
- package/ios/ui/Style/TextDecoration.swift +6 -0
- package/ios/ui/Style/TextStyle.swift +50 -0
- package/ios/ui/Style/View+applyStyle.swift +38 -0
- package/ios/ui/Views/VoltraButton.swift +57 -0
- package/ios/ui/Views/VoltraChart.swift +840 -0
- package/ios/ui/Views/VoltraCircularProgressView.swift +103 -0
- package/ios/ui/Views/VoltraDivider.swift +16 -0
- package/ios/ui/Views/VoltraFlexView.swift +33 -0
- package/ios/ui/Views/VoltraGauge.swift +65 -0
- package/ios/ui/Views/VoltraGlassContainer.swift +29 -0
- package/ios/ui/Views/VoltraGroupBox.swift +26 -0
- package/ios/ui/Views/VoltraHStack.swift +70 -0
- package/ios/ui/Views/VoltraImage.swift +109 -0
- package/ios/ui/Views/VoltraLabel.swift +24 -0
- package/ios/ui/Views/VoltraLinearGradient.swift +115 -0
- package/ios/ui/Views/VoltraLinearProgressView.swift +118 -0
- package/ios/ui/Views/VoltraLink.swift +25 -0
- package/ios/ui/Views/VoltraMask.swift +23 -0
- package/ios/ui/Views/VoltraSpacer.swift +16 -0
- package/ios/ui/Views/VoltraSymbol.swift +160 -0
- package/ios/ui/Views/VoltraText.swift +87 -0
- package/ios/ui/Views/VoltraTimer.swift +131 -0
- package/ios/ui/Views/VoltraToggle.swift +39 -0
- package/ios/ui/Views/VoltraVStack.swift +68 -0
- package/ios/ui/Views/VoltraZStack.swift +33 -0
- package/ios/ui/Voltra.swift +86 -0
- package/package.json +91 -18
- package/build/cjs/VoltraModule.js +0 -6
- package/build/cjs/VoltraModule.js.map +0 -1
- package/build/cjs/components/VoltraLiveActivityPreview.js +0 -20
- package/build/cjs/components/VoltraLiveActivityPreview.js.map +0 -1
- package/build/cjs/components/VoltraView.js +0 -37
- package/build/cjs/components/VoltraView.js.map +0 -1
- package/build/cjs/components/VoltraWidgetPreview.js +0 -26
- package/build/cjs/components/VoltraWidgetPreview.js.map +0 -1
- package/build/cjs/events.js +0 -19
- package/build/cjs/events.js.map +0 -1
- package/build/cjs/helpers.js +0 -30
- package/build/cjs/helpers.js.map +0 -1
- package/build/cjs/index.js +0 -49
- package/build/cjs/index.js.map +0 -1
- package/build/cjs/live-activity/api.js +0 -158
- package/build/cjs/live-activity/api.js.map +0 -1
- package/build/cjs/logger.js +0 -36
- package/build/cjs/logger.js.map +0 -1
- package/build/cjs/preload.js +0 -54
- package/build/cjs/preload.js.map +0 -1
- package/build/cjs/utils/assertRunningOnApple.js +0 -13
- package/build/cjs/utils/assertRunningOnApple.js.map +0 -1
- package/build/cjs/utils/helpers.js +0 -7
- package/build/cjs/utils/helpers.js.map +0 -1
- package/build/cjs/utils/index.js +0 -19
- package/build/cjs/utils/index.js.map +0 -1
- package/build/cjs/utils/useUpdateOnHMR.js +0 -22
- package/build/cjs/utils/useUpdateOnHMR.js.map +0 -1
- package/build/cjs/widgets/server-credentials.js +0 -18
- package/build/cjs/widgets/server-credentials.js.map +0 -1
- package/build/cjs/widgets/widget-api.js +0 -59
- package/build/cjs/widgets/widget-api.js.map +0 -1
- package/build/esm/VoltraModule.js +0 -4
- package/build/esm/VoltraModule.js.map +0 -1
- package/build/esm/components/VoltraLiveActivityPreview.js +0 -17
- package/build/esm/components/VoltraLiveActivityPreview.js.map +0 -1
- package/build/esm/components/VoltraView.js +0 -34
- package/build/esm/components/VoltraView.js.map +0 -1
- package/build/esm/components/VoltraWidgetPreview.js +0 -23
- package/build/esm/components/VoltraWidgetPreview.js.map +0 -1
- package/build/esm/events.js +0 -13
- package/build/esm/events.js.map +0 -1
- package/build/esm/helpers.js +0 -23
- package/build/esm/helpers.js.map +0 -1
- package/build/esm/index.js +0 -10
- package/build/esm/index.js.map +0 -1
- package/build/esm/live-activity/api.js +0 -146
- package/build/esm/live-activity/api.js.map +0 -1
- package/build/esm/logger.js +0 -33
- package/build/esm/logger.js.map +0 -1
- package/build/esm/preload.js +0 -46
- package/build/esm/preload.js.map +0 -1
- package/build/esm/utils/assertRunningOnApple.js +0 -9
- package/build/esm/utils/assertRunningOnApple.js.map +0 -1
- package/build/esm/utils/helpers.js.map +0 -1
- package/build/esm/utils/index.js.map +0 -1
- package/build/esm/utils/useUpdateOnHMR.js +0 -18
- package/build/esm/utils/useUpdateOnHMR.js.map +0 -1
- package/build/esm/widgets/server-credentials.js +0 -11
- package/build/esm/widgets/server-credentials.js.map +0 -1
- package/build/esm/widgets/widget-api.js +0 -47
- package/build/esm/widgets/widget-api.js.map +0 -1
- package/build/types/VoltraModule.d.ts +0 -44
- package/build/types/VoltraModule.d.ts.map +0 -1
- package/build/types/components/VoltraLiveActivityPreview.d.ts.map +0 -1
- package/build/types/components/VoltraView.d.ts.map +0 -1
- package/build/types/components/VoltraWidgetPreview.d.ts.map +0 -1
- package/build/types/events.d.ts.map +0 -1
- package/build/types/helpers.d.ts.map +0 -1
- package/build/types/index.d.ts.map +0 -1
- package/build/types/live-activity/api.d.ts.map +0 -1
- package/build/types/logger.d.ts.map +0 -1
- package/build/types/preload.d.ts.map +0 -1
- package/build/types/types.d.ts.map +0 -1
- package/build/types/utils/assertRunningOnApple.d.ts.map +0 -1
- package/build/types/utils/helpers.d.ts.map +0 -1
- package/build/types/utils/index.d.ts.map +0 -1
- package/build/types/utils/useUpdateOnHMR.d.ts.map +0 -1
- package/build/types/widgets/server-credentials.d.ts.map +0 -1
- package/build/types/widgets/widget-api.d.ts.map +0 -1
- /package/build/{types → typescript/commonjs}/components/VoltraLiveActivityPreview.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/components/VoltraView.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/components/VoltraWidgetPreview.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/events.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/helpers.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/live-activity/api.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/logger.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/preload.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/types.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/utils/assertRunningOnApple.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/utils/helpers.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/utils/index.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/utils/useUpdateOnHMR.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/widgets/server-credentials.d.ts +0 -0
- /package/build/{types → typescript/commonjs}/widgets/widget-api.d.ts +0 -0
- /package/{build → expo-plugin/build}/cjs/package.json +0 -0
- /package/{build → expo-plugin/build}/cjs/types.js +0 -0
- /package/{build → expo-plugin/build}/cjs/types.js.map +0 -0
- /package/{build → expo-plugin/build}/esm/package.json +0 -0
- /package/{build → expo-plugin/build}/esm/types.js +0 -0
- /package/{build → expo-plugin/build}/esm/types.js.map +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// A single component element in the Voltra UI tree
|
|
4
|
+
public struct VoltraElement: Hashable {
|
|
5
|
+
/// Component type name (e.g., "VStack", "Text", "Button")
|
|
6
|
+
public let type: String
|
|
7
|
+
|
|
8
|
+
/// Optional identifier for the element
|
|
9
|
+
public let id: String?
|
|
10
|
+
|
|
11
|
+
/// Child nodes or text content
|
|
12
|
+
public let children: VoltraNode?
|
|
13
|
+
|
|
14
|
+
/// Raw properties (stored as JSONValue for type safety)
|
|
15
|
+
private let _props: [String: JSONValue]?
|
|
16
|
+
|
|
17
|
+
/// Optional stylesheet for resolving style references
|
|
18
|
+
public let stylesheet: [[String: JSONValue]]?
|
|
19
|
+
|
|
20
|
+
/// Optional shared elements for resolving element references
|
|
21
|
+
public let sharedElements: [JSONValue]?
|
|
22
|
+
|
|
23
|
+
// MARK: - Hashable
|
|
24
|
+
|
|
25
|
+
public func hash(into hasher: inout Hasher) {
|
|
26
|
+
hasher.combine(type)
|
|
27
|
+
hasher.combine(id)
|
|
28
|
+
hasher.combine(children)
|
|
29
|
+
hasher.combine(_props)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static func == (lhs: VoltraElement, rhs: VoltraElement) -> Bool {
|
|
33
|
+
lhs.type == rhs.type &&
|
|
34
|
+
lhs.id == rhs.id &&
|
|
35
|
+
lhs.children == rhs.children &&
|
|
36
|
+
lhs._props == rhs._props
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// MARK: - Computed Properties
|
|
40
|
+
|
|
41
|
+
/// Expanded props with full property names
|
|
42
|
+
public var props: [String: JSONValue]? {
|
|
43
|
+
guard let props = _props else { return nil }
|
|
44
|
+
var expanded: [String: JSONValue] = [:]
|
|
45
|
+
for (key, value) in props {
|
|
46
|
+
// Expand short key to full name using unified ShortNames mapping
|
|
47
|
+
let fullKey = ShortNames.expand(key)
|
|
48
|
+
expanded[fullKey] = value
|
|
49
|
+
}
|
|
50
|
+
return expanded.isEmpty ? nil : expanded
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Style dictionary with expanded keys
|
|
54
|
+
public var style: [String: JSONValue]? {
|
|
55
|
+
guard let styleValue = props?["style"] else {
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let styleDict: [String: JSONValue]
|
|
60
|
+
|
|
61
|
+
// Handle stylesheet reference (integer index)
|
|
62
|
+
if let index = styleValue.intValue,
|
|
63
|
+
let stylesheet = stylesheet,
|
|
64
|
+
index >= 0, index < stylesheet.count
|
|
65
|
+
{
|
|
66
|
+
styleDict = stylesheet[index]
|
|
67
|
+
}
|
|
68
|
+
// Handle inline style (object)
|
|
69
|
+
else if let objectValue = styleValue.objectValue {
|
|
70
|
+
styleDict = objectValue
|
|
71
|
+
} else {
|
|
72
|
+
return nil
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
var expanded: [String: JSONValue] = [:]
|
|
76
|
+
for (key, value) in styleDict {
|
|
77
|
+
// Use unified ShortNames mapping for style properties
|
|
78
|
+
let expandedKey = ShortNames.expand(key)
|
|
79
|
+
expanded[expandedKey] = value
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return expanded
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// MARK: - Initialization
|
|
86
|
+
|
|
87
|
+
/// Initialize from JSONValue (no serialization roundtrip)
|
|
88
|
+
/// - Parameters:
|
|
89
|
+
/// - json: The JSON value to parse
|
|
90
|
+
/// - stylesheet: Optional shared stylesheet for style deduplication
|
|
91
|
+
/// - sharedElements: Optional shared elements array for element deduplication
|
|
92
|
+
public init?(from json: JSONValue, stylesheet: [[String: JSONValue]]? = nil, sharedElements: [JSONValue]? = nil) {
|
|
93
|
+
guard case let .object(dict) = json else {
|
|
94
|
+
return nil
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Decode component type as Int (numeric ID) and convert to component name
|
|
98
|
+
guard case let .int(typeID) = dict["t"],
|
|
99
|
+
let componentTypeID = ComponentTypeID(rawValue: typeID)
|
|
100
|
+
else {
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
type = componentTypeID.componentName
|
|
104
|
+
|
|
105
|
+
// Extract id
|
|
106
|
+
id = dict["i"]?.stringValue
|
|
107
|
+
|
|
108
|
+
// Extract children
|
|
109
|
+
if let childrenValue = dict["c"] {
|
|
110
|
+
children = VoltraNode(from: childrenValue, stylesheet: stylesheet, sharedElements: sharedElements)
|
|
111
|
+
} else {
|
|
112
|
+
children = nil
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Extract props
|
|
116
|
+
if let propsValue = dict["p"], case let .object(propsDict) = propsValue {
|
|
117
|
+
_props = propsDict
|
|
118
|
+
} else {
|
|
119
|
+
_props = nil
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Store stylesheet reference
|
|
123
|
+
self.stylesheet = stylesheet
|
|
124
|
+
|
|
125
|
+
// Store shared elements reference
|
|
126
|
+
self.sharedElements = sharedElements
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Get component prop by name - handles both single component and array
|
|
130
|
+
public func componentProp(_ propName: String) -> VoltraNode {
|
|
131
|
+
guard let propValue = props?[propName] else { return .empty }
|
|
132
|
+
|
|
133
|
+
return VoltraNode(from: propValue, stylesheet: stylesheet, sharedElements: sharedElements)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/// Decode parameters from props
|
|
137
|
+
public func parameters<T: Decodable>(_: T.Type) -> T {
|
|
138
|
+
guard let props = props else {
|
|
139
|
+
// Return default instance if decoding fails
|
|
140
|
+
return try! JSONDecoder().decode(T.self, from: "{}".data(using: .utf8)!)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
do {
|
|
144
|
+
// Convert JSONValue dictionary to [String: Any] for JSONSerialization
|
|
145
|
+
let dict = props.mapValues { $0.toAny() }
|
|
146
|
+
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])
|
|
147
|
+
return try JSONDecoder().decode(T.self, from: jsonData)
|
|
148
|
+
} catch {
|
|
149
|
+
// Return default instance if decoding fails
|
|
150
|
+
return try! JSONDecoder().decode(T.self, from: "{}".data(using: .utf8)!)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// MARK: - Event Types
|
|
4
|
+
|
|
5
|
+
/// All Voltra event types with their associated data
|
|
6
|
+
public enum VoltraEventType {
|
|
7
|
+
/// Persistent events (widget → app, survives app death)
|
|
8
|
+
case interaction(source: String, identifier: String, payload: String?)
|
|
9
|
+
|
|
10
|
+
// Transient events (main app only, in-memory)
|
|
11
|
+
case stateChange(activityName: String, state: String)
|
|
12
|
+
case tokenReceived(activityName: String, pushToken: String)
|
|
13
|
+
case pushToStartTokenReceived(token: String)
|
|
14
|
+
|
|
15
|
+
/// Whether this event should be persisted to UserDefaults (survives app death)
|
|
16
|
+
var isPersistent: Bool {
|
|
17
|
+
switch self {
|
|
18
|
+
case .interaction:
|
|
19
|
+
return true
|
|
20
|
+
default:
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// The event name used for JS bridge
|
|
26
|
+
var name: String {
|
|
27
|
+
switch self {
|
|
28
|
+
case .interaction:
|
|
29
|
+
return "interaction"
|
|
30
|
+
case .stateChange:
|
|
31
|
+
return "stateChange"
|
|
32
|
+
case .tokenReceived:
|
|
33
|
+
return "activityTokenReceived"
|
|
34
|
+
case .pushToStartTokenReceived:
|
|
35
|
+
return "activityPushToStartTokenReceived"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Convert to dictionary for JS bridge
|
|
40
|
+
var asDictionary: [String: Any] {
|
|
41
|
+
var dict: [String: Any] = ["type": name]
|
|
42
|
+
|
|
43
|
+
switch self {
|
|
44
|
+
case let .interaction(source, identifier, payload):
|
|
45
|
+
dict["source"] = source
|
|
46
|
+
dict["timestamp"] = Date().timeIntervalSince1970
|
|
47
|
+
dict["identifier"] = identifier
|
|
48
|
+
dict["payload"] = payload ?? ""
|
|
49
|
+
|
|
50
|
+
case let .stateChange(activityName, state):
|
|
51
|
+
dict["timestamp"] = Date().timeIntervalSince1970
|
|
52
|
+
dict["activityName"] = activityName
|
|
53
|
+
dict["activityState"] = state
|
|
54
|
+
|
|
55
|
+
case let .tokenReceived(activityName, pushToken):
|
|
56
|
+
dict["timestamp"] = Date().timeIntervalSince1970
|
|
57
|
+
dict["activityName"] = activityName
|
|
58
|
+
dict["pushToken"] = pushToken
|
|
59
|
+
|
|
60
|
+
case let .pushToStartTokenReceived(token):
|
|
61
|
+
dict["pushToStartToken"] = token
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return dict
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// MARK: - Notification Name
|
|
69
|
+
|
|
70
|
+
extension Notification.Name {
|
|
71
|
+
static let voltraEvent = Notification.Name("voltraEvent")
|
|
72
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
/// A centralized event bus that manages Voltra events
|
|
5
|
+
/// - Persistent events (interactions): routed through UserDefaults for cross-process delivery
|
|
6
|
+
/// - Transient events (state changes, tokens): routed through NotificationCenter for in-process delivery
|
|
7
|
+
public class VoltraEventBus {
|
|
8
|
+
public static let shared = VoltraEventBus()
|
|
9
|
+
|
|
10
|
+
private var observer: NSObjectProtocol?
|
|
11
|
+
private let lock = NSLock()
|
|
12
|
+
|
|
13
|
+
private init() {}
|
|
14
|
+
|
|
15
|
+
/// Send an event. Routing is automatic based on event type:
|
|
16
|
+
/// - Persistent events → UserDefaults (survives app death, cross-process) + NotificationCenter (hot delivery)
|
|
17
|
+
/// - Transient events → NotificationCenter only (in-memory, same process)
|
|
18
|
+
public func send(_ event: VoltraEventType) {
|
|
19
|
+
// Compute dictionary once to ensure consistent timestamp across all delivery paths
|
|
20
|
+
let eventData = event.asDictionary
|
|
21
|
+
|
|
22
|
+
if event.isPersistent {
|
|
23
|
+
// Persistent: write to UserDefaults first (for widget → app communication, survives app death)
|
|
24
|
+
VoltraPersistentEventQueue.write(eventData)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Always post to NotificationCenter for immediate delivery when app is running
|
|
28
|
+
NotificationCenter.default.post(
|
|
29
|
+
name: .voltraEvent,
|
|
30
|
+
object: nil,
|
|
31
|
+
userInfo: eventData
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Subscribe to Voltra events. This will:
|
|
36
|
+
/// 1. Replay any persisted events from UserDefaults (cold start)
|
|
37
|
+
/// 2. Set up a NotificationCenter observer for all events (hot delivery)
|
|
38
|
+
///
|
|
39
|
+
/// - Parameter handler: A closure that receives the event name and event data dictionary
|
|
40
|
+
public func subscribe(handler: @escaping (String, [String: Any]) -> Void) {
|
|
41
|
+
lock.lock()
|
|
42
|
+
defer { lock.unlock() }
|
|
43
|
+
|
|
44
|
+
// 1. Replay persisted events from UserDefaults (interactions from widget)
|
|
45
|
+
let persistedEvents = VoltraPersistentEventQueue.popAll()
|
|
46
|
+
for event in persistedEvents {
|
|
47
|
+
handler(event.name, event.data)
|
|
48
|
+
}
|
|
49
|
+
VoltraLogger.event.info("Replayed \(persistedEvents.count) persisted events")
|
|
50
|
+
|
|
51
|
+
// 2. Listen for all events via NotificationCenter (hot delivery)
|
|
52
|
+
observer = NotificationCenter.default.addObserver(
|
|
53
|
+
forName: .voltraEvent,
|
|
54
|
+
object: nil,
|
|
55
|
+
queue: .main
|
|
56
|
+
) { notification in
|
|
57
|
+
guard let userInfo = notification.userInfo as? [String: Any],
|
|
58
|
+
let eventName = userInfo["type"] as? String
|
|
59
|
+
else {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
handler(eventName, userInfo)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Unsubscribe from Voltra events
|
|
67
|
+
public func unsubscribe() {
|
|
68
|
+
lock.lock()
|
|
69
|
+
defer { lock.unlock() }
|
|
70
|
+
|
|
71
|
+
if let observer = observer {
|
|
72
|
+
NotificationCenter.default.removeObserver(observer)
|
|
73
|
+
self.observer = nil
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
deinit {
|
|
78
|
+
unsubscribe()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Utility for reading/writing preloaded images to App Group shared storage
|
|
5
|
+
public enum VoltraImageStore {
|
|
6
|
+
private static let imageDirectoryName = "voltra_images"
|
|
7
|
+
|
|
8
|
+
/// Get the shared container URL for storing images
|
|
9
|
+
public static func imageDirectory() -> URL? {
|
|
10
|
+
guard let groupId = VoltraConfig.groupIdentifier(),
|
|
11
|
+
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId)
|
|
12
|
+
else { return nil }
|
|
13
|
+
|
|
14
|
+
return containerURL.appendingPathComponent(imageDirectoryName, isDirectory: true)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Ensure the image directory exists
|
|
18
|
+
private static func ensureDirectoryExists() throws {
|
|
19
|
+
guard let directory = imageDirectory() else {
|
|
20
|
+
throw VoltraImageStoreError.appGroupNotConfigured
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if !FileManager.default.fileExists(atPath: directory.path) {
|
|
24
|
+
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Save image data to App Group storage
|
|
29
|
+
/// - Parameters:
|
|
30
|
+
/// - data: The image data to save
|
|
31
|
+
/// - key: The key/name to use for the image (will be used as assetName)
|
|
32
|
+
public static func saveImage(_ data: Data, key: String) throws {
|
|
33
|
+
try ensureDirectoryExists()
|
|
34
|
+
|
|
35
|
+
guard let directory = imageDirectory() else {
|
|
36
|
+
throw VoltraImageStoreError.appGroupNotConfigured
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let sanitizedKey = sanitizeKey(key)
|
|
40
|
+
let fileURL = directory.appendingPathComponent(sanitizedKey)
|
|
41
|
+
|
|
42
|
+
// Write atomically to ensure the file is fully written before it becomes visible
|
|
43
|
+
try data.write(to: fileURL, options: .atomic)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// Load a preloaded image from App Group storage
|
|
47
|
+
/// - Parameter key: The key/name of the image
|
|
48
|
+
/// - Returns: The UIImage if found, nil otherwise
|
|
49
|
+
public static func loadImage(key: String) -> UIImage? {
|
|
50
|
+
guard let directory = imageDirectory() else { return nil }
|
|
51
|
+
|
|
52
|
+
let sanitizedKey = sanitizeKey(key)
|
|
53
|
+
let fileURL = directory.appendingPathComponent(sanitizedKey)
|
|
54
|
+
|
|
55
|
+
guard FileManager.default.fileExists(atPath: fileURL.path),
|
|
56
|
+
let data = try? Data(contentsOf: fileURL),
|
|
57
|
+
let image = UIImage(data: data)
|
|
58
|
+
else { return nil }
|
|
59
|
+
|
|
60
|
+
return image
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Check if a preloaded image exists
|
|
64
|
+
/// - Parameter key: The key/name of the image
|
|
65
|
+
/// - Returns: true if the image exists in App Group storage
|
|
66
|
+
public static func imageExists(key: String) -> Bool {
|
|
67
|
+
guard let directory = imageDirectory() else { return false }
|
|
68
|
+
|
|
69
|
+
let sanitizedKey = sanitizeKey(key)
|
|
70
|
+
let fileURL = directory.appendingPathComponent(sanitizedKey)
|
|
71
|
+
|
|
72
|
+
return FileManager.default.fileExists(atPath: fileURL.path)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Remove a preloaded image from App Group storage
|
|
76
|
+
/// - Parameter key: The key/name of the image to remove
|
|
77
|
+
public static func removeImage(key: String) {
|
|
78
|
+
guard let directory = imageDirectory() else { return }
|
|
79
|
+
|
|
80
|
+
let sanitizedKey = sanitizeKey(key)
|
|
81
|
+
let fileURL = directory.appendingPathComponent(sanitizedKey)
|
|
82
|
+
|
|
83
|
+
try? FileManager.default.removeItem(at: fileURL)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Remove multiple preloaded images
|
|
87
|
+
/// - Parameter keys: The keys/names of the images to remove
|
|
88
|
+
public static func removeImages(keys: [String]) {
|
|
89
|
+
for key in keys {
|
|
90
|
+
removeImage(key: key)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// Clear all preloaded images from App Group storage
|
|
95
|
+
public static func clearAll() {
|
|
96
|
+
guard let directory = imageDirectory() else { return }
|
|
97
|
+
|
|
98
|
+
try? FileManager.default.removeItem(at: directory)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Sanitize the key to be a valid filename
|
|
102
|
+
private static func sanitizeKey(_ key: String) -> String {
|
|
103
|
+
// Replace any characters that might cause issues in filenames
|
|
104
|
+
let invalidChars = CharacterSet(charactersIn: "/\\:*?\"<>|")
|
|
105
|
+
return key.components(separatedBy: invalidChars).joined(separator: "_")
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Errors that can occur during image store operations
|
|
110
|
+
public enum VoltraImageStoreError: Error, LocalizedError {
|
|
111
|
+
case appGroupNotConfigured
|
|
112
|
+
|
|
113
|
+
public var errorDescription: String? {
|
|
114
|
+
switch self {
|
|
115
|
+
case .appGroupNotConfigured:
|
|
116
|
+
return "App Group not configured. Set 'groupIdentifier' in the Voltra config plugin."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Matches `@use-voltra/expo-plugin` `localePick` fallback order for bundled widget initial JSON.
|
|
4
|
+
public enum VoltraInitialStateLocale {
|
|
5
|
+
public static func pickJson(from perLocale: [String: String], preferredLanguages: [String]) -> String? {
|
|
6
|
+
let entries = perLocale.filter { !$0.value.isEmpty }
|
|
7
|
+
if entries.isEmpty {
|
|
8
|
+
return nil
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
func normalize(_ tag: String) -> String {
|
|
12
|
+
tag.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
13
|
+
.lowercased()
|
|
14
|
+
.replacingOccurrences(of: "_", with: "-")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
var byNorm: [String: String] = [:]
|
|
18
|
+
for (k, v) in entries {
|
|
19
|
+
byNorm[normalize(k)] = v
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for pref in preferredLanguages {
|
|
23
|
+
let n = normalize(pref)
|
|
24
|
+
if let direct = byNorm[n] {
|
|
25
|
+
return direct
|
|
26
|
+
}
|
|
27
|
+
let lang = n.split(separator: "-").first.map(String.init) ?? n
|
|
28
|
+
for (key, val) in entries {
|
|
29
|
+
let kn = normalize(key)
|
|
30
|
+
let keyLang = kn.split(separator: "-").first.map(String.init) ?? kn
|
|
31
|
+
if keyLang == lang {
|
|
32
|
+
return val
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if let en = byNorm["en"] {
|
|
38
|
+
return en
|
|
39
|
+
}
|
|
40
|
+
if let def = byNorm["__default"] {
|
|
41
|
+
return def
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let sorted = entries.keys.sorted()
|
|
45
|
+
guard let firstKey = sorted.first else {
|
|
46
|
+
return nil
|
|
47
|
+
}
|
|
48
|
+
return entries[firstKey]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static func preferredLanguageTags() -> [String] {
|
|
52
|
+
Locale.preferredLanguages
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import ActivityKit
|
|
2
|
+
import AppIntents
|
|
3
|
+
|
|
4
|
+
public struct VoltraInteractionIntent: LiveActivityIntent {
|
|
5
|
+
public static var title: LocalizedStringResource = "Interact"
|
|
6
|
+
public static var isDiscoverable: Bool = false
|
|
7
|
+
|
|
8
|
+
/// The ID of the activity
|
|
9
|
+
@Parameter(title: "Activity ID")
|
|
10
|
+
var activityId: String
|
|
11
|
+
|
|
12
|
+
/// The ID of the component in your JSON (e.g., "button_1", "pause_btn")
|
|
13
|
+
@Parameter(title: "Component ID")
|
|
14
|
+
var componentId: String
|
|
15
|
+
|
|
16
|
+
// Optional: Only if you need to pass extra data (like "true/false" or "toggle")
|
|
17
|
+
@Parameter(title: "Payload")
|
|
18
|
+
var payload: String?
|
|
19
|
+
|
|
20
|
+
public init() {}
|
|
21
|
+
|
|
22
|
+
public init(activityId: String, componentId: String, payload: String? = nil) {
|
|
23
|
+
self.activityId = activityId
|
|
24
|
+
self.componentId = componentId
|
|
25
|
+
self.payload = payload
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public func perform() async throws -> some IntentResult {
|
|
29
|
+
VoltraEventBus.shared.send(
|
|
30
|
+
.interaction(
|
|
31
|
+
source: activityId,
|
|
32
|
+
identifier: componentId,
|
|
33
|
+
payload: payload
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return .result()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import os
|
|
3
|
+
import Security
|
|
4
|
+
|
|
5
|
+
/// Shared Keychain helper for securely storing and reading widget server credentials.
|
|
6
|
+
/// Used by both the main app (to write credentials) and the widget extension (to read them).
|
|
7
|
+
public enum VoltraKeychainHelper {
|
|
8
|
+
/// Keychain service identifier for Voltra widget credentials
|
|
9
|
+
private static let service = "voltra-widget-server-credentials"
|
|
10
|
+
|
|
11
|
+
/// Key for the auth token
|
|
12
|
+
private static let tokenKey = "auth_token"
|
|
13
|
+
|
|
14
|
+
/// Key for additional headers (stored as JSON)
|
|
15
|
+
private static let headersKey = "custom_headers"
|
|
16
|
+
|
|
17
|
+
/// Get the Keychain Access Group from Info.plist (set by the config plugin)
|
|
18
|
+
private static func keychainGroup() -> String? {
|
|
19
|
+
VoltraConfig.keychainGroup()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// MARK: - Token Storage
|
|
23
|
+
|
|
24
|
+
/// Save an auth token to the shared Keychain.
|
|
25
|
+
/// Called from the main app after user login.
|
|
26
|
+
@discardableResult
|
|
27
|
+
public static func saveToken(_ token: String) -> Bool {
|
|
28
|
+
guard let data = token.data(using: .utf8) else { return false }
|
|
29
|
+
|
|
30
|
+
// Delete existing token first
|
|
31
|
+
deleteToken()
|
|
32
|
+
|
|
33
|
+
var query: [String: Any] = [
|
|
34
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
35
|
+
kSecAttrService as String: service,
|
|
36
|
+
kSecAttrAccount as String: tokenKey,
|
|
37
|
+
kSecValueData as String: data,
|
|
38
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
// Add access group if configured (for sharing between app and extension)
|
|
42
|
+
if let group = keychainGroup() {
|
|
43
|
+
query[kSecAttrAccessGroup as String] = group
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let status = SecItemAdd(query as CFDictionary, nil)
|
|
47
|
+
if status != errSecSuccess {
|
|
48
|
+
VoltraLogger.keychain.error("Failed to save token: \(status)")
|
|
49
|
+
}
|
|
50
|
+
return status == errSecSuccess
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Read the auth token from the shared Keychain.
|
|
54
|
+
/// Called from the widget extension's TimelineProvider.
|
|
55
|
+
public static func readToken() -> String? {
|
|
56
|
+
var query: [String: Any] = [
|
|
57
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
58
|
+
kSecAttrService as String: service,
|
|
59
|
+
kSecAttrAccount as String: tokenKey,
|
|
60
|
+
kSecReturnData as String: true,
|
|
61
|
+
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
if let group = keychainGroup() {
|
|
65
|
+
query[kSecAttrAccessGroup as String] = group
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
var item: CFTypeRef?
|
|
69
|
+
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
|
70
|
+
|
|
71
|
+
guard status == errSecSuccess, let data = item as? Data else {
|
|
72
|
+
if status != errSecItemNotFound {
|
|
73
|
+
VoltraLogger.keychain.error("Failed to read token: \(status)")
|
|
74
|
+
}
|
|
75
|
+
return nil
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return String(data: data, encoding: .utf8)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Delete the auth token from the shared Keychain.
|
|
82
|
+
@discardableResult
|
|
83
|
+
public static func deleteToken() -> Bool {
|
|
84
|
+
var query: [String: Any] = [
|
|
85
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
86
|
+
kSecAttrService as String: service,
|
|
87
|
+
kSecAttrAccount as String: tokenKey,
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
if let group = keychainGroup() {
|
|
91
|
+
query[kSecAttrAccessGroup as String] = group
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let status = SecItemDelete(query as CFDictionary)
|
|
95
|
+
return status == errSecSuccess || status == errSecItemNotFound
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// MARK: - Custom Headers Storage
|
|
99
|
+
|
|
100
|
+
/// Save additional custom headers to the shared Keychain.
|
|
101
|
+
@discardableResult
|
|
102
|
+
public static func saveHeaders(_ headers: [String: String]) -> Bool {
|
|
103
|
+
guard let data = try? JSONSerialization.data(withJSONObject: headers) else { return false }
|
|
104
|
+
|
|
105
|
+
// Delete existing headers first
|
|
106
|
+
deleteHeaders()
|
|
107
|
+
|
|
108
|
+
var query: [String: Any] = [
|
|
109
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
110
|
+
kSecAttrService as String: service,
|
|
111
|
+
kSecAttrAccount as String: headersKey,
|
|
112
|
+
kSecValueData as String: data,
|
|
113
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
if let group = keychainGroup() {
|
|
117
|
+
query[kSecAttrAccessGroup as String] = group
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let status = SecItemAdd(query as CFDictionary, nil)
|
|
121
|
+
if status != errSecSuccess {
|
|
122
|
+
VoltraLogger.keychain.error("Failed to save headers: \(status)")
|
|
123
|
+
}
|
|
124
|
+
return status == errSecSuccess
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// Read custom headers from the shared Keychain.
|
|
128
|
+
public static func readHeaders() -> [String: String]? {
|
|
129
|
+
var query: [String: Any] = [
|
|
130
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
131
|
+
kSecAttrService as String: service,
|
|
132
|
+
kSecAttrAccount as String: headersKey,
|
|
133
|
+
kSecReturnData as String: true,
|
|
134
|
+
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
if let group = keychainGroup() {
|
|
138
|
+
query[kSecAttrAccessGroup as String] = group
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var item: CFTypeRef?
|
|
142
|
+
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
|
143
|
+
|
|
144
|
+
guard status == errSecSuccess,
|
|
145
|
+
let data = item as? Data,
|
|
146
|
+
let headers = try? JSONSerialization.jsonObject(with: data) as? [String: String]
|
|
147
|
+
else {
|
|
148
|
+
return nil
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return headers
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// Delete custom headers from the shared Keychain.
|
|
155
|
+
@discardableResult
|
|
156
|
+
public static func deleteHeaders() -> Bool {
|
|
157
|
+
var query: [String: Any] = [
|
|
158
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
159
|
+
kSecAttrService as String: service,
|
|
160
|
+
kSecAttrAccount as String: headersKey,
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
if let group = keychainGroup() {
|
|
164
|
+
query[kSecAttrAccessGroup as String] = group
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let status = SecItemDelete(query as CFDictionary)
|
|
168
|
+
return status == errSecSuccess || status == errSecItemNotFound
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// MARK: - Convenience
|
|
172
|
+
|
|
173
|
+
/// Clear all Voltra widget server credentials from the Keychain.
|
|
174
|
+
public static func clearAll() {
|
|
175
|
+
deleteToken()
|
|
176
|
+
deleteHeaders()
|
|
177
|
+
}
|
|
178
|
+
}
|