@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
|
@@ -1,34 +1,52 @@
|
|
|
1
1
|
import { XcodeProject } from '@expo/config-plugins'
|
|
2
2
|
|
|
3
3
|
import { IOS } from '../../constants'
|
|
4
|
+
import type { MainAppSigningSettings, MainAppTargetSettings } from './mainAppSettings'
|
|
4
5
|
|
|
5
|
-
export interface
|
|
6
|
+
export interface EnsureConfigurationListOptions {
|
|
6
7
|
targetName: string
|
|
7
8
|
bundleIdentifier: string
|
|
8
9
|
deploymentTarget: string
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* App marketing version (CFBundleShortVersionString). App Store Connect expects the appex
|
|
12
|
+
* version to match the app's, so this becomes the widget's MARKETING_VERSION.
|
|
13
|
+
*/
|
|
14
|
+
version?: string
|
|
15
|
+
/** App build number; becomes the widget's CURRENT_PROJECT_VERSION. */
|
|
16
|
+
buildNumber?: string
|
|
17
|
+
/** Main app signing settings, applied per configuration name (Debug→Debug, Release→Release). */
|
|
18
|
+
mainAppSettings?: MainAppTargetSettings | null
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the main app signing settings for a widget configuration name: an exact name match
|
|
23
|
+
* wins, otherwise the first available configuration's settings are used as fallback.
|
|
24
|
+
*/
|
|
25
|
+
function signingForConfiguration(
|
|
26
|
+
mainAppSettings: MainAppTargetSettings | null | undefined,
|
|
27
|
+
configurationName: string
|
|
28
|
+
): MainAppSigningSettings {
|
|
29
|
+
if (!mainAppSettings) {
|
|
30
|
+
return {}
|
|
31
|
+
}
|
|
32
|
+
return mainAppSettings.byConfigurationName[configurationName] ?? mainAppSettings.fallback
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createBuildSettings(options: EnsureConfigurationListOptions, configurationName: string) {
|
|
36
|
+
const { targetName, bundleIdentifier, deploymentTarget, version, buildNumber, mainAppSettings } = options
|
|
37
|
+
const { codeSignStyle, developmentTeam, provisioningProfileSpecifier } = signingForConfiguration(
|
|
38
|
+
mainAppSettings,
|
|
39
|
+
configurationName
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const buildSettings: Record<string, string> = {
|
|
25
43
|
PRODUCT_NAME: `"$(TARGET_NAME)"`,
|
|
26
44
|
SWIFT_VERSION: IOS.SWIFT_VERSION,
|
|
27
45
|
TARGETED_DEVICE_FAMILY: `"${IOS.DEVICE_FAMILY}"`,
|
|
28
46
|
INFOPLIST_FILE: `${targetName}/Info.plist`,
|
|
29
47
|
INFOPLIST_OUTPUT_FORMAT: `"xml"`,
|
|
30
|
-
CURRENT_PROJECT_VERSION: `"1"`,
|
|
31
|
-
MARKETING_VERSION: `"1.0"`,
|
|
48
|
+
CURRENT_PROJECT_VERSION: `"${buildNumber ?? '1'}"`,
|
|
49
|
+
MARKETING_VERSION: `"${version ?? '1.0'}"`,
|
|
32
50
|
IPHONEOS_DEPLOYMENT_TARGET: `"${deploymentTarget}"`,
|
|
33
51
|
PRODUCT_BUNDLE_IDENTIFIER: `"${bundleIdentifier}"`,
|
|
34
52
|
SWIFT_OPTIMIZATION_LEVEL: `"-Onone"`,
|
|
@@ -37,41 +55,37 @@ function createCommonBuildSettings(options: AddConfigurationListOptions) {
|
|
|
37
55
|
ASSETCATALOG_COMPILER_APPICON_NAME: '""',
|
|
38
56
|
}
|
|
39
57
|
|
|
40
|
-
// Synchronize code signing settings from main app target
|
|
58
|
+
// Synchronize code signing settings from the main app target's matching configuration
|
|
41
59
|
if (codeSignStyle) {
|
|
42
|
-
|
|
60
|
+
buildSettings.CODE_SIGN_STYLE = `"${codeSignStyle}"`
|
|
43
61
|
}
|
|
44
62
|
if (developmentTeam) {
|
|
45
|
-
|
|
63
|
+
buildSettings.DEVELOPMENT_TEAM = `"${developmentTeam}"`
|
|
46
64
|
}
|
|
47
65
|
if (provisioningProfileSpecifier) {
|
|
48
|
-
|
|
66
|
+
buildSettings.PROVISIONING_PROFILE_SPECIFIER = `"${provisioningProfileSpecifier}"`
|
|
49
67
|
}
|
|
50
68
|
|
|
51
|
-
return
|
|
69
|
+
return buildSettings
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
/**
|
|
55
|
-
* Adds
|
|
73
|
+
* Adds a fresh XCConfigurationList for the widget extension target. Internal create-only fallback
|
|
74
|
+
* for {@link ensureXCConfigurationList}; not part of the public pipeline.
|
|
56
75
|
*/
|
|
57
|
-
|
|
76
|
+
function addXCConfigurationList(xcodeProject: XcodeProject, options: EnsureConfigurationListOptions) {
|
|
58
77
|
const { targetName } = options
|
|
59
|
-
const commonBuildSettings = createCommonBuildSettings(options)
|
|
60
78
|
|
|
61
79
|
const buildConfigurationsList = [
|
|
62
80
|
{
|
|
63
81
|
name: 'Debug',
|
|
64
82
|
isa: 'XCBuildConfiguration',
|
|
65
|
-
buildSettings:
|
|
66
|
-
...commonBuildSettings,
|
|
67
|
-
},
|
|
83
|
+
buildSettings: createBuildSettings(options, 'Debug'),
|
|
68
84
|
},
|
|
69
85
|
{
|
|
70
86
|
name: 'Release',
|
|
71
87
|
isa: 'XCBuildConfiguration',
|
|
72
|
-
buildSettings:
|
|
73
|
-
...commonBuildSettings,
|
|
74
|
-
},
|
|
88
|
+
buildSettings: createBuildSettings(options, 'Release'),
|
|
75
89
|
},
|
|
76
90
|
]
|
|
77
91
|
|
|
@@ -85,11 +99,13 @@ export function addXCConfigurationList(xcodeProject: XcodeProject, options: AddC
|
|
|
85
99
|
}
|
|
86
100
|
|
|
87
101
|
/**
|
|
88
|
-
* Ensures an existing XCConfigurationList is updated, or adds a new one if missing.
|
|
102
|
+
* Ensures an existing XCConfigurationList is updated, or adds a new one if missing. Each widget
|
|
103
|
+
* configuration receives the build settings derived for its own name, so Debug and Release signing
|
|
104
|
+
* stay in sync with the main app's respective configurations.
|
|
89
105
|
*/
|
|
90
106
|
export function ensureXCConfigurationList(
|
|
91
107
|
xcodeProject: XcodeProject,
|
|
92
|
-
options:
|
|
108
|
+
options: EnsureConfigurationListOptions,
|
|
93
109
|
existingConfigurationListId?: string | { value?: string }
|
|
94
110
|
) {
|
|
95
111
|
const configurationListId =
|
|
@@ -103,7 +119,6 @@ export function ensureXCConfigurationList(
|
|
|
103
119
|
return addXCConfigurationList(xcodeProject, options)
|
|
104
120
|
}
|
|
105
121
|
|
|
106
|
-
const commonBuildSettings = createCommonBuildSettings(options)
|
|
107
122
|
const buildConfigurations = configurationList.buildConfigurations
|
|
108
123
|
const buildConfigurationSection = xcodeProject.pbxXCBuildConfigurationSection()
|
|
109
124
|
|
|
@@ -117,9 +132,11 @@ export function ensureXCConfigurationList(
|
|
|
117
132
|
continue
|
|
118
133
|
}
|
|
119
134
|
|
|
135
|
+
const configurationName =
|
|
136
|
+
typeof buildConfiguration.name === 'string' ? buildConfiguration.name.replace(/^"|"$/g, '') : ''
|
|
120
137
|
buildConfiguration.buildSettings = {
|
|
121
138
|
...(buildConfiguration.buildSettings ?? {}),
|
|
122
|
-
...
|
|
139
|
+
...createBuildSettings(options, configurationName),
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { XcodeProject } from '@expo/config-plugins'
|
|
2
|
+
|
|
3
|
+
const pbxFile = require('xcode/lib/pbxFile')
|
|
4
|
+
|
|
5
|
+
/** Strips surrounding quotes from a pbx path/name value. */
|
|
6
|
+
export function normalizePath(value: string | undefined): string {
|
|
7
|
+
if (!value) {
|
|
8
|
+
return ''
|
|
9
|
+
}
|
|
10
|
+
return value.replace(/^"|"$/g, '')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Strips a trailing `/* comment *\/` and whitespace, yielding the bare UUID of a pbx reference. */
|
|
14
|
+
export function normalizeRef(value: unknown): string {
|
|
15
|
+
return String(value)
|
|
16
|
+
.replace(/\/\*.*?\*\//g, '')
|
|
17
|
+
.trim()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolves the PBXFileReference UUID for a widget file, scoped to the widget's own PBXGroup.
|
|
22
|
+
*
|
|
23
|
+
* pbxproj paths are group-relative, so a bare path like `Assets.xcassets` collides with any other
|
|
24
|
+
* extension's identically named file. Scoping the lookup to the children of the widget group
|
|
25
|
+
* (identified by `targetName`) keeps the widget's references distinct from those, which is what
|
|
26
|
+
* prevents the shared-fileRef corruption behind issues #87/#32. When the widget group does not
|
|
27
|
+
* exist yet, a fresh reference is created.
|
|
28
|
+
*/
|
|
29
|
+
export function ensureWidgetFileReference(xcodeProject: XcodeProject, filePath: string, targetName: string): string {
|
|
30
|
+
const file = new pbxFile(filePath)
|
|
31
|
+
const fileReferenceSection = xcodeProject.pbxFileReferenceSection()
|
|
32
|
+
const group = xcodeProject.pbxGroupByName(targetName)
|
|
33
|
+
|
|
34
|
+
if (group?.children) {
|
|
35
|
+
for (const child of group.children) {
|
|
36
|
+
const refKey = normalizeRef(child.value)
|
|
37
|
+
const entry = fileReferenceSection[refKey]
|
|
38
|
+
if (!entry) {
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
const entryPath = normalizePath(entry.path)
|
|
42
|
+
if (entryPath === file.path || entryPath === normalizePath(filePath)) {
|
|
43
|
+
return refKey
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
file.fileRef = xcodeProject.generateUuid()
|
|
49
|
+
xcodeProject.addToPbxFileReferenceSection(file)
|
|
50
|
+
return file.fileRef
|
|
51
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { XcodeProject } from '@expo/config-plugins'
|
|
2
2
|
|
|
3
3
|
import type { IOSWidgetExtensionFiles } from '../../types'
|
|
4
|
+
import { ensureWidgetFileReference } from './fileReferences'
|
|
4
5
|
|
|
5
6
|
const pbxFile = require('xcode/lib/pbxFile')
|
|
6
7
|
|
|
@@ -9,37 +10,63 @@ export interface AddPbxGroupOptions {
|
|
|
9
10
|
widgetFiles: IOSWidgetExtensionFiles
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
function collectGroupFiles(widgetFiles: IOSWidgetExtensionFiles): string[] {
|
|
14
|
+
const { swiftFiles, intentFiles, assetDirectories, entitlementFiles, plistFiles, localizedStringResources } =
|
|
15
|
+
widgetFiles
|
|
16
|
+
return [
|
|
17
|
+
...swiftFiles,
|
|
18
|
+
...intentFiles,
|
|
19
|
+
...entitlementFiles,
|
|
20
|
+
...plistFiles,
|
|
21
|
+
...assetDirectories,
|
|
22
|
+
...localizedStringResources,
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
|
|
12
26
|
/**
|
|
13
27
|
* Adds a PBXGroup for the widget extension files.
|
|
28
|
+
*
|
|
29
|
+
* Constructs the PBXGroup and its PBXFileReference children by hand rather than delegating to
|
|
30
|
+
* `xcodeProject.addPbxGroup`, because that helper also creates a PBXBuildFile per file as a side
|
|
31
|
+
* effect. Those extra build files collide with the ones managed by the build-phase functions and
|
|
32
|
+
* produce the "no parent for object" consistency errors from issues #87/#32. File references are
|
|
33
|
+
* resolved through the widget-scoped {@link ensureWidgetFileReference} so they are shared with the
|
|
34
|
+
* build phases instead of duplicated.
|
|
35
|
+
*
|
|
36
|
+
* Internal create-only fallback for {@link ensurePbxGroup}; not part of the public pipeline.
|
|
14
37
|
*/
|
|
15
|
-
|
|
38
|
+
function addPbxGroup(xcodeProject: XcodeProject, options: AddPbxGroupOptions): void {
|
|
16
39
|
const { targetName, widgetFiles } = options
|
|
17
|
-
const
|
|
18
|
-
widgetFiles
|
|
40
|
+
const allFiles = collectGroupFiles(widgetFiles)
|
|
19
41
|
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
...localizedStringResources,
|
|
29
|
-
],
|
|
30
|
-
targetName,
|
|
31
|
-
targetName
|
|
32
|
-
)
|
|
42
|
+
const pbxGroupUuid = xcodeProject.generateUuid()
|
|
43
|
+
const pbxGroup = {
|
|
44
|
+
isa: 'PBXGroup',
|
|
45
|
+
children: [] as { value: string; comment: string }[],
|
|
46
|
+
name: targetName,
|
|
47
|
+
path: targetName,
|
|
48
|
+
sourceTree: '"<group>"',
|
|
49
|
+
}
|
|
33
50
|
|
|
34
|
-
// Add PBXGroup to top level group
|
|
35
51
|
const groups = xcodeProject.hash.project.objects['PBXGroup']
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
groups[pbxGroupUuid] = pbxGroup
|
|
53
|
+
groups[`${pbxGroupUuid}_comment`] = targetName
|
|
54
|
+
|
|
55
|
+
for (const filePath of allFiles) {
|
|
56
|
+
const file = new pbxFile(filePath)
|
|
57
|
+
const fileRef = ensureWidgetFileReference(xcodeProject, filePath, targetName)
|
|
58
|
+
pbxGroup.children.push({ value: fileRef, comment: file.basename })
|
|
42
59
|
}
|
|
60
|
+
|
|
61
|
+
// Attach the new group to the top-level (unnamed, path-less) group.
|
|
62
|
+
Object.keys(groups).forEach(function (key) {
|
|
63
|
+
if (/_comment$/.test(key)) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
if (groups[key].name === undefined && groups[key].path === undefined) {
|
|
67
|
+
xcodeProject.addToPbxGroup(pbxGroupUuid, key)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
43
70
|
}
|
|
44
71
|
|
|
45
72
|
/**
|
|
@@ -47,16 +74,7 @@ export function addPbxGroup(xcodeProject: XcodeProject, options: AddPbxGroupOpti
|
|
|
47
74
|
*/
|
|
48
75
|
export function ensurePbxGroup(xcodeProject: XcodeProject, options: AddPbxGroupOptions): void {
|
|
49
76
|
const { targetName, widgetFiles } = options
|
|
50
|
-
const
|
|
51
|
-
widgetFiles
|
|
52
|
-
const allFiles = [
|
|
53
|
-
...swiftFiles,
|
|
54
|
-
...intentFiles,
|
|
55
|
-
...entitlementFiles,
|
|
56
|
-
...plistFiles,
|
|
57
|
-
...assetDirectories,
|
|
58
|
-
...localizedStringResources,
|
|
59
|
-
]
|
|
77
|
+
const allFiles = collectGroupFiles(widgetFiles)
|
|
60
78
|
|
|
61
79
|
const existingGroup = xcodeProject.pbxGroupByName(targetName)
|
|
62
80
|
if (!existingGroup) {
|
|
@@ -70,7 +88,7 @@ export function ensurePbxGroup(xcodeProject: XcodeProject, options: AddPbxGroupO
|
|
|
70
88
|
|
|
71
89
|
for (const filePath of allFiles) {
|
|
72
90
|
const file = new pbxFile(filePath)
|
|
73
|
-
const fileRef =
|
|
91
|
+
const fileRef = ensureWidgetFileReference(xcodeProject, filePath, targetName)
|
|
74
92
|
const alreadyInGroup = existingGroup.children.some(
|
|
75
93
|
(child: any) => child.value === fileRef || child.comment === file.basename
|
|
76
94
|
)
|
|
@@ -79,23 +97,3 @@ export function ensurePbxGroup(xcodeProject: XcodeProject, options: AddPbxGroupO
|
|
|
79
97
|
}
|
|
80
98
|
}
|
|
81
99
|
}
|
|
82
|
-
|
|
83
|
-
function ensureFileReference(xcodeProject: XcodeProject, filePath: string): string {
|
|
84
|
-
const fileReferenceSection = xcodeProject.pbxFileReferenceSection()
|
|
85
|
-
const file = new pbxFile(filePath)
|
|
86
|
-
|
|
87
|
-
for (const key of Object.keys(fileReferenceSection)) {
|
|
88
|
-
if (/_comment$/.test(key)) {
|
|
89
|
-
continue
|
|
90
|
-
}
|
|
91
|
-
const entry = fileReferenceSection[key]
|
|
92
|
-
const entryPath = typeof entry?.path === 'string' ? entry.path.replace(/^"|"$/g, '') : ''
|
|
93
|
-
if (entryPath === file.path || entryPath === filePath) {
|
|
94
|
-
return key
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
file.fileRef = xcodeProject.generateUuid()
|
|
99
|
-
xcodeProject.addToPbxFileReferenceSection(file)
|
|
100
|
-
return file.fileRef
|
|
101
|
-
}
|
|
@@ -1,21 +1,133 @@
|
|
|
1
|
-
import { ConfigPlugin, withXcodeProject } from '@expo/config-plugins'
|
|
1
|
+
import { ConfigPlugin, withXcodeProject, XcodeProject } from '@expo/config-plugins'
|
|
2
2
|
import * as path from 'path'
|
|
3
3
|
|
|
4
|
-
import type { IOSWidgetConfig } from '../../types'
|
|
4
|
+
import type { IOSDynamicLiveActivityConfig, IOSWidgetConfig, IOSWidgetExtensionFiles } from '../../types'
|
|
5
5
|
import { getIOSWidgetExtensionFiles } from '../../utils/fileDiscovery'
|
|
6
6
|
import { detectClientRenderedWidgets } from '../clientRendered'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { ensureBuildPhases, ensureWidgetBundleScriptPhase } from './buildPhases'
|
|
8
|
+
import { ensureXCConfigurationList } from './configurationList'
|
|
9
|
+
import { ensurePbxGroup } from './groups'
|
|
10
10
|
import { getMainAppTargetSettings } from './mainAppSettings'
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { ensureProductFile } from './productFile'
|
|
12
|
+
import { createTargetSkeleton, ensureTargetAttributes, ensureTargetDependency } from './target'
|
|
13
13
|
|
|
14
14
|
export interface ConfigureXcodeProjectProps {
|
|
15
15
|
targetName: string
|
|
16
16
|
bundleIdentifier: string
|
|
17
17
|
deploymentTarget: string
|
|
18
|
+
/** App marketing version; becomes the widget's MARKETING_VERSION so the appex matches the app. */
|
|
19
|
+
version?: string
|
|
20
|
+
/** App build number; becomes the widget's CURRENT_PROJECT_VERSION. */
|
|
21
|
+
buildNumber?: string
|
|
18
22
|
widgets?: IOSWidgetConfig[]
|
|
23
|
+
liveActivities?: IOSDynamicLiveActivityConfig[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Applies all widget-extension changes to an already-parsed Xcode project.
|
|
28
|
+
*
|
|
29
|
+
* This is the pure core of {@link configureXcodeProject}: it takes the parsed project, the plugin
|
|
30
|
+
* props, the discovered widget files, and whether any widget is client-rendered, then mutates the
|
|
31
|
+
* project in place. It performs no filesystem or `modRequest` access, which makes it directly
|
|
32
|
+
* testable against pbxproj fixtures.
|
|
33
|
+
*
|
|
34
|
+
* When the widget target does not exist yet, the minimal native-target skeleton is created first
|
|
35
|
+
* (targets cannot be "ensured" into existence); every other object is then reconciled by the same
|
|
36
|
+
* idempotent ensure pipeline that runs for an already-existing target.
|
|
37
|
+
*/
|
|
38
|
+
export function applyXcodeChanges(
|
|
39
|
+
xcodeProject: XcodeProject,
|
|
40
|
+
props: ConfigureXcodeProjectProps,
|
|
41
|
+
widgetFiles: IOSWidgetExtensionFiles,
|
|
42
|
+
hasClientRenderedWidgets = false
|
|
43
|
+
): void {
|
|
44
|
+
const { targetName, bundleIdentifier, deploymentTarget, version, buildNumber } = props
|
|
45
|
+
const groupName = 'Embed Foundation Extensions'
|
|
46
|
+
const mainTargetUuid = xcodeProject.getFirstTarget().uuid
|
|
47
|
+
// The catalog is compiled into the app even for a legacy-only configuration.
|
|
48
|
+
// Keep it in the extension group too so both targets share one PBX file reference.
|
|
49
|
+
const effectiveWidgetFiles: IOSWidgetExtensionFiles = {
|
|
50
|
+
...widgetFiles,
|
|
51
|
+
swiftFiles: Array.from(new Set([...widgetFiles.swiftFiles, 'VoltraDynamicLiveActivityTypes.swift'])),
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Read main app target settings to synchronize code signing (per configuration).
|
|
55
|
+
const mainAppSettings = getMainAppTargetSettings(xcodeProject)
|
|
56
|
+
|
|
57
|
+
// Use the deploymentTarget from plugin config (or default), ignore main app's deployment target.
|
|
58
|
+
// This allows the widget extension to have its own deployment target independent of the main app.
|
|
59
|
+
|
|
60
|
+
// Resolve (or create) the widget target. A target cannot be reconciled into existence, so the
|
|
61
|
+
// absent case creates the minimal skeleton; from here on both paths share one pipeline.
|
|
62
|
+
let targetUuid = xcodeProject.findTargetKey(targetName)
|
|
63
|
+
if (!targetUuid) {
|
|
64
|
+
targetUuid = xcodeProject.generateUuid()
|
|
65
|
+
createTargetSkeleton(xcodeProject, { targetName, targetUuid })
|
|
66
|
+
}
|
|
67
|
+
const target = xcodeProject.pbxNativeTargetSection()[targetUuid]
|
|
68
|
+
|
|
69
|
+
// Ensure the configuration list is present and its settings are in sync.
|
|
70
|
+
const xCConfigurationList = ensureXCConfigurationList(
|
|
71
|
+
xcodeProject,
|
|
72
|
+
{
|
|
73
|
+
targetName,
|
|
74
|
+
bundleIdentifier,
|
|
75
|
+
deploymentTarget,
|
|
76
|
+
version,
|
|
77
|
+
buildNumber,
|
|
78
|
+
mainAppSettings,
|
|
79
|
+
},
|
|
80
|
+
target.buildConfigurationList
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
// Ensure the product file (.appex) exists.
|
|
84
|
+
const productFile = ensureProductFile(xcodeProject, {
|
|
85
|
+
targetName,
|
|
86
|
+
groupName,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Point the target at the reconciled configuration list and product file.
|
|
90
|
+
target.productReference = productFile.fileRef
|
|
91
|
+
target.buildConfigurationList = xCConfigurationList.uuid
|
|
92
|
+
target.productType = `"com.apple.product-type.app-extension"`
|
|
93
|
+
target.name = targetName
|
|
94
|
+
target.productName = targetName
|
|
95
|
+
if (!target.buildPhases) {
|
|
96
|
+
target.buildPhases = []
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Ensure the group first so the widget's file references exist before the build phases
|
|
100
|
+
// reference them (the phases resolve files through the widget-scoped group).
|
|
101
|
+
ensurePbxGroup(xcodeProject, {
|
|
102
|
+
targetName,
|
|
103
|
+
widgetFiles: effectiveWidgetFiles,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
// Ensure build phases and their files.
|
|
107
|
+
ensureBuildPhases(xcodeProject, {
|
|
108
|
+
targetUuid,
|
|
109
|
+
targetName,
|
|
110
|
+
groupName,
|
|
111
|
+
productFile,
|
|
112
|
+
widgetFiles: effectiveWidgetFiles,
|
|
113
|
+
mainTargetUuid: xcodeProject.getFirstTarget().uuid,
|
|
114
|
+
// The app-side lifecycle service always compiles against the generated catalog.
|
|
115
|
+
// An empty catalog keeps legacy-only apps source-compatible.
|
|
116
|
+
mainSwiftFiles: ['VoltraDynamicLiveActivityTypes.swift'],
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
if (hasClientRenderedWidgets || (props.liveActivities?.length ?? 0) > 0) {
|
|
120
|
+
ensureWidgetBundleScriptPhase(xcodeProject, targetUuid)
|
|
121
|
+
}
|
|
122
|
+
if ((props.liveActivities?.length ?? 0) > 0) {
|
|
123
|
+
// Local Dynamic Live Activity starts preflight the baked definition from
|
|
124
|
+
// the app process, while WidgetKit renders from the extension process.
|
|
125
|
+
// Bake the same manifest into both products.
|
|
126
|
+
ensureWidgetBundleScriptPhase(xcodeProject, mainTargetUuid, 'live-activities')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
ensureTargetAttributes(xcodeProject, targetUuid)
|
|
130
|
+
ensureTargetDependency(xcodeProject, targetUuid)
|
|
19
131
|
}
|
|
20
132
|
|
|
21
133
|
/**
|
|
@@ -28,10 +140,12 @@ export interface ConfigureXcodeProjectProps {
|
|
|
28
140
|
* - Adds build phases (Sources, CopyFiles, Frameworks, Resources)
|
|
29
141
|
* - Adds PBXGroup for widget files
|
|
30
142
|
*
|
|
31
|
-
* This should run after generateWidgetExtensionFiles so the files exist.
|
|
143
|
+
* This should run after generateWidgetExtensionFiles so the files exist. The wrapper is kept thin:
|
|
144
|
+
* it discovers widget files and detects client-rendered widgets, then delegates the actual pbxproj
|
|
145
|
+
* mutation to {@link applyXcodeChanges}.
|
|
32
146
|
*/
|
|
33
147
|
export const configureXcodeProject: ConfigPlugin<ConfigureXcodeProjectProps> = (config, props) => {
|
|
34
|
-
const { targetName,
|
|
148
|
+
const { targetName, widgets, liveActivities } = props
|
|
35
149
|
|
|
36
150
|
return withXcodeProject(config, (config) => {
|
|
37
151
|
if (config.modRequest.introspect) {
|
|
@@ -39,7 +153,6 @@ export const configureXcodeProject: ConfigPlugin<ConfigureXcodeProjectProps> = (
|
|
|
39
153
|
}
|
|
40
154
|
|
|
41
155
|
const xcodeProject = config.modResults
|
|
42
|
-
const groupName = 'Embed Foundation Extensions'
|
|
43
156
|
|
|
44
157
|
// The release widget-bundling phase is only needed when a widget is a Dynamic Widget (server
|
|
45
158
|
// widgets carry no JS bundle). Detect once so both the create and update paths agree.
|
|
@@ -47,119 +160,11 @@ export const configureXcodeProject: ConfigPlugin<ConfigureXcodeProjectProps> = (
|
|
|
47
160
|
!!widgets &&
|
|
48
161
|
detectClientRenderedWidgets(widgets, config.modRequest.projectRoot).some((widget) => widget.clientRendered)
|
|
49
162
|
|
|
50
|
-
// Check if target already exists
|
|
51
|
-
const nativeTargets = xcodeProject.pbxNativeTargetSection()
|
|
52
|
-
const existingTargetKey = xcodeProject.findTargetKey(targetName)
|
|
53
|
-
const existingTarget = existingTargetKey ? nativeTargets[existingTargetKey] : null
|
|
54
|
-
|
|
55
163
|
const { platformProjectRoot } = config.modRequest
|
|
56
164
|
const targetPath = path.join(platformProjectRoot, targetName)
|
|
57
165
|
const widgetFiles = getIOSWidgetExtensionFiles(targetPath, targetName)
|
|
58
166
|
|
|
59
|
-
|
|
60
|
-
const mainAppSettings = getMainAppTargetSettings(xcodeProject)
|
|
61
|
-
|
|
62
|
-
// Use the deploymentTarget from plugin config (or default), ignore main app's deployment target
|
|
63
|
-
// This allows the widget extension to have its own deployment target independent of the main app
|
|
64
|
-
|
|
65
|
-
if (existingTarget && existingTargetKey) {
|
|
66
|
-
// Ensure configuration list is up to date
|
|
67
|
-
const xCConfigurationList = ensureXCConfigurationList(
|
|
68
|
-
xcodeProject,
|
|
69
|
-
{
|
|
70
|
-
targetName,
|
|
71
|
-
bundleIdentifier,
|
|
72
|
-
deploymentTarget,
|
|
73
|
-
codeSignStyle: mainAppSettings?.codeSignStyle,
|
|
74
|
-
developmentTeam: mainAppSettings?.developmentTeam,
|
|
75
|
-
provisioningProfileSpecifier: mainAppSettings?.provisioningProfileSpecifier,
|
|
76
|
-
},
|
|
77
|
-
existingTarget.buildConfigurationList
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
// Ensure product file exists
|
|
81
|
-
const productFile = ensureProductFile(xcodeProject, {
|
|
82
|
-
targetName,
|
|
83
|
-
groupName,
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
// Update target references
|
|
87
|
-
existingTarget.productReference = productFile.fileRef
|
|
88
|
-
existingTarget.buildConfigurationList = xCConfigurationList.uuid
|
|
89
|
-
existingTarget.productType = `"com.apple.product-type.app-extension"`
|
|
90
|
-
existingTarget.name = targetName
|
|
91
|
-
existingTarget.productName = targetName
|
|
92
|
-
if (!existingTarget.buildPhases) {
|
|
93
|
-
existingTarget.buildPhases = []
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Ensure build phases and groups
|
|
97
|
-
ensureBuildPhases(xcodeProject, {
|
|
98
|
-
targetUuid: existingTargetKey,
|
|
99
|
-
groupName,
|
|
100
|
-
productFile,
|
|
101
|
-
widgetFiles,
|
|
102
|
-
mainTargetUuid: xcodeProject.getFirstTarget().uuid,
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
if (hasClientRenderedWidgets) {
|
|
106
|
-
ensureWidgetBundleScriptPhase(xcodeProject, existingTargetKey)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
ensurePbxGroup(xcodeProject, {
|
|
110
|
-
targetName,
|
|
111
|
-
widgetFiles,
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
ensureTargetAttributes(xcodeProject, existingTargetKey)
|
|
115
|
-
ensureTargetDependency(xcodeProject, existingTargetKey)
|
|
116
|
-
|
|
117
|
-
return config
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Add configuration list
|
|
121
|
-
const targetUuid = xcodeProject.generateUuid()
|
|
122
|
-
|
|
123
|
-
const xCConfigurationList = addXCConfigurationList(xcodeProject, {
|
|
124
|
-
targetName,
|
|
125
|
-
bundleIdentifier,
|
|
126
|
-
deploymentTarget,
|
|
127
|
-
codeSignStyle: mainAppSettings?.codeSignStyle,
|
|
128
|
-
developmentTeam: mainAppSettings?.developmentTeam,
|
|
129
|
-
provisioningProfileSpecifier: mainAppSettings?.provisioningProfileSpecifier,
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
// Add product file
|
|
133
|
-
const productFile = addProductFile(xcodeProject, {
|
|
134
|
-
targetName,
|
|
135
|
-
groupName,
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
// Configure target (native target, project section, dependency)
|
|
139
|
-
configureTarget(xcodeProject, {
|
|
140
|
-
targetName,
|
|
141
|
-
targetUuid,
|
|
142
|
-
productFile,
|
|
143
|
-
xCConfigurationList,
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
// Add build phases
|
|
147
|
-
addBuildPhases(xcodeProject, {
|
|
148
|
-
targetUuid,
|
|
149
|
-
groupName,
|
|
150
|
-
productFile,
|
|
151
|
-
widgetFiles,
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
if (hasClientRenderedWidgets) {
|
|
155
|
-
ensureWidgetBundleScriptPhase(xcodeProject, targetUuid)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Add PBX group
|
|
159
|
-
addPbxGroup(xcodeProject, {
|
|
160
|
-
targetName,
|
|
161
|
-
widgetFiles,
|
|
162
|
-
})
|
|
167
|
+
applyXcodeChanges(xcodeProject, props, widgetFiles, hasClientRenderedWidgets || (liveActivities?.length ?? 0) > 0)
|
|
163
168
|
|
|
164
169
|
return config
|
|
165
170
|
})
|