@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
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export {
|
|
|
5
5
|
} from './components/VoltraLiveActivityPreview.js'
|
|
6
6
|
export { VoltraView, type VoltraViewProps } from './components/VoltraView.js'
|
|
7
7
|
export { VoltraWidgetPreview, type VoltraWidgetPreviewProps } from './components/VoltraWidgetPreview.js'
|
|
8
|
+
export { type DynamicWidgetProps, type DynamicWidgetPropsValue, updateDynamicWidget } from './dynamic-widget/api.js'
|
|
8
9
|
export * from './events.js'
|
|
9
10
|
export { isGlassSupported, isHeadless, useIsHeadless } from './helpers.js'
|
|
10
11
|
export { logger, type VoltraLogLevel } from './logger.js'
|
|
@@ -22,6 +23,18 @@ export {
|
|
|
22
23
|
type UseLiveActivityOptions,
|
|
23
24
|
type UseLiveActivityResult,
|
|
24
25
|
} from './live-activity/api.js'
|
|
26
|
+
export {
|
|
27
|
+
getDynamicLiveActivityDefinitionIds,
|
|
28
|
+
startDynamicLiveActivity,
|
|
29
|
+
type StartDynamicLiveActivityOptions,
|
|
30
|
+
updateDynamicLiveActivity,
|
|
31
|
+
type UpdateDynamicLiveActivityOptions,
|
|
32
|
+
useDynamicLiveActivity,
|
|
33
|
+
type UseDynamicLiveActivityOptions,
|
|
34
|
+
type UseDynamicLiveActivityResult,
|
|
35
|
+
type DynamicLiveActivityProps,
|
|
36
|
+
type DynamicLiveActivityPropsValue,
|
|
37
|
+
} from './live-activity/dynamic-api.js'
|
|
25
38
|
export type { DismissalPolicy, LiveActivityVariants } from '@use-voltra/ios'
|
|
26
39
|
export {
|
|
27
40
|
clearPreloadedImages,
|
|
@@ -32,9 +45,19 @@ export {
|
|
|
32
45
|
} from './preload.js'
|
|
33
46
|
export { assertRunningOnApple } from './utils/assertRunningOnApple.js'
|
|
34
47
|
export { enableWidgetHotReload } from './utils/enableWidgetHotReload.js'
|
|
48
|
+
export { enableDynamicLiveActivityHotReload } from './utils/enableDynamicLiveActivityHotReload.js'
|
|
35
49
|
export { useUpdateOnHMR } from './utils/useUpdateOnHMR.js'
|
|
36
50
|
export * from './utils/helpers.js'
|
|
37
51
|
export type { VoltraElementJson, VoltraNodeJson } from './types.js'
|
|
52
|
+
export {
|
|
53
|
+
clearWidgetServerUpdate,
|
|
54
|
+
getWidgetServerUpdate,
|
|
55
|
+
setWidgetServerUpdate,
|
|
56
|
+
type WidgetServerUpdateBody,
|
|
57
|
+
type WidgetServerUpdateOptions,
|
|
58
|
+
type WidgetServerUpdateSettings,
|
|
59
|
+
type WidgetServerUpdateSnapshot,
|
|
60
|
+
} from './widgets/server-update.js'
|
|
38
61
|
export {
|
|
39
62
|
clearWidgetServerCredentials,
|
|
40
63
|
setWidgetServerCredentials,
|
package/src/live-activity/api.ts
CHANGED
|
@@ -40,7 +40,7 @@ export type UseLiveActivityResult = {
|
|
|
40
40
|
isActive: boolean
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const normalizeSharedLiveActivityOptions = (
|
|
43
|
+
export const normalizeSharedLiveActivityOptions = (
|
|
44
44
|
options?: SharedLiveActivityOptions
|
|
45
45
|
): SharedLiveActivityOptions | undefined => {
|
|
46
46
|
if (!options) return undefined
|
|
@@ -66,7 +66,7 @@ const normalizeSharedLiveActivityOptions = (
|
|
|
66
66
|
return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const normalizeEndLiveActivityOptions = (
|
|
69
|
+
export const normalizeEndLiveActivityOptions = (
|
|
70
70
|
options?: EndLiveActivityOptions
|
|
71
71
|
): { dismissalPolicy?: { type: 'immediate' | 'after'; date?: number } } | undefined => {
|
|
72
72
|
if (!options?.dismissalPolicy) return undefined
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import { addVoltraListener } from '../events.js'
|
|
4
|
+
import { assertRunningOnApple, useUpdateOnHMR } from '../utils/index.js'
|
|
5
|
+
import { getNativeVoltra } from '../VoltraModule.js'
|
|
6
|
+
import {
|
|
7
|
+
isLiveActivityActive,
|
|
8
|
+
normalizeSharedLiveActivityOptions,
|
|
9
|
+
stopLiveActivity,
|
|
10
|
+
type EndLiveActivityOptions,
|
|
11
|
+
type SharedLiveActivityOptions,
|
|
12
|
+
} from './api.js'
|
|
13
|
+
|
|
14
|
+
/** @experimental A JSON-compatible value accepted as Dynamic Live Activity props. */
|
|
15
|
+
export type DynamicLiveActivityPropsValue =
|
|
16
|
+
| string
|
|
17
|
+
| number
|
|
18
|
+
| boolean
|
|
19
|
+
| null
|
|
20
|
+
| ReadonlyArray<DynamicLiveActivityPropsValue>
|
|
21
|
+
| Readonly<{ [key: string]: DynamicLiveActivityPropsValue }>
|
|
22
|
+
|
|
23
|
+
/** @experimental A complete JSON-compatible props record for a Dynamic Live Activity update. */
|
|
24
|
+
export type DynamicLiveActivityProps = Readonly<{ [key: string]: DynamicLiveActivityPropsValue }>
|
|
25
|
+
|
|
26
|
+
/** @experimental Options used to start a Dynamic Live Activity. */
|
|
27
|
+
export type StartDynamicLiveActivityOptions = {
|
|
28
|
+
activityName?: string
|
|
29
|
+
deepLinkUrl?: string
|
|
30
|
+
channelId?: string
|
|
31
|
+
} & SharedLiveActivityOptions
|
|
32
|
+
|
|
33
|
+
/** @experimental Options used to update a Dynamic Live Activity. */
|
|
34
|
+
export type UpdateDynamicLiveActivityOptions = SharedLiveActivityOptions
|
|
35
|
+
|
|
36
|
+
/** @experimental Options for `useDynamicLiveActivity`. */
|
|
37
|
+
export type UseDynamicLiveActivityOptions = StartDynamicLiveActivityOptions & {
|
|
38
|
+
autoStart?: boolean
|
|
39
|
+
autoUpdate?: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** @experimental Lifecycle controls returned by `useDynamicLiveActivity`. */
|
|
43
|
+
export type UseDynamicLiveActivityResult = {
|
|
44
|
+
start: (options?: StartDynamicLiveActivityOptions) => Promise<void>
|
|
45
|
+
update: (options?: UpdateDynamicLiveActivityOptions) => Promise<void>
|
|
46
|
+
end: (options?: EndLiveActivityOptions) => Promise<void>
|
|
47
|
+
isActive: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function serializeDynamicLiveActivityProps(props: DynamicLiveActivityProps): string {
|
|
51
|
+
const ancestors = new Set<object>()
|
|
52
|
+
|
|
53
|
+
const validate = (value: unknown, path: string): void => {
|
|
54
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean') return
|
|
55
|
+
|
|
56
|
+
if (typeof value === 'number') {
|
|
57
|
+
if (!Number.isFinite(value)) {
|
|
58
|
+
throw new TypeError(`Dynamic Live Activity props must be JSON-compatible; ${path} is not a finite number.`)
|
|
59
|
+
}
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
if (ancestors.has(value)) {
|
|
65
|
+
throw new TypeError(
|
|
66
|
+
`Dynamic Live Activity props must be JSON-compatible; ${path} contains a circular reference.`
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
ancestors.add(value)
|
|
70
|
+
value.forEach((item, index) => validate(item, `${path}[${index}]`))
|
|
71
|
+
ancestors.delete(value)
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof value === 'object') {
|
|
76
|
+
const prototype = Object.getPrototypeOf(value)
|
|
77
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
78
|
+
throw new TypeError(`Dynamic Live Activity props must be JSON-compatible; ${path} must be a plain object.`)
|
|
79
|
+
}
|
|
80
|
+
if (ancestors.has(value)) {
|
|
81
|
+
throw new TypeError(
|
|
82
|
+
`Dynamic Live Activity props must be JSON-compatible; ${path} contains a circular reference.`
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
ancestors.add(value)
|
|
86
|
+
for (const [key, item] of Object.entries(value as Record<string, unknown>)) {
|
|
87
|
+
validate(item, `${path}.${key}`)
|
|
88
|
+
}
|
|
89
|
+
ancestors.delete(value)
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
throw new TypeError(
|
|
94
|
+
`Dynamic Live Activity props must be JSON-compatible; ${path} has unsupported type ${typeof value}.`
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (props === null || Array.isArray(props) || typeof props !== 'object') {
|
|
99
|
+
throw new TypeError('Dynamic Live Activity props must be a JSON-compatible record.')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
validate(props, 'props')
|
|
103
|
+
return JSON.stringify(props)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Starts a bundled Dynamic Live Activity with a complete opaque props record.
|
|
108
|
+
* @experimental
|
|
109
|
+
*/
|
|
110
|
+
export async function startDynamicLiveActivity(
|
|
111
|
+
definitionId: string,
|
|
112
|
+
props: DynamicLiveActivityProps,
|
|
113
|
+
options?: StartDynamicLiveActivityOptions
|
|
114
|
+
): Promise<string> {
|
|
115
|
+
if (!assertRunningOnApple()) return ''
|
|
116
|
+
|
|
117
|
+
const propsJson = serializeDynamicLiveActivityProps(props)
|
|
118
|
+
const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)
|
|
119
|
+
return getNativeVoltra().startDynamicLiveActivity(definitionId, propsJson, {
|
|
120
|
+
target: 'liveActivity',
|
|
121
|
+
deepLinkUrl: options?.deepLinkUrl,
|
|
122
|
+
activityName: options?.activityName,
|
|
123
|
+
channelId: options?.channelId,
|
|
124
|
+
...normalizedSharedOptions,
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Replaces a Dynamic Live Activity's complete opaque props record.
|
|
130
|
+
* @experimental
|
|
131
|
+
*/
|
|
132
|
+
export async function updateDynamicLiveActivity(
|
|
133
|
+
activityName: string,
|
|
134
|
+
props: DynamicLiveActivityProps,
|
|
135
|
+
options?: UpdateDynamicLiveActivityOptions
|
|
136
|
+
): Promise<void> {
|
|
137
|
+
if (!assertRunningOnApple()) return
|
|
138
|
+
|
|
139
|
+
const propsJson = serializeDynamicLiveActivityProps(props)
|
|
140
|
+
return getNativeVoltra().updateDynamicLiveActivity(
|
|
141
|
+
activityName,
|
|
142
|
+
propsJson,
|
|
143
|
+
normalizeSharedLiveActivityOptions(options) ?? {}
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Returns the Dynamic Live Activity definition IDs bundled in the installed app.
|
|
149
|
+
* @experimental
|
|
150
|
+
*/
|
|
151
|
+
export async function getDynamicLiveActivityDefinitionIds(): Promise<string[]> {
|
|
152
|
+
if (!assertRunningOnApple()) return []
|
|
153
|
+
return getNativeVoltra().getDynamicLiveActivityDefinitionIds()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Manages the lifecycle of one Dynamic Live Activity definition.
|
|
158
|
+
*
|
|
159
|
+
* Complete props are sent on every update. In development, call
|
|
160
|
+
* `enableDynamicLiveActivityHotReload()` once in the app host to reload only
|
|
161
|
+
* the definition changed by Fast Refresh.
|
|
162
|
+
* @experimental
|
|
163
|
+
*/
|
|
164
|
+
export function useDynamicLiveActivity<Props extends DynamicLiveActivityProps = DynamicLiveActivityProps>(
|
|
165
|
+
definitionId: string,
|
|
166
|
+
props: Props,
|
|
167
|
+
options?: UseDynamicLiveActivityOptions
|
|
168
|
+
): UseDynamicLiveActivityResult {
|
|
169
|
+
const [activityName, setActivityName] = useState<string | null>(() => {
|
|
170
|
+
if (options?.activityName) {
|
|
171
|
+
return isLiveActivityActive(options.activityName) ? options.activityName : null
|
|
172
|
+
}
|
|
173
|
+
return null
|
|
174
|
+
})
|
|
175
|
+
const propsRef = useRef(props)
|
|
176
|
+
const optionsRef = useRef(options)
|
|
177
|
+
const lastUpdateOptionsRef = useRef<UpdateDynamicLiveActivityOptions | undefined>(undefined)
|
|
178
|
+
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
propsRef.current = props
|
|
181
|
+
}, [props])
|
|
182
|
+
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
optionsRef.current = options
|
|
185
|
+
}, [options])
|
|
186
|
+
|
|
187
|
+
useUpdateOnHMR()
|
|
188
|
+
|
|
189
|
+
const start = useCallback(
|
|
190
|
+
async (startOptions?: StartDynamicLiveActivityOptions) => {
|
|
191
|
+
const id = await startDynamicLiveActivity(definitionId, propsRef.current, {
|
|
192
|
+
...optionsRef.current,
|
|
193
|
+
...startOptions,
|
|
194
|
+
})
|
|
195
|
+
setActivityName(id)
|
|
196
|
+
},
|
|
197
|
+
[definitionId]
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
const update = useCallback(
|
|
201
|
+
async (updateOptions?: UpdateDynamicLiveActivityOptions) => {
|
|
202
|
+
if (!activityName) return
|
|
203
|
+
|
|
204
|
+
const mergedOptions = { ...optionsRef.current, ...updateOptions }
|
|
205
|
+
lastUpdateOptionsRef.current = mergedOptions
|
|
206
|
+
await updateDynamicLiveActivity(activityName, propsRef.current, mergedOptions)
|
|
207
|
+
},
|
|
208
|
+
[activityName]
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
const end = useCallback(
|
|
212
|
+
async (endOptions?: EndLiveActivityOptions) => {
|
|
213
|
+
if (!activityName) return
|
|
214
|
+
|
|
215
|
+
await stopLiveActivity(activityName, endOptions)
|
|
216
|
+
setActivityName(null)
|
|
217
|
+
},
|
|
218
|
+
[activityName]
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (options?.autoStart) void start()
|
|
223
|
+
}, [options?.autoStart, start])
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
if (options?.autoUpdate) void update(lastUpdateOptionsRef.current)
|
|
227
|
+
}, [options?.autoUpdate, props, update])
|
|
228
|
+
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
if (!activityName) return
|
|
231
|
+
|
|
232
|
+
const subscription = addVoltraListener('stateChange', (event) => {
|
|
233
|
+
if (event.activityName !== activityName) return
|
|
234
|
+
if (event.activityState === 'dismissed' || event.activityState === 'ended') setActivityName(null)
|
|
235
|
+
})
|
|
236
|
+
return () => subscription.remove()
|
|
237
|
+
}, [activityName])
|
|
238
|
+
|
|
239
|
+
return { start, update, end, isActive: activityName !== null }
|
|
240
|
+
}
|
|
@@ -32,6 +32,15 @@ type VoltraInteractionEvent = Readonly<{
|
|
|
32
32
|
payload: string
|
|
33
33
|
}>
|
|
34
34
|
|
|
35
|
+
type VoltraDynamicLiveActivityRenderFailedEvent = Readonly<{
|
|
36
|
+
source: string
|
|
37
|
+
timestamp: number
|
|
38
|
+
type: 'dynamicLiveActivityRenderFailed'
|
|
39
|
+
activityName: string
|
|
40
|
+
definitionId: string
|
|
41
|
+
message: string
|
|
42
|
+
}>
|
|
43
|
+
|
|
35
44
|
type StartVoltraOptions = Readonly<{
|
|
36
45
|
target?: string
|
|
37
46
|
deepLinkUrl?: string
|
|
@@ -86,26 +95,39 @@ type WidgetServerCredentials = Readonly<{
|
|
|
86
95
|
|
|
87
96
|
export interface Spec extends TurboModule {
|
|
88
97
|
readonly onInteraction: CodegenTypes.EventEmitter<VoltraInteractionEvent>
|
|
98
|
+
readonly onDynamicLiveActivityRenderFailed: CodegenTypes.EventEmitter<VoltraDynamicLiveActivityRenderFailedEvent>
|
|
89
99
|
readonly onStateChanged: CodegenTypes.EventEmitter<VoltraActivityUpdateEvent>
|
|
90
100
|
readonly onActivityTokenReceived: CodegenTypes.EventEmitter<VoltraActivityTokenReceivedEvent>
|
|
91
101
|
readonly onActivityPushToStartTokenReceived: CodegenTypes.EventEmitter<VoltraActivityPushToStartTokenReceivedEvent>
|
|
102
|
+
drainDynamicLiveActivityRenderFailures(): void
|
|
103
|
+
setDynamicLiveActivityRenderFailureListenerActive(active: boolean): void
|
|
92
104
|
startLiveActivity(jsonString: string, options: StartVoltraOptions): Promise<string>
|
|
93
105
|
updateLiveActivity(activityId: string, jsonString: string, options: UpdateVoltraOptions): Promise<void>
|
|
106
|
+
startDynamicLiveActivity(definitionId: string, propsJson: string, options: StartVoltraOptions): Promise<string>
|
|
107
|
+
updateDynamicLiveActivity(activityId: string, propsJson: string, options: UpdateVoltraOptions): Promise<void>
|
|
94
108
|
endLiveActivity(activityId: string, options: EndVoltraOptions): Promise<void>
|
|
95
109
|
endAllLiveActivities(): Promise<void>
|
|
96
110
|
getLatestVoltraActivityId(): Promise<string | null>
|
|
97
111
|
listVoltraActivityIds(): Promise<string[]>
|
|
112
|
+
getDynamicLiveActivityDefinitionIds(): Promise<string[]>
|
|
98
113
|
isLiveActivityActive(activityName: string): boolean
|
|
99
114
|
isHeadless(): boolean
|
|
100
115
|
preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult>
|
|
101
116
|
reloadLiveActivities(activityNames?: string[] | null): Promise<void>
|
|
117
|
+
reloadDynamicLiveActivities(definitionIds?: string[] | null): Promise<void>
|
|
102
118
|
clearPreloadedImages(keys?: string[] | null): Promise<void>
|
|
119
|
+
updateDynamicWidget(dynamicWidgetId: string, dynamicWidgetPropsJson: string): Promise<void>
|
|
103
120
|
updateWidget(widgetId: string, jsonString: string, options: UpdateWidgetOptions): Promise<void>
|
|
104
121
|
scheduleWidget(widgetId: string, timelineJson: string): Promise<void>
|
|
105
122
|
reloadWidgets(widgetIds?: string[] | null): Promise<void>
|
|
106
123
|
clearWidget(widgetId: string): Promise<void>
|
|
107
124
|
clearAllWidgets(): Promise<void>
|
|
108
125
|
getActiveWidgets<T = unknown>(): Promise<T[]>
|
|
126
|
+
/** Settings are passed as JSON so an arbitrary `body` survives the bridge unchanged. */
|
|
127
|
+
setWidgetServerUpdate(settingsJson: string, widgetId?: string | null): Promise<void>
|
|
128
|
+
clearWidgetServerUpdate(widgetId?: string | null): Promise<void>
|
|
129
|
+
/** Result is JSON so an arbitrary `body` survives the bridge unchanged, or null. */
|
|
130
|
+
getWidgetServerUpdate(widgetId?: string | null): Promise<string | null>
|
|
109
131
|
setWidgetServerCredentials(credentials: WidgetServerCredentials): Promise<void>
|
|
110
132
|
clearWidgetServerCredentials(): Promise<void>
|
|
111
133
|
}
|
package/src/types.ts
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getFastRefreshHub } from '@use-voltra/ios'
|
|
2
|
+
|
|
3
|
+
import { getNativeVoltra } from '../VoltraModule.js'
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
var __voltraDynamicLiveActivityDefinitionUpdated: ((definitionId: string) => void) | undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reload Dynamic Live Activities after a Metro Fast Refresh patch. When Metro
|
|
11
|
+
* re-evaluates a generated definition entry, only that definition is reloaded.
|
|
12
|
+
* Component-only refresh boundaries do not re-evaluate their importer, so those
|
|
13
|
+
* patches fall back to reloading every Dynamic Live Activity definition.
|
|
14
|
+
* Legacy activities and Dynamic Widgets are unaffected.
|
|
15
|
+
*
|
|
16
|
+
* Subscribes to the shared {@link getFastRefreshHub} so multiple `__accept`
|
|
17
|
+
* calls from one save collapse into a single native reload.
|
|
18
|
+
*/
|
|
19
|
+
export function enableDynamicLiveActivityHotReload(): () => void {
|
|
20
|
+
if (!__DEV__) return () => {}
|
|
21
|
+
|
|
22
|
+
const hub = getFastRefreshHub()
|
|
23
|
+
const previousDefinitionUpdated = global.__voltraDynamicLiveActivityDefinitionUpdated
|
|
24
|
+
const updatedDefinitionIds = new Set<string>()
|
|
25
|
+
|
|
26
|
+
global.__voltraDynamicLiveActivityDefinitionUpdated = (definitionId) => {
|
|
27
|
+
// A generated entry re-evaluated inside a patch: batch it so the debounced
|
|
28
|
+
// flush reloads each changed definition exactly once. A signal that arrives
|
|
29
|
+
// outside a patch (the first require of a definition) has no flush coming,
|
|
30
|
+
// so reload it immediately.
|
|
31
|
+
if (hub.isAccepting) {
|
|
32
|
+
updatedDefinitionIds.add(definitionId)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
void getNativeVoltra().reloadDynamicLiveActivities([definitionId])
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const unsubscribe = hub.onPatch(() => {
|
|
39
|
+
const definitionIds = Array.from(updatedDefinitionIds)
|
|
40
|
+
updatedDefinitionIds.clear()
|
|
41
|
+
// No definition re-evaluated during this patch: a component-only boundary
|
|
42
|
+
// changed, so fall back to reloading every definition (null).
|
|
43
|
+
void getNativeVoltra().reloadDynamicLiveActivities(definitionIds.length > 0 ? definitionIds : null)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
unsubscribe()
|
|
48
|
+
global.__voltraDynamicLiveActivityDefinitionUpdated = previousDefinitionUpdated
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getFastRefreshHub } from '@use-voltra/ios'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
var __accept: (...args: unknown[]) => void
|
|
5
|
-
}
|
|
3
|
+
import { reloadWidgets } from '../widgets/widget-api.js'
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* Trigger `reloadWidgets()` on every Metro Fast Refresh patch (DEV only).
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Subscribes to the shared {@link getFastRefreshHub}, which wraps the global
|
|
9
|
+
* `__accept` callback Metro fires when a Fast Refresh patch lands in the host
|
|
10
|
+
* app's JS runtime. On each debounced patch it calls
|
|
12
11
|
* `WidgetCenter.shared.reloadAllTimelines()` so WidgetKit re-invokes each widget
|
|
13
12
|
* Provider, which re-fetches the freshest bundle from Metro and renders the
|
|
14
13
|
* updated UI.
|
|
@@ -19,21 +18,15 @@ declare global {
|
|
|
19
18
|
* workflow the dev still relies on WidgetKit's natural lifecycle refresh on
|
|
20
19
|
* app foreground.
|
|
21
20
|
*
|
|
22
|
-
* Call once at app startup. Returns `dispose()` to
|
|
23
|
-
*
|
|
21
|
+
* Call once at app startup. Returns `dispose()` to unsubscribe (rarely needed
|
|
22
|
+
* in practice). No-op in release builds.
|
|
24
23
|
*/
|
|
25
24
|
export function enableWidgetHotReload(): () => void {
|
|
26
25
|
if (!__DEV__) {
|
|
27
26
|
return () => {}
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
global['__accept'] = (...args) => {
|
|
29
|
+
return getFastRefreshHub().onPatch(() => {
|
|
32
30
|
void reloadWidgets()
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return () => {
|
|
37
|
-
global['__accept'] = oldAccept
|
|
38
|
-
}
|
|
31
|
+
})
|
|
39
32
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
+
import { getFastRefreshHub } from '@use-voltra/ios'
|
|
1
2
|
import { useEffect, useState } from 'react'
|
|
2
3
|
|
|
3
|
-
declare global {
|
|
4
|
-
var __accept: (...args: unknown[]) => void
|
|
5
|
-
}
|
|
6
|
-
|
|
7
4
|
export const useUpdateOnHMR = () => {
|
|
8
5
|
const [, forceUpdate] = useState(0)
|
|
9
6
|
|
|
@@ -12,14 +9,8 @@ export const useUpdateOnHMR = () => {
|
|
|
12
9
|
return
|
|
13
10
|
}
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
global['__accept'] = (...args) => {
|
|
12
|
+
return getFastRefreshHub().onPatch(() => {
|
|
17
13
|
forceUpdate((prev) => prev + 1)
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return () => {
|
|
22
|
-
global['__accept'] = oldAccept
|
|
23
|
-
}
|
|
14
|
+
})
|
|
24
15
|
}, [])
|
|
25
16
|
}
|
|
@@ -3,6 +3,11 @@ import { getNativeVoltra } from '../VoltraModule.js'
|
|
|
3
3
|
|
|
4
4
|
export type { WidgetServerCredentials } from '../types.js'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use {@link setWidgetServerUpdate} with an `Authorization` header. This writes the
|
|
8
|
+
* same stored credentials and keeps the same replace-everything semantics, so migrating is a
|
|
9
|
+
* one-line change; it will be removed in a future major.
|
|
10
|
+
*/
|
|
6
11
|
export async function setWidgetServerCredentials(credentials: WidgetServerCredentials): Promise<void> {
|
|
7
12
|
if (!credentials.token) {
|
|
8
13
|
throw new Error('[Voltra][iOS] setWidgetServerCredentials: token is required')
|
|
@@ -11,6 +16,9 @@ export async function setWidgetServerCredentials(credentials: WidgetServerCreden
|
|
|
11
16
|
return getNativeVoltra().setWidgetServerCredentials(credentials)
|
|
12
17
|
}
|
|
13
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Use {@link clearWidgetServerUpdate} instead.
|
|
21
|
+
*/
|
|
14
22
|
export async function clearWidgetServerCredentials(): Promise<void> {
|
|
15
23
|
return getNativeVoltra().clearWidgetServerCredentials()
|
|
16
24
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { WidgetServerUpdateOptions, WidgetServerUpdateSettings, WidgetServerUpdateSnapshot } from '../types.js'
|
|
2
|
+
import { getNativeVoltra } from '../VoltraModule.js'
|
|
3
|
+
|
|
4
|
+
export type {
|
|
5
|
+
WidgetServerUpdateBody,
|
|
6
|
+
WidgetServerUpdateOptions,
|
|
7
|
+
WidgetServerUpdateSettings,
|
|
8
|
+
WidgetServerUpdateSnapshot,
|
|
9
|
+
} from '../types.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Overrides a server-driven widget's `serverUpdate` settings at runtime.
|
|
13
|
+
*
|
|
14
|
+
* The `serverUpdate` entry in app.json supplies the defaults; this replaces any of them for one
|
|
15
|
+
* widget, or for every server-driven widget when no `widgetId` is given. A widget-scoped call wins
|
|
16
|
+
* over a global one, and `headers` and `query` merge per key across the two.
|
|
17
|
+
*
|
|
18
|
+
* Each call replaces the whole layer it writes, so pass every field you want to keep. Setting
|
|
19
|
+
* anything reschedules the widgets it affects and fetches once immediately.
|
|
20
|
+
*
|
|
21
|
+
* @example Point a widget at the tenant's own backend once the user has logged in.
|
|
22
|
+
* ```ts
|
|
23
|
+
* await setWidgetServerUpdate(
|
|
24
|
+
* { url: `https://${tenant}.example.com/widgets/portfolio`, headers: { Authorization: `Bearer ${token}` } },
|
|
25
|
+
* { widgetId: 'portfolio' }
|
|
26
|
+
* )
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example Take a widget over and drive it from the app until you hand it back.
|
|
30
|
+
* ```ts
|
|
31
|
+
* await setWidgetServerUpdate({ enabled: false }, { widgetId: 'portfolio' })
|
|
32
|
+
* await updateDynamicWidget('portfolio', localProps)
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @throws if the widget has no `serverUpdate` in app.json, if the URL is not https (plain http is
|
|
36
|
+
* allowed only in a debug build, and only for a local dev host), or if `query` names one of the
|
|
37
|
+
* parameters Voltra already sends.
|
|
38
|
+
*/
|
|
39
|
+
export async function setWidgetServerUpdate(
|
|
40
|
+
settings: WidgetServerUpdateSettings,
|
|
41
|
+
options?: WidgetServerUpdateOptions
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
return getNativeVoltra().setWidgetServerUpdate(JSON.stringify(settings ?? {}), options?.widgetId ?? null)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Drops the runtime settings for one widget, or the global ones when no `widgetId` is given, so
|
|
48
|
+
* the widget falls back to what app.json configured.
|
|
49
|
+
*
|
|
50
|
+
* Clearing the global settings is the logout gesture: along with the settings it drops what the
|
|
51
|
+
* server last sent for every server-driven widget, so a Dynamic Widget goes back to `{}` with
|
|
52
|
+
* `env.serverUpdate.status` of `never` rather than showing the previous account's data. Credentials
|
|
53
|
+
* set with the deprecated `setWidgetServerCredentials` are stored separately — clear those with
|
|
54
|
+
* `clearWidgetServerCredentials`.
|
|
55
|
+
*/
|
|
56
|
+
export async function clearWidgetServerUpdate(options?: WidgetServerUpdateOptions): Promise<void> {
|
|
57
|
+
return getNativeVoltra().clearWidgetServerUpdate(options?.widgetId ?? null)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Reads a widget's `serverUpdate` settings back, without reasoning about what was set where.
|
|
62
|
+
*
|
|
63
|
+
* With a `widgetId`, this is the fully resolved settings that widget would fetch with right now:
|
|
64
|
+
* every layer flattened and app.json's defaults applied — `null` if the widget is not
|
|
65
|
+
* server-driven. Without one, this is the raw contents of the global layer only — what the last
|
|
66
|
+
* `setWidgetServerUpdate(settings)` call (with no `widgetId`) wrote, with no defaults applied and
|
|
67
|
+
* every field optional — `null` if nothing has been set globally.
|
|
68
|
+
*
|
|
69
|
+
* @example Check what a widget is about to fetch from.
|
|
70
|
+
* ```ts
|
|
71
|
+
* const snapshot = await getWidgetServerUpdate({ widgetId: 'portfolio' })
|
|
72
|
+
* if (snapshot?.enabled) {
|
|
73
|
+
* console.log(`portfolio fetches ${snapshot.url} every ${snapshot.intervalMinutes}m`)
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export async function getWidgetServerUpdate(options: { widgetId: string }): Promise<WidgetServerUpdateSnapshot | null>
|
|
78
|
+
export async function getWidgetServerUpdate(options?: undefined): Promise<WidgetServerUpdateSettings | null>
|
|
79
|
+
export async function getWidgetServerUpdate(
|
|
80
|
+
options?: WidgetServerUpdateOptions
|
|
81
|
+
): Promise<WidgetServerUpdateSnapshot | WidgetServerUpdateSettings | null> {
|
|
82
|
+
const json = await getNativeVoltra().getWidgetServerUpdate(options?.widgetId ?? null)
|
|
83
|
+
return json == null ? null : JSON.parse(json)
|
|
84
|
+
}
|
|
File without changes
|