@use-voltra/ios-client 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/Voltra.podspec +1 -0
  2. package/build/commonjs/events.js +23 -0
  3. package/build/commonjs/events.js.map +1 -1
  4. package/build/commonjs/index.js +59 -0
  5. package/build/commonjs/index.js.map +1 -1
  6. package/build/commonjs/live-activity/api.js +3 -1
  7. package/build/commonjs/live-activity/api.js.map +1 -1
  8. package/build/commonjs/live-activity/dynamic-api.js +173 -0
  9. package/build/commonjs/live-activity/dynamic-api.js.map +1 -0
  10. package/build/commonjs/native/NativeVoltra.js.map +1 -1
  11. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js +47 -0
  12. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  13. package/build/commonjs/utils/enableWidgetHotReload.js +8 -11
  14. package/build/commonjs/utils/enableWidgetHotReload.js.map +1 -1
  15. package/build/commonjs/utils/useUpdateOnHMR.js +3 -7
  16. package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -1
  17. package/build/commonjs/widgets/server-credentials.js +9 -0
  18. package/build/commonjs/widgets/server-credentials.js.map +1 -1
  19. package/build/commonjs/widgets/server-update.js +78 -0
  20. package/build/commonjs/widgets/server-update.js.map +1 -0
  21. package/build/module/events.js +23 -0
  22. package/build/module/events.js.map +1 -1
  23. package/build/module/index.js +3 -0
  24. package/build/module/index.js.map +1 -1
  25. package/build/module/live-activity/api.js +2 -2
  26. package/build/module/live-activity/api.js.map +1 -1
  27. package/build/module/live-activity/dynamic-api.js +167 -0
  28. package/build/module/live-activity/dynamic-api.js.map +1 -0
  29. package/build/module/native/NativeVoltra.js.map +1 -1
  30. package/build/module/utils/enableDynamicLiveActivityHotReload.js +43 -0
  31. package/build/module/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  32. package/build/module/utils/enableWidgetHotReload.js +9 -11
  33. package/build/module/utils/enableWidgetHotReload.js.map +1 -1
  34. package/build/module/utils/useUpdateOnHMR.js +3 -7
  35. package/build/module/utils/useUpdateOnHMR.js.map +1 -1
  36. package/build/module/widgets/server-credentials.js +9 -0
  37. package/build/module/widgets/server-credentials.js.map +1 -1
  38. package/build/module/widgets/server-update.js +72 -0
  39. package/build/module/widgets/server-update.js.map +1 -0
  40. package/build/typescript/commonjs/events.d.ts +7 -0
  41. package/build/typescript/commonjs/events.d.ts.map +1 -1
  42. package/build/typescript/commonjs/index.d.ts +3 -0
  43. package/build/typescript/commonjs/index.d.ts.map +1 -1
  44. package/build/typescript/commonjs/live-activity/api.d.ts +7 -0
  45. package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -1
  46. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts +54 -0
  47. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts.map +1 -0
  48. package/build/typescript/commonjs/native/NativeVoltra.d.ts +20 -0
  49. package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -1
  50. package/build/typescript/commonjs/types.d.ts +1 -1
  51. package/build/typescript/commonjs/types.d.ts.map +1 -1
  52. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  53. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  54. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts +5 -7
  55. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts.map +1 -1
  56. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts +0 -3
  57. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -1
  58. package/build/typescript/commonjs/widgets/server-credentials.d.ts +8 -0
  59. package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -1
  60. package/build/typescript/commonjs/widgets/server-update.d.ts +64 -0
  61. package/build/typescript/commonjs/widgets/server-update.d.ts.map +1 -0
  62. package/build/typescript/module/events.d.ts +7 -0
  63. package/build/typescript/module/events.d.ts.map +1 -1
  64. package/build/typescript/module/index.d.ts +3 -0
  65. package/build/typescript/module/index.d.ts.map +1 -1
  66. package/build/typescript/module/live-activity/api.d.ts +7 -0
  67. package/build/typescript/module/live-activity/api.d.ts.map +1 -1
  68. package/build/typescript/module/live-activity/dynamic-api.d.ts +54 -0
  69. package/build/typescript/module/live-activity/dynamic-api.d.ts.map +1 -0
  70. package/build/typescript/module/native/NativeVoltra.d.ts +20 -0
  71. package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -1
  72. package/build/typescript/module/types.d.ts +1 -1
  73. package/build/typescript/module/types.d.ts.map +1 -1
  74. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  75. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  76. package/build/typescript/module/utils/enableWidgetHotReload.d.ts +5 -7
  77. package/build/typescript/module/utils/enableWidgetHotReload.d.ts.map +1 -1
  78. package/build/typescript/module/utils/useUpdateOnHMR.d.ts +0 -3
  79. package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -1
  80. package/build/typescript/module/widgets/server-credentials.d.ts +8 -0
  81. package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -1
  82. package/build/typescript/module/widgets/server-update.d.ts +64 -0
  83. package/build/typescript/module/widgets/server-update.d.ts.map +1 -0
  84. package/expo-plugin/build/cjs/constants.js +20 -1
  85. package/expo-plugin/build/cjs/constants.js.map +1 -1
  86. package/expo-plugin/build/cjs/index.js +6 -0
  87. package/expo-plugin/build/cjs/index.js.map +1 -1
  88. package/expo-plugin/build/cjs/ios/index.js +1 -0
  89. package/expo-plugin/build/cjs/ios/index.js.map +1 -1
  90. package/expo-plugin/build/cjs/ios/infoPlist.js +28 -5
  91. package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -1
  92. package/expo-plugin/build/cjs/ios/serverUpdate.js +25 -0
  93. package/expo-plugin/build/cjs/ios/serverUpdate.js.map +1 -0
  94. package/expo-plugin/build/cjs/ios-widget/clientRendered.js +4 -4
  95. package/expo-plugin/build/cjs/ios-widget/clientRendered.js.map +1 -1
  96. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js +5 -5
  97. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js.map +1 -1
  98. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js +130 -0
  99. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  100. package/expo-plugin/build/cjs/ios-widget/files/index.js +9 -2
  101. package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -1
  102. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +6 -3
  103. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -1
  104. package/expo-plugin/build/cjs/ios-widget/files/manifest.js +24 -0
  105. package/expo-plugin/build/cjs/ios-widget/files/manifest.js.map +1 -1
  106. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js +7 -0
  107. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js.map +1 -0
  108. package/expo-plugin/build/cjs/ios-widget/files/swift.js +56 -26
  109. package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -1
  110. package/expo-plugin/build/cjs/ios-widget/index.js +9 -3
  111. package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -1
  112. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +34 -22
  113. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -1
  114. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +51 -11
  115. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -1
  116. package/expo-plugin/build/cjs/ios-widget/xcode/index.js +21 -5
  117. package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -1
  118. package/expo-plugin/build/cjs/utils/urlScheme.js +36 -14
  119. package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -1
  120. package/expo-plugin/build/cjs/validation.js +54 -0
  121. package/expo-plugin/build/cjs/validation.js.map +1 -1
  122. package/expo-plugin/build/esm/constants.js +17 -0
  123. package/expo-plugin/build/esm/constants.js.map +1 -1
  124. package/expo-plugin/build/esm/index.js +6 -0
  125. package/expo-plugin/build/esm/index.js.map +1 -1
  126. package/expo-plugin/build/esm/ios/index.js +1 -0
  127. package/expo-plugin/build/esm/ios/index.js.map +1 -1
  128. package/expo-plugin/build/esm/ios/infoPlist.js +28 -5
  129. package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -1
  130. package/expo-plugin/build/esm/ios/serverUpdate.js +21 -0
  131. package/expo-plugin/build/esm/ios/serverUpdate.js.map +1 -0
  132. package/expo-plugin/build/esm/ios-widget/clientRendered.js +5 -5
  133. package/expo-plugin/build/esm/ios-widget/clientRendered.js.map +1 -1
  134. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js +6 -6
  135. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js.map +1 -1
  136. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js +122 -0
  137. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  138. package/expo-plugin/build/esm/ios-widget/files/index.js +10 -3
  139. package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -1
  140. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +6 -3
  141. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -1
  142. package/expo-plugin/build/esm/ios-widget/files/manifest.js +23 -1
  143. package/expo-plugin/build/esm/ios-widget/files/manifest.js.map +1 -1
  144. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js +4 -0
  145. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js.map +1 -0
  146. package/expo-plugin/build/esm/ios-widget/files/swift.js +50 -20
  147. package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -1
  148. package/expo-plugin/build/esm/ios-widget/index.js +9 -3
  149. package/expo-plugin/build/esm/ios-widget/index.js.map +1 -1
  150. package/expo-plugin/build/esm/ios-widget/widgetPlist.js +34 -22
  151. package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -1
  152. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +51 -11
  153. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -1
  154. package/expo-plugin/build/esm/ios-widget/xcode/index.js +21 -5
  155. package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -1
  156. package/expo-plugin/build/esm/utils/urlScheme.js +34 -14
  157. package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -1
  158. package/expo-plugin/build/esm/validation.js +54 -1
  159. package/expo-plugin/build/esm/validation.js.map +1 -1
  160. package/expo-plugin/build/types/constants.d.ts +10 -1
  161. package/expo-plugin/build/types/constants.d.ts.map +1 -1
  162. package/expo-plugin/build/types/index.d.ts +1 -1
  163. package/expo-plugin/build/types/index.d.ts.map +1 -1
  164. package/expo-plugin/build/types/ios/index.d.ts +2 -0
  165. package/expo-plugin/build/types/ios/index.d.ts.map +1 -1
  166. package/expo-plugin/build/types/ios/infoPlist.d.ts +2 -0
  167. package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -1
  168. package/expo-plugin/build/types/ios/serverUpdate.d.ts +11 -0
  169. package/expo-plugin/build/types/ios/serverUpdate.d.ts.map +1 -0
  170. package/expo-plugin/build/types/ios-widget/clientRendered.d.ts.map +1 -1
  171. package/expo-plugin/build/types/ios-widget/clientRenderedPrerender.d.ts.map +1 -1
  172. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts +7 -0
  173. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts.map +1 -0
  174. package/expo-plugin/build/types/ios-widget/files/index.d.ts +3 -1
  175. package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -1
  176. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +2 -1
  177. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -1
  178. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts +9 -2
  179. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts.map +1 -1
  180. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts +2 -0
  181. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts.map +1 -0
  182. package/expo-plugin/build/types/ios-widget/files/swift.d.ts +6 -2
  183. package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -1
  184. package/expo-plugin/build/types/ios-widget/index.d.ts +3 -1
  185. package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -1
  186. package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -1
  187. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +3 -1
  188. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -1
  189. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +2 -1
  190. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -1
  191. package/expo-plugin/build/types/types.d.ts +23 -4
  192. package/expo-plugin/build/types/types.d.ts.map +1 -1
  193. package/expo-plugin/build/types/utils/urlScheme.d.ts +16 -0
  194. package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -1
  195. package/expo-plugin/build/types/validation.d.ts +2 -1
  196. package/expo-plugin/build/types/validation.d.ts.map +1 -1
  197. package/expo-plugin/src/constants.ts +24 -1
  198. package/expo-plugin/src/index.ts +9 -0
  199. package/expo-plugin/src/ios/index.ts +3 -0
  200. package/expo-plugin/src/ios/infoPlist.ts +33 -5
  201. package/expo-plugin/src/ios/serverUpdate.ts +29 -0
  202. package/expo-plugin/src/ios-widget/clientRendered.ts +9 -5
  203. package/expo-plugin/src/ios-widget/clientRenderedPrerender.ts +11 -6
  204. package/expo-plugin/src/ios-widget/dynamic-live-activity/swift.ts +138 -0
  205. package/expo-plugin/src/ios-widget/files/index.ts +15 -4
  206. package/expo-plugin/src/ios-widget/files/infoPlist.ts +17 -3
  207. package/expo-plugin/src/ios-widget/files/manifest.ts +42 -2
  208. package/expo-plugin/src/ios-widget/files/swift-utils.ts +3 -0
  209. package/expo-plugin/src/ios-widget/files/swift.ts +69 -22
  210. package/expo-plugin/src/ios-widget/index.ts +13 -3
  211. package/expo-plugin/src/ios-widget/widgetPlist.ts +37 -23
  212. package/expo-plugin/src/ios-widget/xcode/__snapshots__/applyXcodeChanges.node.test.ts.snap +34 -28
  213. package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +59 -12
  214. package/expo-plugin/src/ios-widget/xcode/index.ts +23 -6
  215. package/expo-plugin/src/types.ts +28 -4
  216. package/expo-plugin/src/utils/urlScheme.ts +47 -17
  217. package/expo-plugin/src/validation.ts +76 -1
  218. package/ios/Package.swift +32 -3
  219. package/ios/VoltraWidget.podspec +1 -0
  220. package/ios/app/NativeVoltra.mm +107 -7
  221. package/ios/app/VoltraLiveActivityManager.swift +30 -0
  222. package/ios/app/VoltraLiveActivityService.swift +77 -5
  223. package/ios/app/VoltraModule.swift +99 -1
  224. package/ios/app/VoltraModuleImpl.swift +100 -2
  225. package/ios/app/VoltraViewComponentView.mm +3 -3
  226. package/ios/app/VoltraWidgetService.swift +147 -12
  227. package/ios/app/dynamic-live-activity/VoltraDynamicLiveActivityService.swift +97 -0
  228. package/ios/app/dynamic-live-activity/VoltraLiveActivityChronology.swift +68 -0
  229. package/ios/shared/DynamicWidgetPropsStore.swift +73 -6
  230. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerFetchResolver.swift +34 -0
  231. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerProps.swift +55 -0
  232. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerPropsStore.swift +146 -0
  233. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerUpdateRunner.swift +193 -0
  234. package/ios/shared/ServerWidgetContentResolver.swift +60 -0
  235. package/ios/shared/ServerWidgetResponseStore.swift +25 -0
  236. package/ios/shared/ShortNames.swift +6 -0
  237. package/ios/shared/VoltraConfig.swift +41 -0
  238. package/ios/shared/VoltraConstants.swift +15 -0
  239. package/ios/shared/VoltraElement.swift +127 -43
  240. package/ios/shared/VoltraEventBus.swift +52 -7
  241. package/ios/shared/VoltraJSRenderer.swift +90 -22
  242. package/ios/shared/VoltraNode.swift +1 -109
  243. package/ios/shared/VoltraRefreshIntent.swift +1 -1
  244. package/ios/shared/VoltraWidgetKind.swift +41 -0
  245. package/ios/shared/VoltraWidgetServerFetcher.swift +52 -107
  246. package/ios/shared/WidgetServer/VoltraWidgetAppearance.swift +17 -0
  247. package/ios/shared/WidgetServer/VoltraWidgetServer.swift +138 -0
  248. package/ios/shared/WidgetServer/WidgetCanonicalConfiguration.swift +77 -0
  249. package/ios/shared/WidgetServer/WidgetScope.swift +55 -0
  250. package/ios/shared/WidgetServer/WidgetServerEtagStore.swift +55 -0
  251. package/ios/shared/WidgetServer/WidgetServerFetcher.swift +179 -0
  252. package/ios/shared/WidgetServer/WidgetServerRequestBuilder.swift +114 -0
  253. package/ios/shared/WidgetServer/WidgetServerSettingsCodec.swift +47 -0
  254. package/ios/shared/WidgetServer/WidgetServerSettingsResolver.swift +129 -0
  255. package/ios/shared/WidgetServer/WidgetServerSettingsStore.swift +170 -0
  256. package/ios/shared/WidgetServer/WidgetServerSettingsValidator.swift +73 -0
  257. package/ios/shared/WidgetServer/WidgetServerUpdateSettings.swift +123 -0
  258. package/ios/shared/WidgetServer/WidgetServerUpdateSettingsJson.swift +115 -0
  259. package/ios/shared/dynamic-live-activity/DynamicLiveActivityPropsCodec.swift +13 -0
  260. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityBundleSource.swift +156 -0
  261. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityObserver.swift +97 -0
  262. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityOperations.swift +105 -0
  263. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityPayloadValidator.swift +55 -0
  264. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRegistry.swift +143 -0
  265. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureQueue.swift +158 -0
  266. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureReporter.swift +120 -0
  267. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderer.swift +370 -0
  268. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityTypes.swift +87 -0
  269. package/ios/shared/dynamic-live-activity/VoltraLiveActivityOrder.swift +19 -0
  270. package/ios/target/VoltraClientWidgetRuntime.swift +44 -6
  271. package/ios/target/VoltraDynamicWidgetServerUpdateProvider.swift +204 -0
  272. package/ios/target/VoltraHomeWidget.swift +85 -90
  273. package/ios/ui/Extensions/VoltraNode+View.swift +113 -0
  274. package/ios/ui/Generated/Parameters/ChartParameters.swift +3 -0
  275. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +2 -2
  276. package/ios/ui/Views/VoltraChart.swift +108 -0
  277. package/package.json +4 -4
  278. package/src/events.ts +34 -0
  279. package/src/index.ts +22 -0
  280. package/src/live-activity/api.ts +2 -2
  281. package/src/live-activity/dynamic-api.ts +240 -0
  282. package/src/native/NativeVoltra.ts +21 -0
  283. package/src/types.ts +4 -0
  284. package/src/utils/enableDynamicLiveActivityHotReload.ts +50 -0
  285. package/src/utils/enableWidgetHotReload.ts +9 -16
  286. package/src/utils/useUpdateOnHMR.ts +3 -12
  287. package/src/widgets/server-credentials.ts +8 -0
  288. package/src/widgets/server-update.ts +84 -0
  289. /package/ios/shared/{VoltraKeychainHelper.swift → WidgetServer/VoltraKeychainHelper.swift} +0 -0
