@use-voltra/ios-client 2.1.1 → 2.3.0
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 +61 -8
- package/Voltra.podspec +1 -0
- package/build/commonjs/dynamic-widget/api.js +15 -0
- package/build/commonjs/dynamic-widget/api.js.map +1 -0
- package/build/commonjs/events.js +23 -0
- package/build/commonjs/events.js.map +1 -1
- package/build/commonjs/index.js +74 -7
- package/build/commonjs/index.js.map +1 -1
- package/build/commonjs/live-activity/api.js +3 -1
- package/build/commonjs/live-activity/api.js.map +1 -1
- package/build/commonjs/live-activity/dynamic-api.js +173 -0
- package/build/commonjs/live-activity/dynamic-api.js.map +1 -0
- package/build/commonjs/native/NativeVoltra.js.map +1 -1
- package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js +47 -0
- package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
- package/build/commonjs/utils/enableWidgetHotReload.js +8 -11
- package/build/commonjs/utils/enableWidgetHotReload.js.map +1 -1
- package/build/commonjs/utils/useUpdateOnHMR.js +3 -7
- package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -1
- package/build/commonjs/widgets/server-credentials.js +9 -0
- package/build/commonjs/widgets/server-credentials.js.map +1 -1
- package/build/commonjs/widgets/server-update.js +78 -0
- package/build/commonjs/widgets/server-update.js.map +1 -0
- package/build/module/dynamic-widget/api.js +10 -0
- package/build/module/dynamic-widget/api.js.map +1 -0
- package/build/module/events.js +23 -0
- package/build/module/events.js.map +1 -1
- package/build/module/index.js +4 -0
- package/build/module/index.js.map +1 -1
- package/build/module/live-activity/api.js +2 -2
- package/build/module/live-activity/api.js.map +1 -1
- package/build/module/live-activity/dynamic-api.js +167 -0
- package/build/module/live-activity/dynamic-api.js.map +1 -0
- package/build/module/native/NativeVoltra.js.map +1 -1
- package/build/module/utils/enableDynamicLiveActivityHotReload.js +43 -0
- package/build/module/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
- package/build/module/utils/enableWidgetHotReload.js +9 -11
- package/build/module/utils/enableWidgetHotReload.js.map +1 -1
- package/build/module/utils/useUpdateOnHMR.js +3 -7
- package/build/module/utils/useUpdateOnHMR.js.map +1 -1
- package/build/module/widgets/server-credentials.js +9 -0
- package/build/module/widgets/server-credentials.js.map +1 -1
- package/build/module/widgets/server-update.js +72 -0
- package/build/module/widgets/server-update.js.map +1 -0
- package/build/typescript/commonjs/dynamic-widget/api.d.ts +8 -0
- package/build/typescript/commonjs/dynamic-widget/api.d.ts.map +1 -0
- package/build/typescript/commonjs/events.d.ts +7 -0
- package/build/typescript/commonjs/events.d.ts.map +1 -1
- package/build/typescript/commonjs/index.d.ts +4 -0
- package/build/typescript/commonjs/index.d.ts.map +1 -1
- package/build/typescript/commonjs/live-activity/api.d.ts +7 -0
- package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -1
- package/build/typescript/commonjs/live-activity/dynamic-api.d.ts +54 -0
- package/build/typescript/commonjs/live-activity/dynamic-api.d.ts.map +1 -0
- package/build/typescript/commonjs/native/NativeVoltra.d.ts +21 -0
- package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -1
- package/build/typescript/commonjs/types.d.ts +1 -1
- package/build/typescript/commonjs/types.d.ts.map +1 -1
- package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
- package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
- package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts +5 -7
- package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts.map +1 -1
- package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts +0 -3
- package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -1
- package/build/typescript/commonjs/widgets/server-credentials.d.ts +8 -0
- package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -1
- package/build/typescript/commonjs/widgets/server-update.d.ts +64 -0
- package/build/typescript/commonjs/widgets/server-update.d.ts.map +1 -0
- package/build/typescript/module/dynamic-widget/api.d.ts +8 -0
- package/build/typescript/module/dynamic-widget/api.d.ts.map +1 -0
- package/build/typescript/module/events.d.ts +7 -0
- package/build/typescript/module/events.d.ts.map +1 -1
- package/build/typescript/module/index.d.ts +4 -0
- package/build/typescript/module/index.d.ts.map +1 -1
- package/build/typescript/module/live-activity/api.d.ts +7 -0
- package/build/typescript/module/live-activity/api.d.ts.map +1 -1
- package/build/typescript/module/live-activity/dynamic-api.d.ts +54 -0
- package/build/typescript/module/live-activity/dynamic-api.d.ts.map +1 -0
- package/build/typescript/module/native/NativeVoltra.d.ts +21 -0
- package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -1
- package/build/typescript/module/types.d.ts +1 -1
- package/build/typescript/module/types.d.ts.map +1 -1
- package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
- package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
- package/build/typescript/module/utils/enableWidgetHotReload.d.ts +5 -7
- package/build/typescript/module/utils/enableWidgetHotReload.d.ts.map +1 -1
- package/build/typescript/module/utils/useUpdateOnHMR.d.ts +0 -3
- package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -1
- package/build/typescript/module/widgets/server-credentials.d.ts +8 -0
- package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -1
- package/build/typescript/module/widgets/server-update.d.ts +64 -0
- package/build/typescript/module/widgets/server-update.d.ts.map +1 -0
- package/expo-plugin/build/cjs/constants.js +20 -1
- package/expo-plugin/build/cjs/constants.js.map +1 -1
- package/expo-plugin/build/cjs/index.js +9 -1
- package/expo-plugin/build/cjs/index.js.map +1 -1
- package/expo-plugin/build/cjs/ios/index.js +1 -0
- package/expo-plugin/build/cjs/ios/index.js.map +1 -1
- package/expo-plugin/build/cjs/ios/infoPlist.js +28 -5
- package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -1
- package/expo-plugin/build/cjs/ios/serverUpdate.js +25 -0
- package/expo-plugin/build/cjs/ios/serverUpdate.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/clientRendered.js +4 -4
- package/expo-plugin/build/cjs/ios-widget/clientRendered.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js +5 -5
- package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js +130 -0
- package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/index.js +9 -2
- package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +6 -3
- package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/files/manifest.js +24 -0
- package/expo-plugin/build/cjs/ios-widget/files/manifest.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js +7 -0
- package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/files/swift.js +56 -26
- package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/index.js +9 -3
- package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/podfile.js +38 -12
- package/expo-plugin/build/cjs/ios-widget/podfile.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +34 -22
- package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +194 -118
- package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js +30 -22
- package/expo-plugin/build/cjs/ios-widget/xcode/configurationList.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/fileReferences.js +50 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/fileReferences.js.map +1 -0
- package/expo-plugin/build/cjs/ios-widget/xcode/groups.js +45 -43
- package/expo-plugin/build/cjs/ios-widget/xcode/groups.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/index.js +93 -91
- package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js +41 -39
- package/expo-plugin/build/cjs/ios-widget/xcode/mainAppSettings.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js +2 -2
- package/expo-plugin/build/cjs/ios-widget/xcode/productFile.js.map +1 -1
- package/expo-plugin/build/cjs/ios-widget/xcode/target.js +29 -63
- package/expo-plugin/build/cjs/ios-widget/xcode/target.js.map +1 -1
- package/expo-plugin/build/cjs/utils/urlScheme.js +36 -14
- package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -1
- package/expo-plugin/build/cjs/validation.js +54 -0
- package/expo-plugin/build/cjs/validation.js.map +1 -1
- package/expo-plugin/build/esm/constants.js +17 -0
- package/expo-plugin/build/esm/constants.js.map +1 -1
- package/expo-plugin/build/esm/index.js +9 -1
- package/expo-plugin/build/esm/index.js.map +1 -1
- package/expo-plugin/build/esm/ios/index.js +1 -0
- package/expo-plugin/build/esm/ios/index.js.map +1 -1
- package/expo-plugin/build/esm/ios/infoPlist.js +28 -5
- package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -1
- package/expo-plugin/build/esm/ios/serverUpdate.js +21 -0
- package/expo-plugin/build/esm/ios/serverUpdate.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/clientRendered.js +5 -5
- package/expo-plugin/build/esm/ios-widget/clientRendered.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js +6 -6
- package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js +122 -0
- package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/index.js +10 -3
- package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +6 -3
- package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/files/manifest.js +23 -1
- package/expo-plugin/build/esm/ios-widget/files/manifest.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/files/swift-utils.js +4 -0
- package/expo-plugin/build/esm/ios-widget/files/swift-utils.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/files/swift.js +50 -20
- package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/index.js +9 -3
- package/expo-plugin/build/esm/ios-widget/index.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/podfile.js +36 -11
- package/expo-plugin/build/esm/ios-widget/podfile.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/widgetPlist.js +34 -22
- package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +194 -117
- package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js +31 -22
- package/expo-plugin/build/esm/ios-widget/xcode/configurationList.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/fileReferences.js +45 -0
- package/expo-plugin/build/esm/ios-widget/xcode/fileReferences.js.map +1 -0
- package/expo-plugin/build/esm/ios-widget/xcode/groups.js +45 -42
- package/expo-plugin/build/esm/ios-widget/xcode/groups.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/index.js +97 -96
- package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js +41 -39
- package/expo-plugin/build/esm/ios-widget/xcode/mainAppSettings.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/productFile.js +3 -2
- package/expo-plugin/build/esm/ios-widget/xcode/productFile.js.map +1 -1
- package/expo-plugin/build/esm/ios-widget/xcode/target.js +28 -62
- package/expo-plugin/build/esm/ios-widget/xcode/target.js.map +1 -1
- package/expo-plugin/build/esm/utils/urlScheme.js +34 -14
- package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -1
- package/expo-plugin/build/esm/validation.js +54 -1
- package/expo-plugin/build/esm/validation.js.map +1 -1
- package/expo-plugin/build/types/constants.d.ts +10 -1
- package/expo-plugin/build/types/constants.d.ts.map +1 -1
- package/expo-plugin/build/types/index.d.ts +1 -1
- package/expo-plugin/build/types/index.d.ts.map +1 -1
- package/expo-plugin/build/types/ios/index.d.ts +2 -0
- package/expo-plugin/build/types/ios/index.d.ts.map +1 -1
- package/expo-plugin/build/types/ios/infoPlist.d.ts +2 -0
- package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -1
- package/expo-plugin/build/types/ios/serverUpdate.d.ts +11 -0
- package/expo-plugin/build/types/ios/serverUpdate.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/clientRendered.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/clientRenderedPrerender.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts +7 -0
- package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/index.d.ts +3 -1
- package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +2 -1
- package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/files/manifest.d.ts +9 -2
- package/expo-plugin/build/types/ios-widget/files/manifest.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts +2 -0
- package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/files/swift.d.ts +6 -2
- package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/index.d.ts +3 -1
- package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/podfile.d.ts +19 -1
- package/expo-plugin/build/types/ios-widget/podfile.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +6 -8
- package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts +15 -10
- package/expo-plugin/build/types/ios-widget/xcode/configurationList.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/fileReferences.d.ts +16 -0
- package/expo-plugin/build/types/ios-widget/xcode/fileReferences.d.ts.map +1 -0
- package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts +0 -4
- package/expo-plugin/build/types/ios-widget/xcode/groups.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +23 -3
- package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts +16 -4
- package/expo-plugin/build/types/ios-widget/xcode/mainAppSettings.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts +0 -4
- package/expo-plugin/build/types/ios-widget/xcode/productFile.d.ts.map +1 -1
- package/expo-plugin/build/types/ios-widget/xcode/target.d.ts +11 -26
- package/expo-plugin/build/types/ios-widget/xcode/target.d.ts.map +1 -1
- package/expo-plugin/build/types/types.d.ts +23 -4
- package/expo-plugin/build/types/types.d.ts.map +1 -1
- package/expo-plugin/build/types/utils/urlScheme.d.ts +16 -0
- package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -1
- package/expo-plugin/build/types/validation.d.ts +2 -1
- package/expo-plugin/build/types/validation.d.ts.map +1 -1
- package/expo-plugin/src/constants.ts +24 -1
- package/expo-plugin/src/index.ts +14 -1
- package/expo-plugin/src/ios/index.ts +3 -0
- package/expo-plugin/src/ios/infoPlist.ts +33 -5
- package/expo-plugin/src/ios/serverUpdate.ts +29 -0
- package/expo-plugin/src/ios-widget/clientRendered.ts +9 -5
- package/expo-plugin/src/ios-widget/clientRenderedPrerender.ts +11 -6
- package/expo-plugin/src/ios-widget/dynamic-live-activity/swift.ts +138 -0
- package/expo-plugin/src/ios-widget/files/index.ts +15 -4
- package/expo-plugin/src/ios-widget/files/infoPlist.ts +17 -3
- package/expo-plugin/src/ios-widget/files/manifest.ts +42 -2
- package/expo-plugin/src/ios-widget/files/swift-utils.ts +3 -0
- package/expo-plugin/src/ios-widget/files/swift.ts +69 -22
- package/expo-plugin/src/ios-widget/index.ts +13 -3
- package/expo-plugin/src/ios-widget/podfile.ts +46 -13
- package/expo-plugin/src/ios-widget/widgetPlist.ts +37 -23
- package/expo-plugin/src/ios-widget/xcode/__fixtures__/fresh.pbxproj +197 -0
- package/expo-plugin/src/ios-widget/xcode/__fixtures__/with-existing-extension.pbxproj +321 -0
- package/expo-plugin/src/ios-widget/xcode/__fixtures__/with-per-config-signing.pbxproj +203 -0
- package/expo-plugin/src/ios-widget/xcode/__snapshots__/applyXcodeChanges.node.test.ts.snap +363 -0
- package/expo-plugin/src/ios-widget/xcode/__tests__/pbxConsistency.ts +130 -0
- package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +210 -164
- package/expo-plugin/src/ios-widget/xcode/configurationList.ts +52 -35
- package/expo-plugin/src/ios-widget/xcode/fileReferences.ts +51 -0
- package/expo-plugin/src/ios-widget/xcode/groups.ts +52 -54
- package/expo-plugin/src/ios-widget/xcode/index.ts +124 -119
- package/expo-plugin/src/ios-widget/xcode/mainAppSettings.ts +59 -54
- package/expo-plugin/src/ios-widget/xcode/productFile.ts +3 -2
- package/expo-plugin/src/ios-widget/xcode/target.ts +31 -83
- package/expo-plugin/src/types.ts +28 -4
- package/expo-plugin/src/utils/urlScheme.ts +47 -17
- package/expo-plugin/src/validation.ts +76 -1
- package/ios/Package.swift +39 -4
- package/ios/VoltraWidget.podspec +1 -0
- package/ios/app/NativeVoltra.mm +126 -7
- package/ios/app/VoltraLiveActivityManager.swift +30 -0
- package/ios/app/VoltraLiveActivityService.swift +77 -5
- package/ios/app/VoltraModule.swift +117 -1
- package/ios/app/VoltraModuleImpl.swift +116 -2
- package/ios/app/VoltraViewComponentView.mm +3 -3
- package/ios/app/VoltraWidgetService.swift +147 -12
- package/ios/app/dynamic-live-activity/VoltraDynamicLiveActivityService.swift +97 -0
- package/ios/app/dynamic-live-activity/VoltraLiveActivityChronology.swift +68 -0
- package/ios/shared/DynamicWidgetPropsCodec.swift +51 -0
- package/ios/shared/DynamicWidgetPropsStorage.swift +53 -0
- package/ios/shared/DynamicWidgetPropsStore.swift +117 -0
- package/ios/shared/DynamicWidgetRenderCoordinator.swift +31 -0
- package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerFetchResolver.swift +34 -0
- package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerProps.swift +55 -0
- package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerPropsStore.swift +146 -0
- package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerUpdateRunner.swift +193 -0
- package/ios/shared/DynamicWidgetUpdater.swift +30 -0
- package/ios/shared/ServerWidgetContentResolver.swift +60 -0
- package/ios/shared/ServerWidgetResponseStore.swift +25 -0
- package/ios/shared/ShortNames.swift +6 -0
- package/ios/shared/VoltraConfig.swift +41 -0
- package/ios/shared/VoltraConstants.swift +19 -0
- package/ios/shared/VoltraElement.swift +127 -43
- package/ios/shared/VoltraEventBus.swift +52 -7
- package/ios/shared/VoltraJSRenderer.swift +93 -23
- package/ios/shared/VoltraNode.swift +7 -111
- package/ios/shared/VoltraRefreshIntent.swift +1 -1
- package/ios/shared/VoltraWidgetDefaults.swift +9 -1
- package/ios/shared/VoltraWidgetKind.swift +41 -0
- package/ios/shared/VoltraWidgetServerFetcher.swift +52 -107
- package/ios/shared/WidgetServer/VoltraWidgetAppearance.swift +17 -0
- package/ios/shared/WidgetServer/VoltraWidgetServer.swift +138 -0
- package/ios/shared/WidgetServer/WidgetCanonicalConfiguration.swift +77 -0
- package/ios/shared/WidgetServer/WidgetScope.swift +55 -0
- package/ios/shared/WidgetServer/WidgetServerEtagStore.swift +55 -0
- package/ios/shared/WidgetServer/WidgetServerFetcher.swift +179 -0
- package/ios/shared/WidgetServer/WidgetServerRequestBuilder.swift +114 -0
- package/ios/shared/WidgetServer/WidgetServerSettingsCodec.swift +47 -0
- package/ios/shared/WidgetServer/WidgetServerSettingsResolver.swift +129 -0
- package/ios/shared/WidgetServer/WidgetServerSettingsStore.swift +170 -0
- package/ios/shared/WidgetServer/WidgetServerSettingsValidator.swift +73 -0
- package/ios/shared/WidgetServer/WidgetServerUpdateSettings.swift +123 -0
- package/ios/shared/WidgetServer/WidgetServerUpdateSettingsJson.swift +115 -0
- package/ios/shared/dynamic-live-activity/DynamicLiveActivityPropsCodec.swift +13 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityBundleSource.swift +156 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityObserver.swift +97 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityOperations.swift +105 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityPayloadValidator.swift +55 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRegistry.swift +143 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureQueue.swift +158 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureReporter.swift +120 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderer.swift +370 -0
- package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityTypes.swift +87 -0
- package/ios/shared/dynamic-live-activity/VoltraLiveActivityOrder.swift +19 -0
- package/ios/target/VoltraClientWidgetRuntime.swift +60 -10
- package/ios/target/VoltraDynamicWidgetServerUpdateProvider.swift +204 -0
- package/ios/target/VoltraHomeWidget.swift +91 -92
- package/ios/target/VoltraWidget.swift +3 -1
- package/ios/ui/Extensions/VoltraNode+View.swift +113 -0
- package/ios/ui/Generated/Parameters/ChartParameters.swift +3 -0
- package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +5 -3
- package/ios/ui/Helpers/VoltraProgressDriver.swift +6 -2
- package/ios/ui/Layout/VoltraFlexStackLayout.swift +9 -3
- package/ios/ui/Style/JSColorParser.swift +24 -8
- package/ios/ui/Style/JSGradientParser.swift +36 -12
- package/ios/ui/Style/JSStyleParser.swift +36 -12
- package/ios/ui/Style/LayoutStyle.swift +12 -4
- package/ios/ui/Views/VoltraChart.swift +160 -16
- package/ios/ui/Views/VoltraLinearGradient.swift +6 -2
- package/package.json +5 -5
- package/src/dynamic-widget/api.ts +25 -0
- package/src/events.ts +34 -0
- package/src/index.ts +23 -0
- package/src/live-activity/api.ts +2 -2
- package/src/live-activity/dynamic-api.ts +240 -0
- package/src/native/NativeVoltra.ts +22 -0
- package/src/types.ts +4 -0
- package/src/utils/enableDynamicLiveActivityHotReload.ts +50 -0
- package/src/utils/enableWidgetHotReload.ts +9 -16
- package/src/utils/useUpdateOnHMR.ts +3 -12
- package/src/widgets/server-credentials.ts +8 -0
- package/src/widgets/server-update.ts +84 -0
- /package/ios/shared/{VoltraKeychainHelper.swift → WidgetServer/VoltraKeychainHelper.swift} +0 -0
|
@@ -8,7 +8,9 @@ enum JSColorParser {
|
|
|
8
8
|
// Optimize: standard trim and lowercase
|
|
9
9
|
let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
|
|
10
10
|
|
|
11
|
-
if trimmed.isEmpty {
|
|
11
|
+
if trimmed.isEmpty {
|
|
12
|
+
return nil
|
|
13
|
+
}
|
|
12
14
|
|
|
13
15
|
// 1. Hex (with or without #)
|
|
14
16
|
if trimmed.hasPrefix("#") {
|
|
@@ -57,7 +59,9 @@ enum JSColorParser {
|
|
|
57
59
|
guard let string = value as? String else { return nil }
|
|
58
60
|
|
|
59
61
|
let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
|
|
60
|
-
if trimmed.isEmpty {
|
|
62
|
+
if trimmed.isEmpty {
|
|
63
|
+
return nil
|
|
64
|
+
}
|
|
61
65
|
|
|
62
66
|
if trimmed.hasPrefix("#") {
|
|
63
67
|
return parseHexComponents(trimmed)
|
|
@@ -477,7 +481,9 @@ enum JSColorParser {
|
|
|
477
481
|
|
|
478
482
|
private static func normalizeUnit(_ value: Double) -> Double {
|
|
479
483
|
var result = value.truncatingRemainder(dividingBy: 1)
|
|
480
|
-
if result < 0 {
|
|
484
|
+
if result < 0 {
|
|
485
|
+
result += 1
|
|
486
|
+
}
|
|
481
487
|
return result
|
|
482
488
|
}
|
|
483
489
|
|
|
@@ -506,12 +512,22 @@ enum JSColorParser {
|
|
|
506
512
|
/// Helper function for HSL to RGB conversion
|
|
507
513
|
private static func hueToRgb(p: Double, q: Double, t: Double) -> Double {
|
|
508
514
|
var t = t
|
|
509
|
-
if t < 0 {
|
|
510
|
-
|
|
515
|
+
if t < 0 {
|
|
516
|
+
t += 1
|
|
517
|
+
}
|
|
518
|
+
if t > 1 {
|
|
519
|
+
t -= 1
|
|
520
|
+
}
|
|
511
521
|
|
|
512
|
-
if t < 1.0 / 6.0 {
|
|
513
|
-
|
|
514
|
-
|
|
522
|
+
if t < 1.0 / 6.0 {
|
|
523
|
+
return p + (q - p) * 6 * t
|
|
524
|
+
}
|
|
525
|
+
if t < 1.0 / 2.0 {
|
|
526
|
+
return q
|
|
527
|
+
}
|
|
528
|
+
if t < 2.0 / 3.0 {
|
|
529
|
+
return p + (q - p) * (2.0 / 3.0 - t) * 6
|
|
530
|
+
}
|
|
515
531
|
return p
|
|
516
532
|
}
|
|
517
533
|
}
|
|
@@ -200,12 +200,16 @@ enum JSGradientParser {
|
|
|
200
200
|
depth += 1
|
|
201
201
|
} else if char == ")" {
|
|
202
202
|
depth -= 1
|
|
203
|
-
if depth < 0 {
|
|
203
|
+
if depth < 0 {
|
|
204
|
+
return []
|
|
205
|
+
}
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
if char == ",", depth == 0 {
|
|
207
209
|
let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
208
|
-
if token.isEmpty {
|
|
210
|
+
if token.isEmpty {
|
|
211
|
+
return []
|
|
212
|
+
}
|
|
209
213
|
args.append(token)
|
|
210
214
|
current = ""
|
|
211
215
|
} else {
|
|
@@ -216,7 +220,9 @@ enum JSGradientParser {
|
|
|
216
220
|
guard depth == 0 else { return [] }
|
|
217
221
|
|
|
218
222
|
let token = current.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
219
|
-
if token.isEmpty {
|
|
223
|
+
if token.isEmpty {
|
|
224
|
+
return []
|
|
225
|
+
}
|
|
220
226
|
args.append(token)
|
|
221
227
|
return args
|
|
222
228
|
}
|
|
@@ -231,7 +237,9 @@ enum JSGradientParser {
|
|
|
231
237
|
depth += 1
|
|
232
238
|
} else if char == ")" {
|
|
233
239
|
depth -= 1
|
|
234
|
-
if depth < 0 {
|
|
240
|
+
if depth < 0 {
|
|
241
|
+
return []
|
|
242
|
+
}
|
|
235
243
|
}
|
|
236
244
|
|
|
237
245
|
if char.isWhitespace, depth == 0 {
|
|
@@ -269,10 +277,14 @@ enum JSGradientParser {
|
|
|
269
277
|
for word in words {
|
|
270
278
|
switch word {
|
|
271
279
|
case "left", "right":
|
|
272
|
-
if horizontal != nil {
|
|
280
|
+
if horizontal != nil {
|
|
281
|
+
return nil
|
|
282
|
+
}
|
|
273
283
|
horizontal = word
|
|
274
284
|
case "top", "bottom":
|
|
275
|
-
if vertical != nil {
|
|
285
|
+
if vertical != nil {
|
|
286
|
+
return nil
|
|
287
|
+
}
|
|
276
288
|
vertical = word
|
|
277
289
|
default:
|
|
278
290
|
return nil
|
|
@@ -418,10 +430,14 @@ enum JSGradientParser {
|
|
|
418
430
|
for token in tokens {
|
|
419
431
|
switch token {
|
|
420
432
|
case "left":
|
|
421
|
-
if x != nil {
|
|
433
|
+
if x != nil {
|
|
434
|
+
return nil
|
|
435
|
+
}
|
|
422
436
|
x = 0
|
|
423
437
|
case "right":
|
|
424
|
-
if x != nil {
|
|
438
|
+
if x != nil {
|
|
439
|
+
return nil
|
|
440
|
+
}
|
|
425
441
|
x = 1
|
|
426
442
|
case "center":
|
|
427
443
|
if x == nil {
|
|
@@ -432,10 +448,14 @@ enum JSGradientParser {
|
|
|
432
448
|
return nil
|
|
433
449
|
}
|
|
434
450
|
case "top":
|
|
435
|
-
if y != nil {
|
|
451
|
+
if y != nil {
|
|
452
|
+
return nil
|
|
453
|
+
}
|
|
436
454
|
y = 0
|
|
437
455
|
case "bottom":
|
|
438
|
-
if y != nil {
|
|
456
|
+
if y != nil {
|
|
457
|
+
return nil
|
|
458
|
+
}
|
|
439
459
|
y = 1
|
|
440
460
|
default:
|
|
441
461
|
return nil
|
|
@@ -613,8 +633,12 @@ enum JSGradientParser {
|
|
|
613
633
|
guard !stops.isEmpty else { return [] }
|
|
614
634
|
|
|
615
635
|
var positions = stops.map(\.position)
|
|
616
|
-
if positions.first == nil {
|
|
617
|
-
|
|
636
|
+
if positions.first == nil {
|
|
637
|
+
positions[0] = 0
|
|
638
|
+
}
|
|
639
|
+
if positions.last == nil {
|
|
640
|
+
positions[positions.count - 1] = 1
|
|
641
|
+
}
|
|
618
642
|
|
|
619
643
|
var lastDefined: Double?
|
|
620
644
|
for idx in positions.indices {
|
|
@@ -2,16 +2,24 @@ import SwiftUI
|
|
|
2
2
|
|
|
3
3
|
enum JSStyleParser {
|
|
4
4
|
static func number(_ value: Any?) -> CGFloat? {
|
|
5
|
-
if let v = value as? CGFloat {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
if let v = value as? CGFloat {
|
|
6
|
+
return v
|
|
7
|
+
}
|
|
8
|
+
if let v = value as? Double {
|
|
9
|
+
return CGFloat(v)
|
|
10
|
+
}
|
|
11
|
+
if let v = value as? Int {
|
|
12
|
+
return CGFloat(v)
|
|
13
|
+
}
|
|
8
14
|
// Handle "20.5" strings if necessary, though rarer in raw JSON objects
|
|
9
15
|
return nil
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
static func sizeValue(_ value: Any?) -> SizeValue? {
|
|
13
19
|
// Numeric → Fixed
|
|
14
|
-
if let n = number(value) {
|
|
20
|
+
if let n = number(value) {
|
|
21
|
+
return .fixed(n)
|
|
22
|
+
}
|
|
15
23
|
// String → Fill / Wrap / try numeric
|
|
16
24
|
guard let str = value as? String else { return nil }
|
|
17
25
|
switch str {
|
|
@@ -19,7 +27,9 @@ enum JSStyleParser {
|
|
|
19
27
|
case "auto": return .wrap
|
|
20
28
|
default:
|
|
21
29
|
// Try parsing as numeric string
|
|
22
|
-
if let n = Double(str) {
|
|
30
|
+
if let n = Double(str) {
|
|
31
|
+
return .fixed(CGFloat(n))
|
|
32
|
+
}
|
|
23
33
|
return nil
|
|
24
34
|
}
|
|
25
35
|
}
|
|
@@ -50,8 +60,12 @@ enum JSStyleParser {
|
|
|
50
60
|
static func boolean(_ value: Any?) -> Bool {
|
|
51
61
|
guard let value = value else { return false }
|
|
52
62
|
|
|
53
|
-
if let bool = value as? Bool {
|
|
54
|
-
|
|
63
|
+
if let bool = value as? Bool {
|
|
64
|
+
return bool
|
|
65
|
+
}
|
|
66
|
+
if let int = value as? Int {
|
|
67
|
+
return int == 1
|
|
68
|
+
}
|
|
55
69
|
if let string = value as? String {
|
|
56
70
|
return string.lowercased() == "true"
|
|
57
71
|
}
|
|
@@ -107,9 +121,15 @@ enum JSStyleParser {
|
|
|
107
121
|
let hasUnderline = string.contains("underline")
|
|
108
122
|
let hasLineThrough = string.contains("line-through") || string.contains("strikethrough")
|
|
109
123
|
|
|
110
|
-
if hasUnderline, hasLineThrough {
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
if hasUnderline, hasLineThrough {
|
|
125
|
+
return .underlineLineThrough
|
|
126
|
+
}
|
|
127
|
+
if hasUnderline {
|
|
128
|
+
return .underline
|
|
129
|
+
}
|
|
130
|
+
if hasLineThrough {
|
|
131
|
+
return .lineThrough
|
|
132
|
+
}
|
|
113
133
|
return .none
|
|
114
134
|
}
|
|
115
135
|
|
|
@@ -128,8 +148,12 @@ enum JSStyleParser {
|
|
|
128
148
|
static func overflow(_ value: Any?) -> Overflow? {
|
|
129
149
|
guard let string = (value as? String)?.lowercased() else { return nil }
|
|
130
150
|
|
|
131
|
-
if string == "hidden" {
|
|
132
|
-
|
|
151
|
+
if string == "hidden" {
|
|
152
|
+
return .hidden
|
|
153
|
+
}
|
|
154
|
+
if string == "visible" {
|
|
155
|
+
return .visible
|
|
156
|
+
}
|
|
133
157
|
return nil
|
|
134
158
|
}
|
|
135
159
|
|
|
@@ -112,15 +112,23 @@ struct LayoutModifier: ViewModifier {
|
|
|
112
112
|
|
|
113
113
|
/// Derive effective ideal width: explicit width, then flexBasis, then nil
|
|
114
114
|
private var effectiveIdealWidth: CGFloat? {
|
|
115
|
-
if let w = widthValue {
|
|
116
|
-
|
|
115
|
+
if let w = widthValue {
|
|
116
|
+
return w
|
|
117
|
+
}
|
|
118
|
+
if case let .fixed(v) = style.flexBasis {
|
|
119
|
+
return v
|
|
120
|
+
}
|
|
117
121
|
return nil
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
/// Derive effective ideal height: explicit height, then flexBasis, then nil
|
|
121
125
|
private var effectiveIdealHeight: CGFloat? {
|
|
122
|
-
if let h = heightValue {
|
|
123
|
-
|
|
126
|
+
if let h = heightValue {
|
|
127
|
+
return h
|
|
128
|
+
}
|
|
129
|
+
if case let .fixed(v) = style.flexBasis {
|
|
130
|
+
return v
|
|
131
|
+
}
|
|
124
132
|
return nil
|
|
125
133
|
}
|
|
126
134
|
|
|
@@ -49,7 +49,9 @@ public struct VoltraChart: VoltraView {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
private func bool(_ v: JSONValue) -> Bool? {
|
|
52
|
-
if case let .bool(value) = v {
|
|
52
|
+
if case let .bool(value) = v {
|
|
53
|
+
return value
|
|
54
|
+
}
|
|
53
55
|
return nil
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -60,16 +62,22 @@ public struct VoltraChart: VoltraView {
|
|
|
60
62
|
else { return nil }
|
|
61
63
|
|
|
62
64
|
let props = dict.compactMapValues { jsonValue(from: $0) }
|
|
63
|
-
if props.isEmpty {
|
|
65
|
+
if props.isEmpty {
|
|
66
|
+
return nil
|
|
67
|
+
}
|
|
64
68
|
|
|
65
69
|
let visible = props["v"].flatMap(bool) ?? props["visible"].flatMap(bool)
|
|
66
70
|
let color = (props["c"] ?? props["color"]).flatMap {
|
|
67
|
-
if case let .string(value) = $0 {
|
|
71
|
+
if case let .string(value) = $0 {
|
|
72
|
+
return JSColorParser.parse(value)
|
|
73
|
+
}
|
|
68
74
|
return nil
|
|
69
75
|
}
|
|
70
76
|
let lineWidth = (props["lw"] ?? props["lineWidth"]).flatMap(num).map { CGFloat($0) }
|
|
71
77
|
let dash = ((props["d"] ?? props["dash"]).flatMap {
|
|
72
|
-
if case let .array(values) = $0 {
|
|
78
|
+
if case let .array(values) = $0 {
|
|
79
|
+
return values.compactMap(num).map { CGFloat($0) }
|
|
80
|
+
}
|
|
73
81
|
return nil
|
|
74
82
|
})
|
|
75
83
|
|
|
@@ -140,7 +148,11 @@ public struct VoltraChart: VoltraView {
|
|
|
140
148
|
default: return 0
|
|
141
149
|
}
|
|
142
150
|
}()
|
|
143
|
-
let series: String? = pt.count >= 3 ? {
|
|
151
|
+
let series: String? = pt.count >= 3 ? {
|
|
152
|
+
if case let .string(s) = pt[2] {
|
|
153
|
+
return s
|
|
154
|
+
}; return nil
|
|
155
|
+
}() : nil
|
|
144
156
|
switch pt[0] {
|
|
145
157
|
case let .string(x): return (x, nil, y, series)
|
|
146
158
|
case let .double(x): return (nil, x, y, series)
|
|
@@ -149,6 +161,103 @@ public struct VoltraChart: VoltraView {
|
|
|
149
161
|
}
|
|
150
162
|
}
|
|
151
163
|
|
|
164
|
+
// MARK: - Y scale
|
|
165
|
+
|
|
166
|
+
/// Y-axis bounds pinned by the `yScale` prop; either side may be left to the data.
|
|
167
|
+
private struct YScale {
|
|
168
|
+
let min: Double?
|
|
169
|
+
let max: Double?
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private func parseYScale(from raw: String?) -> YScale? {
|
|
173
|
+
guard let raw,
|
|
174
|
+
let data = raw.data(using: .utf8),
|
|
175
|
+
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
|
|
176
|
+
else { return nil }
|
|
177
|
+
|
|
178
|
+
let props = dict.compactMapValues { jsonValue(from: $0) }
|
|
179
|
+
let min = (props["mn"] ?? props["min"]).flatMap(num)
|
|
180
|
+
let max = (props["mx"] ?? props["max"]).flatMap(num)
|
|
181
|
+
if min == nil, max == nil {
|
|
182
|
+
return nil
|
|
183
|
+
}
|
|
184
|
+
return YScale(min: min, max: max)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/// Domain to hand SwiftUI when `yScale` pins a bound. The open side follows the data exactly as
|
|
188
|
+
/// `computeYDomain` in Android's ChartBitmapRenderer.kt frames it, so both platforms agree.
|
|
189
|
+
private func yScaleDomain(_ marks: [WireMark], pinned: YScale) -> ClosedRange<Double> {
|
|
190
|
+
let auto = autoYDomain(marks)
|
|
191
|
+
var lower = pinned.min ?? auto.lowerBound
|
|
192
|
+
var upper = pinned.max ?? auto.upperBound
|
|
193
|
+
|
|
194
|
+
if upper <= lower {
|
|
195
|
+
// A pin that inverts the domain still has to leave something to draw in: keep the span the
|
|
196
|
+
// data asked for on the side the caller left open, and ignore a pair that cannot be drawn.
|
|
197
|
+
let span = auto.upperBound - auto.lowerBound
|
|
198
|
+
if pinned.max == nil {
|
|
199
|
+
upper = lower + span
|
|
200
|
+
} else if pinned.min == nil {
|
|
201
|
+
lower = upper - span
|
|
202
|
+
} else {
|
|
203
|
+
return auto
|
|
204
|
+
}
|
|
205
|
+
if upper <= lower {
|
|
206
|
+
upper = lower + 1
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return lower ... upper
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private func autoYDomain(_ marks: [WireMark]) -> ClosedRange<Double> {
|
|
214
|
+
var values = marks.flatMap { mark -> [Double] in
|
|
215
|
+
guard mark.type != "sector" else { return [] }
|
|
216
|
+
return (mark.data ?? []).map { xy($0).y }
|
|
217
|
+
}
|
|
218
|
+
values += marks.compactMap { $0.type == "rule" ? $0.props["yv"].flatMap(num) : nil }
|
|
219
|
+
|
|
220
|
+
let finite = values.filter(\.isFinite)
|
|
221
|
+
guard let dataMin = finite.min(), let dataMax = finite.max() else { return 0 ... 1 }
|
|
222
|
+
|
|
223
|
+
// Bars and areas measure their value against the baseline, so zero stays in range.
|
|
224
|
+
if marks.contains(where: { $0.type == "bar" || $0.type == "area" }) {
|
|
225
|
+
let lower = Swift.min(dataMin, 0)
|
|
226
|
+
let upper = Swift.max(dataMax, 0)
|
|
227
|
+
return upper > lower ? lower ... upper : lower ... (lower + 1)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
guard dataMax > dataMin else {
|
|
231
|
+
let padding = dataMin == 0 ? 1 : abs(dataMin) * Self.yDomainPaddingRatio
|
|
232
|
+
return (dataMin - padding) ... (dataMax + padding)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let padding = (dataMax - dataMin) * Self.yDomainPaddingRatio
|
|
236
|
+
var lower = dataMin - padding
|
|
237
|
+
var upper = dataMax + padding
|
|
238
|
+
|
|
239
|
+
// Padding must not invent values on the other side of the baseline, and data that almost
|
|
240
|
+
// reaches zero keeps it in view.
|
|
241
|
+
if dataMin >= 0, lower < 0 {
|
|
242
|
+
lower = 0
|
|
243
|
+
}
|
|
244
|
+
if dataMax <= 0, upper > 0 {
|
|
245
|
+
upper = 0
|
|
246
|
+
}
|
|
247
|
+
let span = upper - lower
|
|
248
|
+
if lower > 0, lower < span * Self.zeroSnapRatio {
|
|
249
|
+
lower = 0
|
|
250
|
+
}
|
|
251
|
+
if upper < 0, -upper < span * Self.zeroSnapRatio {
|
|
252
|
+
upper = 0
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return lower ... upper
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private static let yDomainPaddingRatio = 0.1
|
|
259
|
+
private static let zeroSnapRatio = 0.25
|
|
260
|
+
|
|
152
261
|
// MARK: - body
|
|
153
262
|
|
|
154
263
|
public var body: some View {
|
|
@@ -159,10 +268,12 @@ public struct VoltraChart: VoltraView {
|
|
|
159
268
|
let yAxisGridStyle = parseAxisGridStyle(from: params.yAxisGridStyle)
|
|
160
269
|
let legendVis = visibility(params.legendVisibility)
|
|
161
270
|
let legendItems = parseLegendItems(from: params.foregroundStyleScale)
|
|
271
|
+
let yDomain = parseYScale(from: params.yScale).map { yScaleDomain(wireMarks, pinned: $0) }
|
|
162
272
|
|
|
163
273
|
Chart {
|
|
164
274
|
buildAll(wireMarks)
|
|
165
275
|
}
|
|
276
|
+
.applyChartYScale(domain: yDomain)
|
|
166
277
|
.applyForegroundStyleScale(params.foregroundStyleScale)
|
|
167
278
|
.applyChartStyle(
|
|
168
279
|
element.style,
|
|
@@ -186,12 +297,24 @@ public struct VoltraChart: VoltraView {
|
|
|
186
297
|
|
|
187
298
|
@ChartContentBuilder
|
|
188
299
|
private func buildMark(_ m: WireMark) -> some ChartContent {
|
|
189
|
-
if m.type == "bar" {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if m.type == "
|
|
193
|
-
|
|
194
|
-
|
|
300
|
+
if m.type == "bar" {
|
|
301
|
+
barContent(m)
|
|
302
|
+
}
|
|
303
|
+
if m.type == "line" {
|
|
304
|
+
lineContent(m)
|
|
305
|
+
}
|
|
306
|
+
if m.type == "area" {
|
|
307
|
+
areaContent(m)
|
|
308
|
+
}
|
|
309
|
+
if m.type == "point" {
|
|
310
|
+
pointContent(m)
|
|
311
|
+
}
|
|
312
|
+
if m.type == "rule" {
|
|
313
|
+
ruleContent(m)
|
|
314
|
+
}
|
|
315
|
+
if #available(iOS 17.0, macOS 14.0, *), m.type == "sector" {
|
|
316
|
+
sectorContent(m)
|
|
317
|
+
}
|
|
195
318
|
}
|
|
196
319
|
|
|
197
320
|
// MARK: Bar
|
|
@@ -208,10 +331,16 @@ public struct VoltraChart: VoltraView {
|
|
|
208
331
|
let (xStr, xNum, y, series) = xy(pt)
|
|
209
332
|
let cr: CGFloat? = props["cr"].flatMap(num).map { CGFloat($0) }
|
|
210
333
|
let barWidth: MarkDimension = {
|
|
211
|
-
if let v = props["w"].flatMap(num) {
|
|
334
|
+
if let v = props["w"].flatMap(num) {
|
|
335
|
+
return .fixed(CGFloat(v))
|
|
336
|
+
}
|
|
212
337
|
return .automatic
|
|
213
338
|
}()
|
|
214
|
-
let grouped: Bool = {
|
|
339
|
+
let grouped: Bool = {
|
|
340
|
+
if case let .string(s)? = props["stk"] {
|
|
341
|
+
return s == "grouped"
|
|
342
|
+
}; return false
|
|
343
|
+
}()
|
|
215
344
|
|
|
216
345
|
if let x = xStr {
|
|
217
346
|
if let series {
|
|
@@ -555,15 +684,21 @@ public struct VoltraChart: VoltraView {
|
|
|
555
684
|
case let .string(category) = pt[1]
|
|
556
685
|
{
|
|
557
686
|
let inner: MarkDimension = {
|
|
558
|
-
if let v = props["ir"].flatMap(num) {
|
|
687
|
+
if let v = props["ir"].flatMap(num) {
|
|
688
|
+
return .ratio(CGFloat(v))
|
|
689
|
+
}
|
|
559
690
|
return .automatic
|
|
560
691
|
}()
|
|
561
692
|
let outer: MarkDimension = {
|
|
562
|
-
if let v = props["or"].flatMap(num) {
|
|
693
|
+
if let v = props["or"].flatMap(num) {
|
|
694
|
+
return .ratio(CGFloat(v))
|
|
695
|
+
}
|
|
563
696
|
return .automatic
|
|
564
697
|
}()
|
|
565
698
|
let inset: CGFloat = {
|
|
566
|
-
if let v = props["agin"].flatMap(num) {
|
|
699
|
+
if let v = props["agin"].flatMap(num) {
|
|
700
|
+
return CGFloat(v)
|
|
701
|
+
}
|
|
567
702
|
return 0
|
|
568
703
|
}()
|
|
569
704
|
|
|
@@ -698,6 +833,15 @@ private extension View {
|
|
|
698
833
|
}
|
|
699
834
|
}
|
|
700
835
|
|
|
836
|
+
@ViewBuilder
|
|
837
|
+
func applyChartYScale(domain: ClosedRange<Double>?) -> some View {
|
|
838
|
+
if let domain {
|
|
839
|
+
chartYScale(domain: domain)
|
|
840
|
+
} else {
|
|
841
|
+
self
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
701
845
|
@ViewBuilder
|
|
702
846
|
func applyChartClipping(decoration: DecorationStyle, hasClipping: Bool) -> some View {
|
|
703
847
|
if hasClipping {
|
|
@@ -57,12 +57,16 @@ public struct VoltraLinearGradient: VoltraView {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
if !stops.isEmpty {
|
|
60
|
+
if !stops.isEmpty {
|
|
61
|
+
return Gradient(stops: stops)
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
if let colorsStr = params.colors {
|
|
63
65
|
let parts = colorsStr.split(separator: "|").map(String.init)
|
|
64
66
|
let colors: [Color] = parts.compactMap { JSColorParser.parse($0) }
|
|
65
|
-
if !colors.isEmpty {
|
|
67
|
+
if !colors.isEmpty {
|
|
68
|
+
return Gradient(colors: colors)
|
|
69
|
+
}
|
|
66
70
|
}
|
|
67
71
|
// Fallback neutral gradient
|
|
68
72
|
return Gradient(colors: [Color.black.opacity(0.25), Color.black.opacity(0.05)])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@use-voltra/ios-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Client-only Voltra APIs for iOS",
|
|
5
5
|
"main": "./build/commonjs/index.js",
|
|
6
6
|
"module": "./build/module/index.js",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"@expo/plist": "^0.3.5",
|
|
40
40
|
"dedent": "^1.7.1",
|
|
41
41
|
"xcode": "^3.0.1",
|
|
42
|
-
"@use-voltra/
|
|
43
|
-
"@use-voltra/ios": "^2.
|
|
44
|
-
"@use-voltra/
|
|
42
|
+
"@use-voltra/compiler": "^2.3.0",
|
|
43
|
+
"@use-voltra/ios": "^2.3.0",
|
|
44
|
+
"@use-voltra/expo-plugin": "^2.3.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"expo": "*",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"format:swift:fix": "swiftformat ios",
|
|
126
126
|
"lint": "oxlint src expo-plugin/src",
|
|
127
127
|
"typecheck": "tsc -p tsconfig.typecheck.json --noEmit && tsc -p expo-plugin/tsconfig.typecheck.json --noEmit",
|
|
128
|
-
"test": "jest --config expo-plugin/jest.config.js",
|
|
128
|
+
"test": "jest --config jest.dynamic-widget.config.js && jest --config expo-plugin/jest.config.js",
|
|
129
129
|
"test:swift": "cd ios && swift test"
|
|
130
130
|
}
|
|
131
131
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getNativeVoltra } from '../native/NativeVoltra.js'
|
|
2
|
+
import { assertRunningOnApple } from '../utils/assertRunningOnApple.js'
|
|
3
|
+
|
|
4
|
+
export type DynamicWidgetPropsValue =
|
|
5
|
+
| string
|
|
6
|
+
| number
|
|
7
|
+
| boolean
|
|
8
|
+
| null
|
|
9
|
+
| ReadonlyArray<DynamicWidgetPropsValue>
|
|
10
|
+
| Readonly<{ [dynamicWidgetPropName: string]: DynamicWidgetPropsValue }>
|
|
11
|
+
|
|
12
|
+
export type DynamicWidgetProps = Readonly<{
|
|
13
|
+
[dynamicWidgetPropName: string]: DynamicWidgetPropsValue
|
|
14
|
+
}>
|
|
15
|
+
|
|
16
|
+
export const updateDynamicWidget = async (
|
|
17
|
+
dynamicWidgetId: string,
|
|
18
|
+
dynamicWidgetProps: DynamicWidgetProps
|
|
19
|
+
): Promise<void> => {
|
|
20
|
+
if (!assertRunningOnApple()) return Promise.resolve()
|
|
21
|
+
|
|
22
|
+
const dynamicWidgetPropsJson = JSON.stringify(dynamicWidgetProps)
|
|
23
|
+
|
|
24
|
+
return getNativeVoltra().updateDynamicWidget(dynamicWidgetId, dynamicWidgetPropsJson)
|
|
25
|
+
}
|
package/src/events.ts
CHANGED
|
@@ -30,15 +30,28 @@ export type VoltraInteractionEvent = BasicVoltraEvent & {
|
|
|
30
30
|
payload: string
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
export type VoltraDynamicLiveActivityRenderFailedEvent = BasicVoltraEvent & {
|
|
34
|
+
type: 'dynamicLiveActivityRenderFailed'
|
|
35
|
+
activityName: string
|
|
36
|
+
definitionId: string
|
|
37
|
+
message: string
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
const noopSubscription: EventSubscription = {
|
|
34
41
|
remove: () => {},
|
|
35
42
|
}
|
|
36
43
|
|
|
44
|
+
// Codegen EventEmitter subscriptions do not tell native code when their last
|
|
45
|
+
// JavaScript listener goes away. Keep this count at the public API boundary so
|
|
46
|
+
// the App Group queue is drained only while it can actually be delivered.
|
|
47
|
+
let dynamicRenderFailureListenerCount = 0
|
|
48
|
+
|
|
37
49
|
export type VoltraEventMap = {
|
|
38
50
|
activityTokenReceived: VoltraActivityTokenReceivedEvent
|
|
39
51
|
activityPushToStartTokenReceived: VoltraActivityPushToStartTokenReceivedEvent
|
|
40
52
|
stateChange: VoltraActivityUpdateEvent
|
|
41
53
|
interaction: VoltraInteractionEvent
|
|
54
|
+
dynamicLiveActivityRenderFailed: VoltraDynamicLiveActivityRenderFailedEvent
|
|
42
55
|
}
|
|
43
56
|
|
|
44
57
|
export function addVoltraListener<K extends keyof VoltraEventMap>(
|
|
@@ -63,6 +76,27 @@ export function addVoltraListener<K extends keyof VoltraEventMap>(
|
|
|
63
76
|
return voltraModule.onStateChanged(listener as (arg: VoltraActivityUpdateEvent) => void)
|
|
64
77
|
case 'interaction':
|
|
65
78
|
return voltraModule.onInteraction(listener as (arg: VoltraInteractionEvent) => void)
|
|
79
|
+
case 'dynamicLiveActivityRenderFailed':
|
|
80
|
+
const subscription = voltraModule.onDynamicLiveActivityRenderFailed(
|
|
81
|
+
listener as (arg: VoltraDynamicLiveActivityRenderFailedEvent) => void
|
|
82
|
+
)
|
|
83
|
+
dynamicRenderFailureListenerCount += 1
|
|
84
|
+
if (dynamicRenderFailureListenerCount === 1) {
|
|
85
|
+
voltraModule.setDynamicLiveActivityRenderFailureListenerActive(true)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let removed = false
|
|
89
|
+
return {
|
|
90
|
+
remove: () => {
|
|
91
|
+
if (removed) return
|
|
92
|
+
removed = true
|
|
93
|
+
subscription.remove()
|
|
94
|
+
dynamicRenderFailureListenerCount -= 1
|
|
95
|
+
if (dynamicRenderFailureListenerCount === 0) {
|
|
96
|
+
voltraModule.setDynamicLiveActivityRenderFailureListenerActive(false)
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
}
|
|
66
100
|
default:
|
|
67
101
|
console.warn(`[Voltra] Event '${event}' is not supported. Returning no-op subscription.`)
|
|
68
102
|
return noopSubscription
|