@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,113 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// The parsed root payload for a Live Activity update
|
|
4
|
+
/// Handles the one-time JSON parsing and region extraction
|
|
5
|
+
public struct VoltraLiveActivityPayload: Hashable {
|
|
6
|
+
/// Parsed UI trees for each region
|
|
7
|
+
public let regions: [VoltraRegion: [VoltraNode]]
|
|
8
|
+
|
|
9
|
+
/// Optional tint color for Dynamic Island keyline
|
|
10
|
+
public let keylineTint: String?
|
|
11
|
+
|
|
12
|
+
/// Optional background tint for Lock Screen
|
|
13
|
+
public let activityBackgroundTint: String?
|
|
14
|
+
|
|
15
|
+
/// Whether this payload represents an unsupported version (renders empty)
|
|
16
|
+
public let isUnsupportedVersion: Bool
|
|
17
|
+
|
|
18
|
+
/// Parse from decompressed JSON string (called once per update)
|
|
19
|
+
public init(jsonString: String) throws {
|
|
20
|
+
let root = try JSONValue.parse(from: jsonString)
|
|
21
|
+
|
|
22
|
+
// Migrate to current version if needed
|
|
23
|
+
guard let migrated = try VoltraPayloadMigrator.migrateToCurrentVersion(root) else {
|
|
24
|
+
// Unsupported version (future version) - render empty
|
|
25
|
+
regions = [:]
|
|
26
|
+
keylineTint = nil
|
|
27
|
+
activityBackgroundTint = nil
|
|
28
|
+
isUnsupportedVersion = true
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Extract regions directly from the parsed tree
|
|
33
|
+
regions = try Self.extractRegions(from: migrated)
|
|
34
|
+
keylineTint = migrated["isl_keyline_tint"]?.stringValue
|
|
35
|
+
activityBackgroundTint = migrated["ls_background_tint"]?.stringValue
|
|
36
|
+
isUnsupportedVersion = false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Extract regions from the parsed JSON tree
|
|
40
|
+
private static func extractRegions(from root: JSONValue) throws -> [VoltraRegion: [VoltraNode]] {
|
|
41
|
+
var regions: [VoltraRegion: [VoltraNode]] = [:]
|
|
42
|
+
|
|
43
|
+
// Handle array case (same UI for all regions)
|
|
44
|
+
if case .array = root {
|
|
45
|
+
let nodes = try parseNodes(from: root, stylesheet: nil, sharedElements: nil)
|
|
46
|
+
for region in VoltraRegion.allCases {
|
|
47
|
+
regions[region] = nodes
|
|
48
|
+
}
|
|
49
|
+
return regions
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Handle object case (region-specific UIs)
|
|
53
|
+
guard case let .object(rootObject) = root else {
|
|
54
|
+
throw NSError(domain: "VoltraLiveActivityPayload",
|
|
55
|
+
code: -1,
|
|
56
|
+
userInfo: [NSLocalizedDescriptionKey: "Invalid root JSON type"])
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Extract the shared stylesheet from root (key "s")
|
|
60
|
+
let stylesheet = extractStylesheet(from: rootObject)
|
|
61
|
+
|
|
62
|
+
// Extract the shared elements from root (key "e") for element deduplication
|
|
63
|
+
let sharedElements = extractSharedElements(from: rootObject)
|
|
64
|
+
|
|
65
|
+
// Extract components for each region
|
|
66
|
+
for region in VoltraRegion.allCases {
|
|
67
|
+
if let regionValue = rootObject[region.jsonKey] {
|
|
68
|
+
let nodes = try parseNodes(from: regionValue, stylesheet: stylesheet, sharedElements: sharedElements)
|
|
69
|
+
regions[region] = nodes
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return regions
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Parse an array of JSON values into VoltraNodes
|
|
77
|
+
private static func parseNodes(from value: JSONValue, stylesheet: [[String: JSONValue]]?, sharedElements: [JSONValue]?) throws -> [VoltraNode] {
|
|
78
|
+
if case let .array(nodeArray) = value {
|
|
79
|
+
return try nodeArray.compactMap { nodeJson in
|
|
80
|
+
guard case .object = nodeJson else { return nil }
|
|
81
|
+
return try VoltraNode(from: nodeJson, stylesheet: stylesheet, sharedElements: sharedElements)
|
|
82
|
+
}
|
|
83
|
+
} else if case .object = value {
|
|
84
|
+
// Single node wrapped in array
|
|
85
|
+
return try [VoltraNode(from: value, stylesheet: stylesheet, sharedElements: sharedElements)]
|
|
86
|
+
} else {
|
|
87
|
+
return []
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Extract the shared stylesheet from root
|
|
92
|
+
private static func extractStylesheet(from root: [String: JSONValue]) -> [[String: JSONValue]]? {
|
|
93
|
+
guard case let .array(stylesheetArray) = root["s"] else {
|
|
94
|
+
return nil
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Convert JSONValue array to [[String: JSONValue]]
|
|
98
|
+
return stylesheetArray.compactMap { item in
|
|
99
|
+
if case let .object(dict) = item {
|
|
100
|
+
return dict
|
|
101
|
+
}
|
|
102
|
+
return nil
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Extract the shared elements array from root (for element deduplication)
|
|
107
|
+
private static func extractSharedElements(from root: [String: JSONValue]) -> [JSONValue]? {
|
|
108
|
+
guard case let .array(elementsArray) = root["e"] else {
|
|
109
|
+
return nil
|
|
110
|
+
}
|
|
111
|
+
return elementsArray
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
/// Centralized loggers for the Voltra module.
|
|
4
|
+
///
|
|
5
|
+
/// Each category maps to a distinct domain of concern so logs can be filtered
|
|
6
|
+
/// independently in Console.app or via `log stream --predicate 'subsystem == "com.voltra"'`.
|
|
7
|
+
enum VoltraLogger {
|
|
8
|
+
private static let subsystem = "com.voltra"
|
|
9
|
+
|
|
10
|
+
/// Expo module boundary (JS → native calls, error remapping)
|
|
11
|
+
static let module = Logger(subsystem: subsystem, category: "module")
|
|
12
|
+
|
|
13
|
+
/// Widget data, timelines, server credentials, WidgetCenter reloads
|
|
14
|
+
static let widget = Logger(subsystem: subsystem, category: "widget")
|
|
15
|
+
|
|
16
|
+
/// Live Activity lifecycle (create, update, end, reload)
|
|
17
|
+
static let activity = Logger(subsystem: subsystem, category: "liveActivity")
|
|
18
|
+
|
|
19
|
+
/// Image preloading and the shared image store
|
|
20
|
+
static let image = Logger(subsystem: subsystem, category: "image")
|
|
21
|
+
|
|
22
|
+
/// VoltraEventBus and VoltraPersistentEventQueue
|
|
23
|
+
static let event = Logger(subsystem: subsystem, category: "event")
|
|
24
|
+
|
|
25
|
+
/// Keychain reads and writes
|
|
26
|
+
static let keychain = Logger(subsystem: subsystem, category: "keychain")
|
|
27
|
+
|
|
28
|
+
/// UserDefaults / shared storage (VoltraWidgetDefaults)
|
|
29
|
+
static let storage = Logger(subsystem: subsystem, category: "storage")
|
|
30
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
/// Represents anything that can be rendered (like ReactNode)
|
|
5
|
+
public indirect enum VoltraNode: Hashable, View {
|
|
6
|
+
/// A component element
|
|
7
|
+
case element(VoltraElement)
|
|
8
|
+
|
|
9
|
+
/// Multiple nodes (fragment/array)
|
|
10
|
+
case array([VoltraNode])
|
|
11
|
+
|
|
12
|
+
/// Plain text content
|
|
13
|
+
case text(String)
|
|
14
|
+
|
|
15
|
+
/// Nothing to render
|
|
16
|
+
case empty
|
|
17
|
+
|
|
18
|
+
// MARK: - Initialization
|
|
19
|
+
|
|
20
|
+
/// Initialize from JSONValue (handles all types)
|
|
21
|
+
/// - Parameters:
|
|
22
|
+
/// - json: The JSON value to parse
|
|
23
|
+
/// - stylesheet: Optional shared stylesheet for style deduplication
|
|
24
|
+
/// - sharedElements: Optional shared elements array for element deduplication
|
|
25
|
+
public init(from json: JSONValue, stylesheet: [[String: JSONValue]]? = nil, sharedElements: [JSONValue]? = nil) {
|
|
26
|
+
switch json {
|
|
27
|
+
case let .string(text):
|
|
28
|
+
self = .text(text)
|
|
29
|
+
case let .int(num):
|
|
30
|
+
self = .text(String(num))
|
|
31
|
+
case let .double(num):
|
|
32
|
+
self = .text(String(num))
|
|
33
|
+
case let .bool(val):
|
|
34
|
+
self = .text(String(val))
|
|
35
|
+
case .null:
|
|
36
|
+
self = .empty
|
|
37
|
+
case let .array(items):
|
|
38
|
+
let nodes = items.map { VoltraNode(from: $0, stylesheet: stylesheet, sharedElements: sharedElements) }.filter { !$0.isEmpty }
|
|
39
|
+
self = nodes.isEmpty ? .empty : .array(nodes)
|
|
40
|
+
case let .object(dict):
|
|
41
|
+
// Check for element reference ($r key) and resolve from shared elements
|
|
42
|
+
if let refIndex = dict["$r"]?.intValue,
|
|
43
|
+
let sharedElements = sharedElements,
|
|
44
|
+
refIndex >= 0, refIndex < sharedElements.count
|
|
45
|
+
{
|
|
46
|
+
// Resolve reference by parsing the shared element
|
|
47
|
+
self = VoltraNode(from: sharedElements[refIndex], stylesheet: stylesheet, sharedElements: sharedElements)
|
|
48
|
+
} else if let element = VoltraElement(from: json, stylesheet: stylesheet, sharedElements: sharedElements) {
|
|
49
|
+
self = .element(element)
|
|
50
|
+
} else {
|
|
51
|
+
self = .empty
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Check if node represents nothing
|
|
57
|
+
public var isEmpty: Bool {
|
|
58
|
+
if case .empty = self { return true }
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Parse a VoltraNode from JSON, extracting stylesheet and sharedElements if present
|
|
63
|
+
/// This is a convenience factory that handles the common pattern of extracting
|
|
64
|
+
/// stylesheet ("s") and sharedElements ("e") from the root JSON object.
|
|
65
|
+
/// - Parameter json: The JSON value to parse
|
|
66
|
+
/// - Returns: A parsed VoltraNode
|
|
67
|
+
public static func parse(from json: JSONValue) -> VoltraNode {
|
|
68
|
+
var stylesheet: [[String: JSONValue]]? = nil
|
|
69
|
+
var sharedElements: [JSONValue]? = nil
|
|
70
|
+
|
|
71
|
+
if case let .object(rootObject) = json {
|
|
72
|
+
// Extract stylesheet (key "s")
|
|
73
|
+
if case let .array(stylesheetArray) = rootObject["s"] {
|
|
74
|
+
stylesheet = stylesheetArray.compactMap { item in
|
|
75
|
+
if case let .object(dict) = item { return dict }
|
|
76
|
+
return nil
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Extract shared elements (key "e")
|
|
80
|
+
if case let .array(elementsArray) = rootObject["e"] {
|
|
81
|
+
sharedElements = elementsArray
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return VoltraNode(from: json, stylesheet: stylesheet, sharedElements: sharedElements)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// MARK: - View conformance
|
|
89
|
+
|
|
90
|
+
public var body: some View {
|
|
91
|
+
switch self {
|
|
92
|
+
case let .element(element):
|
|
93
|
+
VoltraElementView(element: element)
|
|
94
|
+
case let .array(nodes):
|
|
95
|
+
// Use stable identifiers: prefer element.id, fall back to index
|
|
96
|
+
let items: [(id: String, node: VoltraNode)] = nodes.enumerated().map { offset, node in
|
|
97
|
+
let id: String
|
|
98
|
+
if case let .element(element) = node, let elementId = element.id {
|
|
99
|
+
id = elementId
|
|
100
|
+
} else {
|
|
101
|
+
id = "idx_\(offset)"
|
|
102
|
+
}
|
|
103
|
+
return (id: id, node: node)
|
|
104
|
+
}
|
|
105
|
+
ForEach(items, id: \.id) { item in
|
|
106
|
+
item.node
|
|
107
|
+
}
|
|
108
|
+
case let .text(text):
|
|
109
|
+
Text(text)
|
|
110
|
+
case .empty:
|
|
111
|
+
EmptyView()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// View that renders a VoltraElement based on its type
|
|
117
|
+
struct VoltraElementView: View {
|
|
118
|
+
let element: VoltraElement
|
|
119
|
+
|
|
120
|
+
var body: some View {
|
|
121
|
+
switch element.type {
|
|
122
|
+
case "Button":
|
|
123
|
+
VoltraButton(element)
|
|
124
|
+
|
|
125
|
+
case "Link":
|
|
126
|
+
VoltraLink(element)
|
|
127
|
+
|
|
128
|
+
case "VStack":
|
|
129
|
+
VoltraVStack(element)
|
|
130
|
+
|
|
131
|
+
case "HStack":
|
|
132
|
+
VoltraHStack(element)
|
|
133
|
+
|
|
134
|
+
case "View":
|
|
135
|
+
VoltraFlexView(element)
|
|
136
|
+
|
|
137
|
+
case "ZStack":
|
|
138
|
+
VoltraZStack(element)
|
|
139
|
+
|
|
140
|
+
case "Text":
|
|
141
|
+
VoltraText(element)
|
|
142
|
+
|
|
143
|
+
case "Image":
|
|
144
|
+
VoltraImage(element)
|
|
145
|
+
|
|
146
|
+
case "Symbol":
|
|
147
|
+
VoltraSymbol(element)
|
|
148
|
+
|
|
149
|
+
case "Divider":
|
|
150
|
+
VoltraDivider(element)
|
|
151
|
+
|
|
152
|
+
case "Spacer":
|
|
153
|
+
VoltraSpacer(element)
|
|
154
|
+
|
|
155
|
+
case "Label":
|
|
156
|
+
VoltraLabel(element)
|
|
157
|
+
|
|
158
|
+
case "Toggle":
|
|
159
|
+
VoltraToggle(element)
|
|
160
|
+
|
|
161
|
+
case "Gauge":
|
|
162
|
+
VoltraGauge(element)
|
|
163
|
+
|
|
164
|
+
case "LinearProgressView":
|
|
165
|
+
VoltraLinearProgressView(element)
|
|
166
|
+
|
|
167
|
+
case "CircularProgressView":
|
|
168
|
+
VoltraCircularProgressView(element)
|
|
169
|
+
|
|
170
|
+
case "Timer":
|
|
171
|
+
VoltraTimer(element)
|
|
172
|
+
|
|
173
|
+
case "GroupBox":
|
|
174
|
+
VoltraGroupBox(element)
|
|
175
|
+
|
|
176
|
+
case "LinearGradient":
|
|
177
|
+
VoltraLinearGradient(element)
|
|
178
|
+
|
|
179
|
+
case "GlassContainer":
|
|
180
|
+
VoltraGlassContainer(element)
|
|
181
|
+
|
|
182
|
+
case "Mask":
|
|
183
|
+
VoltraMask(element)
|
|
184
|
+
|
|
185
|
+
case "Chart":
|
|
186
|
+
if #available(iOS 16.0, macOS 13.0, *) {
|
|
187
|
+
VoltraChart(element)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
default:
|
|
191
|
+
EmptyView()
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Error types for payload migration
|
|
4
|
+
public enum VoltraPayloadError: Error {
|
|
5
|
+
case missingVersion
|
|
6
|
+
case invalidPayloadStructure
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/// Protocol for migrating payloads from one version to the next
|
|
10
|
+
public protocol VoltraPayloadMigration {
|
|
11
|
+
/// The source version this migration upgrades FROM
|
|
12
|
+
static var fromVersion: Int { get }
|
|
13
|
+
|
|
14
|
+
/// The target version this migration upgrades TO
|
|
15
|
+
static var toVersion: Int { get }
|
|
16
|
+
|
|
17
|
+
/// Migrate the raw JSON from the source version to the target version
|
|
18
|
+
static func migrate(_ json: JSONValue) throws -> JSONValue
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Manages payload version migrations
|
|
22
|
+
public enum VoltraPayloadMigrator {
|
|
23
|
+
/// Current (latest) payload version
|
|
24
|
+
public static let currentVersion = 1
|
|
25
|
+
|
|
26
|
+
/// Registered migrations, keyed by source version
|
|
27
|
+
/// When adding a new version:
|
|
28
|
+
/// 1. Increment currentVersion
|
|
29
|
+
/// 2. Add migration: [oldVersion: VOldToVNewMigration.self]
|
|
30
|
+
private static let migrations: [Int: any VoltraPayloadMigration.Type] = [:
|
|
31
|
+
// Empty for v1, add as needed:
|
|
32
|
+
// 1: V1ToV2Migration.self,
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
/// Migrate a payload to the current version
|
|
36
|
+
/// - Parameter json: The raw parsed JSON payload
|
|
37
|
+
/// - Returns: Migrated JSON, or nil if version is unsupported (future version)
|
|
38
|
+
public static func migrateToCurrentVersion(_ json: JSONValue) throws -> JSONValue? {
|
|
39
|
+
guard let version = json["v"]?.intValue else {
|
|
40
|
+
throw VoltraPayloadError.missingVersion
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Future version we don't understand - silently ignore
|
|
44
|
+
if version > currentVersion {
|
|
45
|
+
return nil
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var currentJson = json
|
|
49
|
+
var currentVer = version
|
|
50
|
+
|
|
51
|
+
// Apply migrations sequentially until we reach the current version
|
|
52
|
+
while currentVer < currentVersion {
|
|
53
|
+
guard let migration = migrations[currentVer] else {
|
|
54
|
+
// Gap in migration chain - shouldn't happen if migrations are maintained properly
|
|
55
|
+
return nil
|
|
56
|
+
}
|
|
57
|
+
currentJson = try migration.migrate(currentJson)
|
|
58
|
+
currentVer = migration.toVersion
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return currentJson
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
/// Persistent event queue for events that must survive app death (e.g., interactions from widget)
|
|
5
|
+
/// Uses UserDefaults with App Group for cross-process communication
|
|
6
|
+
public enum VoltraPersistentEventQueue {
|
|
7
|
+
private static let queueKey = "Voltra_EventsQueue"
|
|
8
|
+
|
|
9
|
+
/// Write an event to the persistent queue (UserDefaults)
|
|
10
|
+
static func write(_ payload: [String: Any]) {
|
|
11
|
+
guard let group = VoltraConfig.groupIdentifier(),
|
|
12
|
+
let defaults = UserDefaults(suiteName: group),
|
|
13
|
+
JSONSerialization.isValidJSONObject(payload),
|
|
14
|
+
let data = try? JSONSerialization.data(withJSONObject: payload, options: [])
|
|
15
|
+
else {
|
|
16
|
+
VoltraLogger.event.error("Failed to write event — no group identifier or invalid payload")
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let jsonString = String(data: data, encoding: .utf8) ?? "{}"
|
|
21
|
+
|
|
22
|
+
var queue = defaults.array(forKey: queueKey) as? [String] ?? []
|
|
23
|
+
queue.append(jsonString)
|
|
24
|
+
defaults.set(queue, forKey: queueKey)
|
|
25
|
+
defaults.synchronize()
|
|
26
|
+
|
|
27
|
+
let eventName = payload["type"] as? String ?? "unknown"
|
|
28
|
+
VoltraLogger.event.debug("Wrote event: \(eventName)")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Read all events from the persistent queue and clear it
|
|
32
|
+
/// Returns an array of (eventName, eventData) tuples
|
|
33
|
+
static func popAll() -> [(name: String, data: [String: Any])] {
|
|
34
|
+
guard let group = VoltraConfig.groupIdentifier() else {
|
|
35
|
+
VoltraLogger.event.error("popAll: No group identifier found")
|
|
36
|
+
return []
|
|
37
|
+
}
|
|
38
|
+
guard let defaults = UserDefaults(suiteName: group) else {
|
|
39
|
+
VoltraLogger.event.error("popAll: Could not access UserDefaults for group '\(group)'")
|
|
40
|
+
return []
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let queue = defaults.array(forKey: queueKey) as? [String] ?? []
|
|
44
|
+
let eventCount = queue.count
|
|
45
|
+
VoltraLogger.event.debug("popAll: Found \(eventCount) events in queue")
|
|
46
|
+
|
|
47
|
+
// Clear the queue first
|
|
48
|
+
defaults.set([String](), forKey: queueKey)
|
|
49
|
+
defaults.synchronize()
|
|
50
|
+
|
|
51
|
+
// Skip processing if queue is excessively large (stale data)
|
|
52
|
+
if eventCount > 1000 {
|
|
53
|
+
VoltraLogger.event.warning("popAll: Skipping \(eventCount) stale events")
|
|
54
|
+
return []
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Parse JSON strings into event tuples
|
|
58
|
+
return queue.compactMap { jsonString -> (name: String, data: [String: Any])? in
|
|
59
|
+
guard let data = jsonString.data(using: .utf8),
|
|
60
|
+
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
61
|
+
let eventName = dict["type"] as? String
|
|
62
|
+
else { return nil }
|
|
63
|
+
|
|
64
|
+
return (name: eventName, data: dict)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import AppIntents
|
|
2
|
+
import WidgetKit
|
|
3
|
+
|
|
4
|
+
/// An AppIntent that triggers an immediate widget timeline reload.
|
|
5
|
+
/// Used by the native refresh button overlay on server-driven widgets.
|
|
6
|
+
@available(iOS 17.0, *)
|
|
7
|
+
public struct VoltraRefreshIntent: AppIntent {
|
|
8
|
+
public static var title: LocalizedStringResource = "Refresh Widget"
|
|
9
|
+
public static var isDiscoverable: Bool = false
|
|
10
|
+
|
|
11
|
+
@Parameter(title: "Widget ID")
|
|
12
|
+
public var widgetId: String?
|
|
13
|
+
|
|
14
|
+
public init() {}
|
|
15
|
+
|
|
16
|
+
public init(widgetId: String) {
|
|
17
|
+
self.widgetId = widgetId
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public func perform() async throws -> some IntentResult {
|
|
21
|
+
if let widgetId = widgetId {
|
|
22
|
+
let kind = "\(VoltraStorageKeys.widgetKindPrefix)\(widgetId)"
|
|
23
|
+
WidgetCenter.shared.reloadTimelines(ofKind: kind)
|
|
24
|
+
} else {
|
|
25
|
+
WidgetCenter.shared.reloadAllTimelines()
|
|
26
|
+
}
|
|
27
|
+
return .result()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public enum VoltraRegion: String, Codable, Hashable, CaseIterable {
|
|
4
|
+
case lockScreen
|
|
5
|
+
case islandExpandedCenter
|
|
6
|
+
case islandExpandedLeading
|
|
7
|
+
case islandExpandedTrailing
|
|
8
|
+
case islandExpandedBottom
|
|
9
|
+
case islandCompactLeading
|
|
10
|
+
case islandCompactTrailing
|
|
11
|
+
case islandMinimal
|
|
12
|
+
case supplementalActivityFamiliesSmall
|
|
13
|
+
|
|
14
|
+
/// The JSON key for this region in the payload
|
|
15
|
+
public var jsonKey: String {
|
|
16
|
+
switch self {
|
|
17
|
+
case .lockScreen:
|
|
18
|
+
return "ls"
|
|
19
|
+
case .islandExpandedCenter:
|
|
20
|
+
return "isl_exp_c"
|
|
21
|
+
case .islandExpandedLeading:
|
|
22
|
+
return "isl_exp_l"
|
|
23
|
+
case .islandExpandedTrailing:
|
|
24
|
+
return "isl_exp_t"
|
|
25
|
+
case .islandExpandedBottom:
|
|
26
|
+
return "isl_exp_b"
|
|
27
|
+
case .islandCompactLeading:
|
|
28
|
+
return "isl_cmp_l"
|
|
29
|
+
case .islandCompactTrailing:
|
|
30
|
+
return "isl_cmp_t"
|
|
31
|
+
case .islandMinimal:
|
|
32
|
+
return "isl_min"
|
|
33
|
+
case .supplementalActivityFamiliesSmall:
|
|
34
|
+
return "saf_sm"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
/// Errors that can occur during widget persistence operations.
|
|
5
|
+
public enum WidgetError: Error, LocalizedError {
|
|
6
|
+
case appGroupNotConfigured
|
|
7
|
+
case userDefaultsUnavailable
|
|
8
|
+
|
|
9
|
+
public var errorDescription: String? {
|
|
10
|
+
switch self {
|
|
11
|
+
case .appGroupNotConfigured:
|
|
12
|
+
return "App Group not configured. Set 'groupIdentifier' in the Voltra config plugin to use widgets."
|
|
13
|
+
case .userDefaultsUnavailable:
|
|
14
|
+
return "Unable to access UserDefaults for the app group."
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// Low-level UserDefaults CRUD for widget keys.
|
|
20
|
+
/// Shared between the app target (write/clear) and the widget extension target (read).
|
|
21
|
+
///
|
|
22
|
+
/// Write methods throw `WidgetError` to surface configuration problems to the caller.
|
|
23
|
+
/// Read and remove methods are non-throwing: they return nil / no-op when the app group
|
|
24
|
+
/// is not configured, since the widget extension has no way to propagate errors.
|
|
25
|
+
public enum VoltraWidgetDefaults {
|
|
26
|
+
// MARK: - Read
|
|
27
|
+
|
|
28
|
+
public static func widgetJson(for widgetId: String) -> String? {
|
|
29
|
+
try? resolvedDefaults().string(forKey: VoltraStorageKeys.widgetJson(widgetId))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static func deepLinkUrl(for widgetId: String) -> String? {
|
|
33
|
+
try? resolvedDefaults().string(forKey: VoltraStorageKeys.widgetDeepLinkUrl(widgetId))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public static func timelineString(for widgetId: String) -> String? {
|
|
37
|
+
try? resolvedDefaults().string(forKey: VoltraStorageKeys.widgetTimeline(widgetId))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// MARK: - Write
|
|
41
|
+
|
|
42
|
+
public static func setWidgetJson(_ json: String, for widgetId: String, deepLinkUrl: String?) throws {
|
|
43
|
+
let defaults = try resolvedDefaults()
|
|
44
|
+
|
|
45
|
+
let dataSize = json.utf8.count
|
|
46
|
+
if dataSize > VoltraConstants.widgetJsonWarningSizeBytes {
|
|
47
|
+
VoltraLogger.storage.warning("Large widget payload for '\(widgetId)': \(dataSize) bytes (threshold: \(VoltraConstants.widgetJsonWarningSizeBytes) bytes)")
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
defaults.set(json, forKey: VoltraStorageKeys.widgetJson(widgetId))
|
|
51
|
+
|
|
52
|
+
if let url = deepLinkUrl, !url.isEmpty {
|
|
53
|
+
defaults.set(url, forKey: VoltraStorageKeys.widgetDeepLinkUrl(widgetId))
|
|
54
|
+
} else {
|
|
55
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetDeepLinkUrl(widgetId))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
defaults.synchronize()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public static func setTimeline(_ timeline: String, for widgetId: String) throws {
|
|
62
|
+
let defaults = try resolvedDefaults()
|
|
63
|
+
|
|
64
|
+
let dataSize = timeline.utf8.count
|
|
65
|
+
if dataSize > VoltraConstants.timelineWarningSizeBytes {
|
|
66
|
+
VoltraLogger.storage.warning("Large timeline for '\(widgetId)': \(dataSize) bytes (threshold: \(VoltraConstants.timelineWarningSizeBytes) bytes)")
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
defaults.set(timeline, forKey: VoltraStorageKeys.widgetTimeline(widgetId))
|
|
70
|
+
defaults.synchronize()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// MARK: - Remove
|
|
74
|
+
|
|
75
|
+
/// Removes all persisted data (json, deepLinkUrl, timeline) for a single widget.
|
|
76
|
+
/// This is the single source of truth for which keys exist per widget.
|
|
77
|
+
public static func removeAllData(for widgetId: String) {
|
|
78
|
+
guard let defaults = try? resolvedDefaults() else { return }
|
|
79
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetJson(widgetId))
|
|
80
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetDeepLinkUrl(widgetId))
|
|
81
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetTimeline(widgetId))
|
|
82
|
+
defaults.synchronize()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public static func removeTimeline(for widgetId: String) {
|
|
86
|
+
guard let defaults = try? resolvedDefaults() else { return }
|
|
87
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetTimeline(widgetId))
|
|
88
|
+
defaults.synchronize()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Removes all persisted data for every widget listed in the app's Info.plist.
|
|
92
|
+
public static func removeAllWidgets() {
|
|
93
|
+
guard let defaults = try? resolvedDefaults() else { return }
|
|
94
|
+
let widgetIds = Bundle.main.object(forInfoDictionaryKey: VoltraStorageKeys.widgetIds) as? [String] ?? []
|
|
95
|
+
for widgetId in widgetIds {
|
|
96
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetJson(widgetId))
|
|
97
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetDeepLinkUrl(widgetId))
|
|
98
|
+
defaults.removeObject(forKey: VoltraStorageKeys.widgetTimeline(widgetId))
|
|
99
|
+
}
|
|
100
|
+
defaults.synchronize()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// MARK: - Private
|
|
104
|
+
|
|
105
|
+
private static func resolvedDefaults() throws -> UserDefaults {
|
|
106
|
+
guard let groupId = VoltraConfig.groupIdentifier() else {
|
|
107
|
+
throw WidgetError.appGroupNotConfigured
|
|
108
|
+
}
|
|
109
|
+
guard let defaults = UserDefaults(suiteName: groupId) else {
|
|
110
|
+
throw WidgetError.userDefaultsUnavailable
|
|
111
|
+
}
|
|
112
|
+
return defaults
|
|
113
|
+
}
|
|
114
|
+
}
|