@@ -1,12 +1,25 @@
1
1
  #import "NativeVoltra.h"
2
2
  #import <UIKit/UIKit.h>
3
3
 
4
- #if __has_include("Voltra/Voltra-Swift.h")
5
- #import "Voltra/Voltra-Swift.h"
4
+ #if __has_include("Voltra/VoltraRuntime-Swift.h")
5
+ #import "Voltra/VoltraRuntime-Swift.h"
6
6
  #else
7
- #import "Voltra-Swift.h"
7
+ #import "VoltraRuntime-Swift.h"
8
8
  #endif
9
9
 
10
+ static NSString *VoltraPromiseErrorCode(NSString *fallbackCode, NSError *error)
11
+ {
12
+ if ([error.domain isEqualToString:@"com.callstack.voltra"] && error.code == 4) {
13
+ return @"VOLTRA_RENDERER_MISMATCH";
14
+ }
15
+ return fallbackCode;
16
+ }
17
+
18
+ static void VoltraRejectPromise(RCTPromiseRejectBlock reject, NSString *fallbackCode, NSError *error)
19
+ {
20
+ reject(VoltraPromiseErrorCode(fallbackCode, error), error.localizedDescription, error);
21
+ }
22
+
10
23
  @interface VoltraLaunchObserver : NSObject
11
24
  @end
12
25
 
@@ -65,6 +78,8 @@
65
78
 
66
79
  if ([eventName isEqualToString:@"interaction"]) {
67
80
  [strongSelf emitOnInteraction:eventData];
81
+ } else if ([eventName isEqualToString:@"dynamicLiveActivityRenderFailed"]) {
82
+ [strongSelf emitOnDynamicLiveActivityRenderFailed:eventData];
68
83
  } else if ([eventName isEqualToString:@"stateChange"]) {
69
84
  [strongSelf emitOnStateChanged:eventData];
70
85
  } else if ([eventName isEqualToString:@"activityTokenReceived"]) {
@@ -86,9 +101,20 @@
86
101
  - (void)applicationWillEnterForeground
87
102
  {
88
103
  [self.module clearHeadless];
104
+ [self.module drainDynamicLiveActivityRenderFailures];
89
105
  [self updateRootAppPropertiesHeadless:NO];
90
106
  }
91
107
 
108
+ - (void)drainDynamicLiveActivityRenderFailures
109
+ {
110
+ [self.module drainDynamicLiveActivityRenderFailures];
111
+ }
112
+
113
+ - (void)setDynamicLiveActivityRenderFailureListenerActive:(BOOL)active
114
+ {
115
+ [self.module setDynamicLiveActivityRenderFailureListenerActive:active];
116
+ }
117
+
92
118
  - (UIView *)reactRootViewInView:(UIView *)view
93
119
  {
94
120
  if ([view respondsToSelector:NSSelectorFromString(@"appProperties")] &&
@@ -193,7 +219,7 @@
193
219
  if (auto v = options.staleDate()) opts.staleDate = @(v.value());
194
220
  if (auto v = options.relevanceScore()) opts.relevanceScore = @(v.value());
195
221
  [self.module startLiveActivity:jsonString options:opts completion:^(NSString *activityId, NSError *error) {
196
- if (error) { reject(@"startLiveActivity", error.localizedDescription, error); } else { resolve(activityId); }
222
+ if (error) { VoltraRejectPromise(reject, @"startLiveActivity", error); } else { resolve(activityId); }
197
223
  }];
198
224
  }
199
225
 
@@ -207,7 +233,38 @@
207
233
  if (auto v = options.staleDate()) opts.staleDate = @(v.value());
208
234
  if (auto v = options.relevanceScore()) opts.relevanceScore = @(v.value());
209
235
  [self.module updateLiveActivity:activityId jsonString:jsonString options:opts completion:^(NSError *error) {
210
- if (error) { reject(@"updateLiveActivity", error.localizedDescription, error); } else { resolve(nil); }
236
+ if (error) { VoltraRejectPromise(reject, @"updateLiveActivity", error); } else { resolve(nil); }
237
+ }];
238
+ }
239
+
240
+ - (void)startDynamicLiveActivity:(NSString *)definitionId
241
+ propsJson:(NSString *)propsJson
242
+ options:(JS::NativeVoltra::StartVoltraOptions &)options
243
+ resolve:(RCTPromiseResolveBlock)resolve
244
+ reject:(RCTPromiseRejectBlock)reject
245
+ {
246
+ StartVoltraOptions *opts = [StartVoltraOptions new];
247
+ opts.activityName = options.activityName();
248
+ opts.deepLinkUrl = options.deepLinkUrl();
249
+ opts.channelId = options.channelId();
250
+ if (auto v = options.staleDate()) opts.staleDate = @(v.value());
251
+ if (auto v = options.relevanceScore()) opts.relevanceScore = @(v.value());
252
+ [self.module startDynamicLiveActivity:definitionId propsJson:propsJson options:opts completion:^(NSString *activityId, NSError *error) {
253
+ if (error) { VoltraRejectPromise(reject, @"startDynamicLiveActivity", error); } else { resolve(activityId); }
254
+ }];
255
+ }
256
+
257
+ - (void)updateDynamicLiveActivity:(NSString *)activityId
258
+ propsJson:(NSString *)propsJson
259
+ options:(JS::NativeVoltra::UpdateVoltraOptions &)options
260
+ resolve:(RCTPromiseResolveBlock)resolve
261
+ reject:(RCTPromiseRejectBlock)reject
262
+ {
263
+ UpdateVoltraOptions *opts = [UpdateVoltraOptions new];
264
+ if (auto v = options.staleDate()) opts.staleDate = @(v.value());
265
+ if (auto v = options.relevanceScore()) opts.relevanceScore = @(v.value());
266
+ [self.module updateDynamicLiveActivity:activityId propsJson:propsJson options:opts completion:^(NSError *error) {
267
+ if (error) { VoltraRejectPromise(reject, @"updateDynamicLiveActivity", error); } else { resolve(nil); }
211
268
  }];
212
269
  }
213
270
 
@@ -224,14 +281,14 @@
224
281
  opts.dismissalPolicy = policy;
225
282
  }
226
283
  [self.module endLiveActivity:activityId options:opts completion:^(NSError *error) {
227
- if (error) { reject(@"endLiveActivity", error.localizedDescription, error); } else { resolve(nil); }
284
+ if (error) { VoltraRejectPromise(reject, @"endLiveActivity", error); } else { resolve(nil); }
228
285
  }];
229
286
  }
230
287
 
231
288
  - (void)endAllLiveActivities:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
232
289
  {
233
290
  [self.module endAllLiveActivities:^(NSError *error) {
234
- if (error) { reject(@"endAllLiveActivities", error.localizedDescription, error); } else { resolve(nil); }
291
+ if (error) { VoltraRejectPromise(reject, @"endAllLiveActivities", error); } else { resolve(nil); }
235
292
  }];
236
293
  }
237
294
 
@@ -245,6 +302,11 @@
245
302
  resolve([self.module listVoltraActivityIds]);
246
303
  }
247
304
 
305
+ - (void)getDynamicLiveActivityDefinitionIds:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
306
+ {
307
+ resolve([self.module getDynamicLiveActivityDefinitionIds]);
308
+ }
309
+
248
310
  - (NSNumber *)isLiveActivityActive:(NSString *)activityName
249
311
  {
250
312
  return @([self.module isLiveActivityActive:activityName]);
@@ -271,6 +333,11 @@
271
333
  }];
272
334
  }
273
335
 
336
+ - (void)reloadDynamicLiveActivities:(NSArray *)definitionIds resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
337
+ {
338
+ [self.module reloadDynamicLiveActivities:definitionIds completion:^{ resolve(nil); }];
339
+ }
340
+
274
341
  - (void)clearPreloadedImages:(NSArray *)keys resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
275
342
  {
276
343
  [self.module clearPreloadedImages:keys completion:^{ resolve(nil); }];
@@ -340,6 +407,39 @@
340
407
  }];
341
408
  }
342
409
 
410
+ - (void)setWidgetServerUpdate:(NSString *)settingsJson
411
+ widgetId:(NSString *)widgetId
412
+ resolve:(RCTPromiseResolveBlock)resolve
413
+ reject:(RCTPromiseRejectBlock)reject
414
+ {
415
+ NSString *error = [self.module setWidgetServerUpdate:settingsJson widgetId:widgetId];
416
+ if (error) {
417
+ reject(@"VOLTRA_INVALID_SERVER_UPDATE_SETTINGS", error, nil);
418
+ } else {
419
+ resolve(nil);
420
+ }
421
+ }
422
+
423
+ - (void)clearWidgetServerUpdate:(NSString *)widgetId
424
+ resolve:(RCTPromiseResolveBlock)resolve
425
+ reject:(RCTPromiseRejectBlock)reject
426
+ {
427
+ NSString *error = [self.module clearWidgetServerUpdate:widgetId];
428
+ if (error) {
429
+ reject(@"VOLTRA_INVALID_SERVER_UPDATE_SETTINGS", error, nil);
430
+ } else {
431
+ resolve(nil);
432
+ }
433
+ }
434
+
435
+ - (void)getWidgetServerUpdate:(NSString *)widgetId
436
+ resolve:(RCTPromiseResolveBlock)resolve
437
+ reject:(RCTPromiseRejectBlock)reject
438
+ {
439
+ NSString *json = [self.module getWidgetServerUpdate:widgetId];
440
+ resolve(json);
441
+ }
442
+
343
443
  - (void)setWidgetServerCredentials:(JS::NativeVoltra::WidgetServerCredentials &)credentials
344
444
  resolve:(RCTPromiseResolveBlock)resolve
345
445
  reject:(RCTPromiseRejectBlock)reject
@@ -13,6 +13,9 @@ public actor VoltraLiveActivityManager {
13
13
  // Callbacks are `let` + `@Sendable` so they are immutable after init and safe
14
14
  // to call from any concurrency context without capturing `self`.
15
15
 
16
+ /// Called when ActivityKit exposes an activity instance to this process.
17
+ private let onActivityDiscovered: (@Sendable (String) -> Void)?
18
+
16
19
  /// Called when a push token is received or rotated for a specific activity.
17
20
  /// Parameters: (activityName, hexToken)
18
21
  private let onTokenUpdated: (@Sendable (String, String) -> Void)?
@@ -30,6 +33,7 @@ public actor VoltraLiveActivityManager {
30
33
  /// Drives the main `Activity.activityUpdates` loop. When this task is cancelled,
31
34
  /// the loop exits and no new per-activity observers are created.
32
35
  private var activityUpdatesTask: Task<Void, Never>?
36
+ private var isObserving = false
33
37
 
34
38
  /// Drives the `Activity.pushToStartTokenUpdates` loop (iOS 17.2+ only).
35
39
  private var pushToStartTask: Task<Void, Never>?
@@ -42,6 +46,11 @@ public actor VoltraLiveActivityManager {
42
46
  /// One lifecycle-state observer task per live activity, keyed by `activity.id`.
43
47
  private var stateTasks: [String: Task<Void, Never>] = [:]
44
48
 
49
+ /// Generated Dynamic Live Activity types require separate ActivityKit streams.
50
+ /// This observer owns those streams while this manager continues to own the
51
+ /// unchanged legacy and app-wide push-to-start contracts.
52
+ private let dynamicObserver: VoltraDynamicLiveActivityObserver
53
+
45
54
  /// The last push-to-start token we forwarded to the callback.
46
55
  /// ActivityKit re-delivers the current token whenever a live activity starts or
47
56
  /// ends (the push-to-start eligibility state has changed), even if the token
@@ -52,13 +61,20 @@ public actor VoltraLiveActivityManager {
52
61
  // MARK: - Init
53
62
 
54
63
  public init(
64
+ onActivityDiscovered: (@Sendable (String) -> Void)? = nil,
55
65
  onTokenUpdated: (@Sendable (String, String) -> Void)? = nil,
56
66
  onPushToStartUpdated: (@Sendable (String) -> Void)? = nil,
57
67
  onStateChanged: (@Sendable (String, String) -> Void)? = nil
58
68
  ) {
69
+ self.onActivityDiscovered = onActivityDiscovered
59
70
  self.onTokenUpdated = onTokenUpdated
60
71
  self.onPushToStartUpdated = onPushToStartUpdated
61
72
  self.onStateChanged = onStateChanged
73
+ dynamicObserver = VoltraDynamicLiveActivityObserver(
74
+ onActivityDiscovered: onActivityDiscovered,
75
+ onTokenUpdated: onTokenUpdated,
76
+ onStateChanged: onStateChanged
77
+ )
62
78
  }
63
79
 
64
80
  // MARK: - Public API
@@ -69,9 +85,14 @@ public actor VoltraLiveActivityManager {
69
85
  /// To restart observation, call `stopObserving()` first.
70
86
  public func startObserving() {
71
87
  guard activityUpdatesTask == nil else { return }
88
+ isObserving = true
72
89
 
73
90
  startActivityUpdatesObservation()
74
91
  startPushToStartObservation()
92
+ Task { [weak self, dynamicObserver] in
93
+ guard await self?.currentlyObserving() == true else { return }
94
+ await VoltraDynamicLiveActivityRegistry.shared.startObserving(with: dynamicObserver)
95
+ }
75
96
  }
76
97
 
77
98
  /// Stop all observation and cancel every outstanding task.
@@ -79,6 +100,7 @@ public actor VoltraLiveActivityManager {
79
100
  /// Safe to call from any context. After this returns the actor holds no running
80
101
  /// tasks; calling `startObserving()` again creates a fresh set.
81
102
  public func stopObserving() {
103
+ isObserving = false
82
104
  activityUpdatesTask?.cancel()
83
105
  activityUpdatesTask = nil
84
106
 
@@ -88,6 +110,13 @@ public actor VoltraLiveActivityManager {
88
110
  lastPushToStartToken = nil
89
111
 
90
112
  cancelAllPerActivityTasks()
113
+ Task { [dynamicObserver] in
114
+ await dynamicObserver.stopObserving()
115
+ }
116
+ }
117
+
118
+ private func currentlyObserving() -> Bool {
119
+ isObserving
91
120
  }
92
121
 
93
122
  // MARK: - deinit
@@ -169,6 +198,7 @@ public actor VoltraLiveActivityManager {
169
198
  private func observe(_ activity: Activity<VoltraAttributes>) {
170
199
  let activityId = activity.id
171
200
  let activityName = activity.attributes.name
201
+ onActivityDiscovered?(activityId)
172
202
 
173
203
  // Token observation
174
204
  if let onTokenUpdated, tokenTasks[activityId] == nil {
@@ -78,6 +78,9 @@ public struct UpdateActivityRequest {
78
78
 
79
79
  /// Service for managing Voltra Live Activities
80
80
  public class VoltraLiveActivityService {
81
+ private let chronology = VoltraLiveActivityChronology.shared
82
+ private let dynamicService = VoltraDynamicLiveActivityService()
83
+
81
84
  // MARK: - Availability Checks
82
85
 
83
86
  /// Check if Live Activities are supported on this OS version
@@ -113,7 +116,7 @@ public class VoltraLiveActivityService {
113
116
  return Array(Activity<VoltraAttributes>.activities)
114
117
  }
115
118
 
116
- /// Get the latest (most recently created) activity across both types
119
+ /// Get the latest legacy activity.
117
120
  public func getLatestActivity() -> VoltraActivity? {
118
121
  guard Self.isSupported() else { return nil }
119
122
  let allActivities = getAllActivities()
@@ -122,7 +125,30 @@ public class VoltraLiveActivityService {
122
125
 
123
126
  /// Check if an activity with the given name exists across both types
124
127
  public func isActivityActive(name: String) -> Bool {
125
- findActivity(byName: name) != nil
128
+ findActivity(byName: name) != nil || dynamicService.isActive(name: name)
129
+ }
130
+
131
+ /// The unified list intentionally erases each engine's concrete attributes type.
132
+ public func getAllActivityReferences() -> [VoltraDynamicLiveActivityReference] {
133
+ guard Self.isSupported() else { return [] }
134
+ let legacy = getAllActivities().map {
135
+ VoltraDynamicLiveActivityReference(id: $0.id, name: $0.attributes.name, definitionId: "legacy")
136
+ }
137
+ return chronology.order(legacy + dynamicService.activityReferences())
138
+ }
139
+
140
+ public func latestActivityId() -> String? {
141
+ guard Self.isSupported() else { return nil }
142
+ let legacy = getAllActivities().map {
143
+ VoltraDynamicLiveActivityReference(id: $0.id, name: $0.attributes.name, definitionId: "legacy")
144
+ }
145
+ return chronology.latest(legacy + dynamicService.activityReferences())?.id
146
+ }
147
+
148
+ /// The installed capability list is generated during prebuild and does not
149
+ /// depend on Metro, the app group, or a server connection.
150
+ public func dynamicLiveActivityDefinitionIds() -> [String] {
151
+ dynamicService.definitionIds()
126
152
  }
127
153
 
128
154
  // MARK: - Create Operations
@@ -154,7 +180,7 @@ public class VoltraLiveActivityService {
154
180
  let initialState = try VoltraAttributes.ContentState(uiJsonData: request.jsonString)
155
181
 
156
182
  // Request the activity
157
- _ = try Activity.request(
183
+ let activity = try Activity.request(
158
184
  attributes: attributes,
159
185
  content: .init(
160
186
  state: initialState,
@@ -163,6 +189,7 @@ public class VoltraLiveActivityService {
163
189
  ),
164
190
  pushType: request.pushType
165
191
  )
192
+ chronology.record(activity.id)
166
193
 
167
194
  return finalActivityId
168
195
  }
@@ -202,6 +229,9 @@ public class VoltraLiveActivityService {
202
229
  request: UpdateActivityRequest
203
230
  ) async throws {
204
231
  guard let activity = findActivity(byName: name) else {
232
+ if dynamicService.isActive(name: name) {
233
+ throw VoltraLiveActivityError.rendererMismatch
234
+ }
205
235
  throw VoltraLiveActivityError.notFound
206
236
  }
207
237
  try await updateActivity(activity, request: request)
@@ -231,10 +261,15 @@ public class VoltraLiveActivityService {
231
261
  byName name: String,
232
262
  dismissalPolicy: ActivityUIDismissalPolicy = .immediate
233
263
  ) async throws {
234
- guard let activity = findActivity(byName: name) else {
264
+ if let activity = findActivity(byName: name) {
265
+ await endActivity(activity, dismissalPolicy: dismissalPolicy)
266
+ // Names can collide across engines after a remote start. Shared ending covers both.
267
+ _ = await dynamicService.end(byName: name, dismissalPolicy: dismissalPolicy)
268
+ return
269
+ }
270
+ guard await dynamicService.end(byName: name, dismissalPolicy: dismissalPolicy) else {
235
271
  throw VoltraLiveActivityError.notFound
236
272
  }
237
- await endActivity(activity, dismissalPolicy: dismissalPolicy)
238
273
  }
239
274
 
240
275
  /// End all activities with the same name
@@ -245,6 +280,7 @@ public class VoltraLiveActivityService {
245
280
  for activity in activities {
246
281
  await endActivity(activity)
247
282
  }
283
+ _ = await dynamicService.end(byName: name, dismissalPolicy: .immediate)
248
284
  }
249
285
 
250
286
  /// End all Voltra Live Activities
@@ -254,6 +290,38 @@ public class VoltraLiveActivityService {
254
290
  for activity in activities {
255
291
  await endActivity(activity)
256
292
  }
293
+ await dynamicService.endAll(dismissalPolicy: .immediate)
294
+ }
295
+
296
+ // MARK: - Dynamic operations
297
+
298
+ public func createDynamicActivity(_ request: VoltraDynamicLiveActivityCreateRequest) async throws -> String {
299
+ guard Self.isSupported() else { throw VoltraLiveActivityError.unsupportedOS }
300
+ guard Self.areActivitiesEnabled() else { throw VoltraLiveActivityError.liveActivitiesNotEnabled }
301
+ if request.name.isEmpty == false {
302
+ try await endActivities(byName: request.name)
303
+ }
304
+ return try await dynamicService.create(request)
305
+ }
306
+
307
+ public func updateDynamicActivity(byName name: String, request: VoltraDynamicLiveActivityUpdateRequest) async throws {
308
+ guard Self.isSupported() else { throw VoltraLiveActivityError.unsupportedOS }
309
+ if try await dynamicService.update(byName: name, request: request) {
310
+ return
311
+ }
312
+ if findActivity(byName: name) != nil {
313
+ throw VoltraDynamicLiveActivityError.rendererMismatch
314
+ }
315
+ throw VoltraLiveActivityError.notFound
316
+ }
317
+
318
+ /// Refetch and re-evaluate only invalidated Dynamic Live Activity definitions,
319
+ /// then update their active instances with their current state to trigger a
320
+ /// WidgetKit render. Legacy activities are deliberately untouched.
321
+ public func reloadDynamicActivities(definitionIds: [String]?) async {
322
+ #if DEBUG
323
+ await dynamicService.reload(definitionIds: definitionIds)
324
+ #endif
257
325
  }
258
326
 
259
327
  // MARK: - Monitoring
@@ -280,6 +348,9 @@ public class VoltraLiveActivityService {
280
348
  }
281
349
 
282
350
  let manager = VoltraLiveActivityManager(
351
+ onActivityDiscovered: { [chronology] activityId in
352
+ chronology.record(activityId)
353
+ },
283
354
  onTokenUpdated: onTokenUpdated,
284
355
  onPushToStartUpdated: onPushToStartUpdated,
285
356
  onStateChanged: { activityName, state in
@@ -305,4 +376,5 @@ public enum VoltraLiveActivityError: Error {
305
376
  case unsupportedOS
306
377
  case notFound
307
378
  case liveActivitiesNotEnabled
379
+ case rendererMismatch
308
380
  }
@@ -1,10 +1,42 @@
1
1
  import Foundation
2
2
 
3
- public enum VoltraErrors: Error {
3
+ public enum VoltraErrors: Error, CustomNSError {
4
4
  case unsupportedOS
5
5
  case notFound
6
6
  case liveActivitiesNotEnabled
7
+ case rendererMismatch
7
8
  case unexpectedError(Error)
9
+
10
+ public static let errorDomain = "com.callstack.voltra"
11
+
12
+ public var errorCode: Int {
13
+ switch self {
14
+ case .unexpectedError: 0
15
+ case .unsupportedOS: 1
16
+ case .notFound: 2
17
+ case .liveActivitiesNotEnabled: 3
18
+ case .rendererMismatch: 4
19
+ }
20
+ }
21
+
22
+ public var errorUserInfo: [String: Any] {
23
+ [NSLocalizedDescriptionKey: errorDescription]
24
+ }
25
+
26
+ private var errorDescription: String {
27
+ switch self {
28
+ case .unsupportedOS:
29
+ "Live Activities require iOS 16.4 or newer."
30
+ case .notFound:
31
+ "The requested Live Activity was not found."
32
+ case .liveActivitiesNotEnabled:
33
+ "Live Activities are disabled for this app."
34
+ case .rendererMismatch:
35
+ "The Live Activity belongs to a different renderer."
36
+ case let .unexpectedError(error):
37
+ error.localizedDescription
38
+ }
39
+ }
8
40
  }
9
41
 
10
42
  @objc public final class VoltraModule: NSObject {
@@ -59,6 +91,37 @@ public enum VoltraErrors: Error {
59
91
  }
60
92
  }
61
93
 
94
+ @objc public func startDynamicLiveActivity(
95
+ _ definitionId: String,
96
+ propsJson: String,
97
+ options: StartVoltraOptions?,
98
+ completion: @escaping (String?, Error?) -> Void
99
+ ) {
100
+ Task {
101
+ do {
102
+ try completion(await impl.startDynamicLiveActivity(definitionId: definitionId, propsJson: propsJson, options: options), nil)
103
+ } catch {
104
+ completion(nil, error)
105
+ }
106
+ }
107
+ }
108
+
109
+ @objc public func updateDynamicLiveActivity(
110
+ _ activityId: String,
111
+ propsJson: String,
112
+ options: UpdateVoltraOptions?,
113
+ completion: @escaping (Error?) -> Void
114
+ ) {
115
+ Task {
116
+ do {
117
+ try await impl.updateDynamicLiveActivity(activityId: activityId, propsJson: propsJson, options: options)
118
+ completion(nil)
119
+ } catch {
120
+ completion(error)
121
+ }
122
+ }
123
+ }
124
+
62
125
  @objc public func endLiveActivity(
63
126
  _ activityId: String,
64
127
  options: EndVoltraOptions?,
@@ -93,6 +156,10 @@ public enum VoltraErrors: Error {
93
156
  impl.listVoltraActivityIds()
94
157
  }
95
158
 
159
+ @objc public func getDynamicLiveActivityDefinitionIds() -> [String] {
160
+ impl.getDynamicLiveActivityDefinitionIds()
161
+ }
162
+
96
163
  @objc public func isLiveActivityActive(_ activityName: String) -> Bool {
97
164
  impl.isLiveActivityActive(name: activityName)
98
165
  }
@@ -105,6 +172,14 @@ public enum VoltraErrors: Error {
105
172
  impl.clearHeadless()
106
173
  }
107
174
 
175
+ @objc public func drainDynamicLiveActivityRenderFailures() {
176
+ impl.drainDynamicLiveActivityRenderFailures()
177
+ }
178
+
179
+ @objc public func setDynamicLiveActivityRenderFailureListenerActive(_ active: Bool) {
180
+ impl.setDynamicLiveActivityRenderFailureListenerActive(active)
181
+ }
182
+
108
183
  // MARK: - Images
109
184
 
110
185
  @objc public func preloadImages(
@@ -136,6 +211,13 @@ public enum VoltraErrors: Error {
136
211
  }
137
212
  }
138
213
 
214
+ @objc public func reloadDynamicLiveActivities(_ definitionIds: NSArray?, completion: @escaping () -> Void) {
215
+ Task {
216
+ await impl.reloadDynamicLiveActivities(definitionIds: definitionIds?.compactMap { $0 as? String })
217
+ completion()
218
+ }
219
+ }
220
+
139
221
  @objc public func clearPreloadedImages(_ keys: NSArray?, completion: @escaping () -> Void) {
140
222
  Task {
141
223
  await impl.clearPreloadedImages(keys: keys?.compactMap { $0 as? String })
@@ -225,6 +307,22 @@ public enum VoltraErrors: Error {
225
307
  }
226
308
  }
227
309
 
310
+ // MARK: - Widget Server Update Settings
311
+
312
+ /// - Returns: an error message when the settings were rejected, or nil when they were applied.
313
+ @objc public func setWidgetServerUpdate(_ settingsJson: String, widgetId: String?) -> NSString? {
314
+ impl.setWidgetServerUpdate(settingsJson: settingsJson, widgetId: widgetId) as NSString?
315
+ }
316
+
317
+ @objc public func clearWidgetServerUpdate(_ widgetId: String?) -> NSString? {
318
+ impl.clearWidgetServerUpdate(widgetId: widgetId) as NSString?
319
+ }
320
+
321
+ /// - Returns: settings as JSON (resolved for a `widgetId`, raw global otherwise), or nil.
322
+ @objc public func getWidgetServerUpdate(_ widgetId: String?) -> NSString? {
323
+ impl.getWidgetServerUpdate(widgetId: widgetId) as NSString?
324
+ }
325
+
228
326
  // MARK: - Widget Server Credentials
229
327
 
230
328
  @objc public func setWidgetServerCredentials(_ token: String, headers: NSDictionary?) {