voltra 1.0.1 → 1.1.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 (548) hide show
  1. package/README.md +17 -13
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  6. package/android/.gradle/8.9/gc.properties +0 -0
  7. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  8. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  9. package/android/.gradle/vcs-1/gc.properties +0 -0
  10. package/android/build.gradle +84 -0
  11. package/android/src/main/AndroidManifest.xml +15 -0
  12. package/android/src/main/java/voltra/VoltraModule.kt +296 -0
  13. package/android/src/main/java/voltra/VoltraNotificationManager.kt +157 -0
  14. package/android/src/main/java/voltra/VoltraRN.kt +206 -0
  15. package/android/src/main/java/voltra/events/VoltraEvent.kt +25 -0
  16. package/android/src/main/java/voltra/events/VoltraEventBus.kt +198 -0
  17. package/android/src/main/java/voltra/generated/ShortNames.kt +167 -0
  18. package/android/src/main/java/voltra/glance/GlanceFactory.kt +20 -0
  19. package/android/src/main/java/voltra/glance/RemoteViewsGenerator.kt +121 -0
  20. package/android/src/main/java/voltra/glance/StyleUtils.kt +126 -0
  21. package/android/src/main/java/voltra/glance/VoltraRenderContext.kt +15 -0
  22. package/android/src/main/java/voltra/glance/renderers/ButtonRenderers.kt +219 -0
  23. package/android/src/main/java/voltra/glance/renderers/ComplexRenderers.kt +189 -0
  24. package/android/src/main/java/voltra/glance/renderers/InputRenderers.kt +180 -0
  25. package/android/src/main/java/voltra/glance/renderers/LayoutRenderers.kt +259 -0
  26. package/android/src/main/java/voltra/glance/renderers/LazyListRenderers.kt +149 -0
  27. package/android/src/main/java/voltra/glance/renderers/ProgressRenderers.kt +109 -0
  28. package/android/src/main/java/voltra/glance/renderers/RenderCommon.kt +221 -0
  29. package/android/src/main/java/voltra/glance/renderers/TextAndImageRenderers.kt +114 -0
  30. package/android/src/main/java/voltra/images/VoltraImageManager.kt +123 -0
  31. package/android/src/main/java/voltra/models/VoltraPayload.kt +53 -0
  32. package/android/src/main/java/voltra/models/parameters/AndroidBoxParameters.kt +20 -0
  33. package/android/src/main/java/voltra/models/parameters/AndroidButtonParameters.kt +20 -0
  34. package/android/src/main/java/voltra/models/parameters/AndroidCheckBoxParameters.kt +24 -0
  35. package/android/src/main/java/voltra/models/parameters/AndroidCircleIconButtonParameters.kt +28 -0
  36. package/android/src/main/java/voltra/models/parameters/AndroidCircularProgressIndicatorParameters.kt +20 -0
  37. package/android/src/main/java/voltra/models/parameters/AndroidColumnParameters.kt +22 -0
  38. package/android/src/main/java/voltra/models/parameters/AndroidFilledButtonParameters.kt +30 -0
  39. package/android/src/main/java/voltra/models/parameters/AndroidImageParameters.kt +22 -0
  40. package/android/src/main/java/voltra/models/parameters/AndroidLazyColumnParameters.kt +20 -0
  41. package/android/src/main/java/voltra/models/parameters/AndroidLazyVerticalGridParameters.kt +20 -0
  42. package/android/src/main/java/voltra/models/parameters/AndroidLinearProgressIndicatorParameters.kt +22 -0
  43. package/android/src/main/java/voltra/models/parameters/AndroidOutlineButtonParameters.kt +28 -0
  44. package/android/src/main/java/voltra/models/parameters/AndroidRadioButtonParameters.kt +24 -0
  45. package/android/src/main/java/voltra/models/parameters/AndroidRowParameters.kt +22 -0
  46. package/android/src/main/java/voltra/models/parameters/AndroidScaffoldParameters.kt +22 -0
  47. package/android/src/main/java/voltra/models/parameters/AndroidSpacerParameters.kt +20 -0
  48. package/android/src/main/java/voltra/models/parameters/AndroidSquareIconButtonParameters.kt +28 -0
  49. package/android/src/main/java/voltra/models/parameters/AndroidSwitchParameters.kt +24 -0
  50. package/android/src/main/java/voltra/models/parameters/AndroidTextParameters.kt +26 -0
  51. package/android/src/main/java/voltra/models/parameters/AndroidTitleBarParameters.kt +24 -0
  52. package/android/src/main/java/voltra/parsing/VoltraDecompressor.kt +56 -0
  53. package/android/src/main/java/voltra/parsing/VoltraNodeDeserializer.kt +43 -0
  54. package/android/src/main/java/voltra/parsing/VoltraPayloadParser.kt +32 -0
  55. package/android/src/main/java/voltra/payload/ComponentTypeID.kt +63 -0
  56. package/android/src/main/java/voltra/styling/JSColorParser.kt +255 -0
  57. package/android/src/main/java/voltra/styling/JSStyleParser.kt +338 -0
  58. package/android/src/main/java/voltra/styling/StyleConverter.kt +255 -0
  59. package/android/src/main/java/voltra/styling/StyleModifiers.kt +312 -0
  60. package/android/src/main/java/voltra/styling/StyleStructures.kt +207 -0
  61. package/android/src/main/java/voltra/widget/VoltraGlanceWidget.kt +171 -0
  62. package/android/src/main/java/voltra/widget/VoltraWidgetManager.kt +314 -0
  63. package/android/src/main/java/voltra/widget/VoltraWidgetReceiver.kt +28 -0
  64. package/android/src/main/res/xml/voltra_file_paths.xml +4 -0
  65. package/build/VoltraModule.d.ts +60 -0
  66. package/build/VoltraModule.d.ts.map +1 -1
  67. package/build/VoltraModule.js.map +1 -1
  68. package/build/android/client.d.ts +8 -0
  69. package/build/android/client.d.ts.map +1 -0
  70. package/build/android/client.js +10 -0
  71. package/build/android/client.js.map +1 -0
  72. package/build/android/components/VoltraView.d.ts +29 -0
  73. package/build/android/components/VoltraView.d.ts.map +1 -0
  74. package/build/android/components/VoltraView.js +44 -0
  75. package/build/android/components/VoltraView.js.map +1 -0
  76. package/build/android/components/VoltraWidgetPreview.d.ts +22 -0
  77. package/build/android/components/VoltraWidgetPreview.d.ts.map +1 -0
  78. package/build/android/components/VoltraWidgetPreview.js +27 -0
  79. package/build/android/components/VoltraWidgetPreview.js.map +1 -0
  80. package/build/android/index.d.ts +15 -0
  81. package/build/android/index.d.ts.map +1 -0
  82. package/build/android/index.js +3 -0
  83. package/build/android/index.js.map +1 -0
  84. package/build/android/jsx/Box.d.ts +4 -0
  85. package/build/android/jsx/Box.d.ts.map +1 -0
  86. package/build/android/jsx/Box.js +3 -0
  87. package/build/android/jsx/Box.js.map +1 -0
  88. package/build/android/jsx/Button.d.ts +4 -0
  89. package/build/android/jsx/Button.d.ts.map +1 -0
  90. package/build/android/jsx/Button.js +3 -0
  91. package/build/android/jsx/Button.js.map +1 -0
  92. package/build/android/jsx/CheckBox.d.ts +4 -0
  93. package/build/android/jsx/CheckBox.d.ts.map +1 -0
  94. package/build/android/jsx/CheckBox.js +3 -0
  95. package/build/android/jsx/CheckBox.js.map +1 -0
  96. package/build/android/jsx/CircleIconButton.d.ts +4 -0
  97. package/build/android/jsx/CircleIconButton.d.ts.map +1 -0
  98. package/build/android/jsx/CircleIconButton.js +11 -0
  99. package/build/android/jsx/CircleIconButton.js.map +1 -0
  100. package/build/android/jsx/CircularProgressIndicator.d.ts +4 -0
  101. package/build/android/jsx/CircularProgressIndicator.d.ts.map +1 -0
  102. package/build/android/jsx/CircularProgressIndicator.js +3 -0
  103. package/build/android/jsx/CircularProgressIndicator.js.map +1 -0
  104. package/build/android/jsx/Column.d.ts +4 -0
  105. package/build/android/jsx/Column.d.ts.map +1 -0
  106. package/build/android/jsx/Column.js +3 -0
  107. package/build/android/jsx/Column.js.map +1 -0
  108. package/build/android/jsx/FilledButton.d.ts +4 -0
  109. package/build/android/jsx/FilledButton.d.ts.map +1 -0
  110. package/build/android/jsx/FilledButton.js +11 -0
  111. package/build/android/jsx/FilledButton.js.map +1 -0
  112. package/build/android/jsx/Image.d.ts +13 -0
  113. package/build/android/jsx/Image.d.ts.map +1 -0
  114. package/build/android/jsx/Image.js +11 -0
  115. package/build/android/jsx/Image.js.map +1 -0
  116. package/build/android/jsx/LazyColumn.d.ts +4 -0
  117. package/build/android/jsx/LazyColumn.d.ts.map +1 -0
  118. package/build/android/jsx/LazyColumn.js +3 -0
  119. package/build/android/jsx/LazyColumn.js.map +1 -0
  120. package/build/android/jsx/LazyVerticalGrid.d.ts +4 -0
  121. package/build/android/jsx/LazyVerticalGrid.d.ts.map +1 -0
  122. package/build/android/jsx/LazyVerticalGrid.js +3 -0
  123. package/build/android/jsx/LazyVerticalGrid.js.map +1 -0
  124. package/build/android/jsx/LinearProgressIndicator.d.ts +4 -0
  125. package/build/android/jsx/LinearProgressIndicator.d.ts.map +1 -0
  126. package/build/android/jsx/LinearProgressIndicator.js +3 -0
  127. package/build/android/jsx/LinearProgressIndicator.js.map +1 -0
  128. package/build/android/jsx/OutlineButton.d.ts +4 -0
  129. package/build/android/jsx/OutlineButton.d.ts.map +1 -0
  130. package/build/android/jsx/OutlineButton.js +11 -0
  131. package/build/android/jsx/OutlineButton.js.map +1 -0
  132. package/build/android/jsx/RadioButton.d.ts +4 -0
  133. package/build/android/jsx/RadioButton.d.ts.map +1 -0
  134. package/build/android/jsx/RadioButton.js +3 -0
  135. package/build/android/jsx/RadioButton.js.map +1 -0
  136. package/build/android/jsx/Row.d.ts +4 -0
  137. package/build/android/jsx/Row.d.ts.map +1 -0
  138. package/build/android/jsx/Row.js +3 -0
  139. package/build/android/jsx/Row.js.map +1 -0
  140. package/build/android/jsx/Scaffold.d.ts +4 -0
  141. package/build/android/jsx/Scaffold.d.ts.map +1 -0
  142. package/build/android/jsx/Scaffold.js +3 -0
  143. package/build/android/jsx/Scaffold.js.map +1 -0
  144. package/build/android/jsx/Spacer.d.ts +4 -0
  145. package/build/android/jsx/Spacer.d.ts.map +1 -0
  146. package/build/android/jsx/Spacer.js +3 -0
  147. package/build/android/jsx/Spacer.js.map +1 -0
  148. package/build/android/jsx/SquareIconButton.d.ts +4 -0
  149. package/build/android/jsx/SquareIconButton.d.ts.map +1 -0
  150. package/build/android/jsx/SquareIconButton.js +11 -0
  151. package/build/android/jsx/SquareIconButton.js.map +1 -0
  152. package/build/android/jsx/Switch.d.ts +4 -0
  153. package/build/android/jsx/Switch.d.ts.map +1 -0
  154. package/build/android/jsx/Switch.js +3 -0
  155. package/build/android/jsx/Switch.js.map +1 -0
  156. package/build/android/jsx/Text.d.ts +7 -0
  157. package/build/android/jsx/Text.d.ts.map +1 -0
  158. package/build/android/jsx/Text.js +3 -0
  159. package/build/android/jsx/Text.js.map +1 -0
  160. package/build/android/jsx/TitleBar.d.ts +4 -0
  161. package/build/android/jsx/TitleBar.d.ts.map +1 -0
  162. package/build/android/jsx/TitleBar.js +11 -0
  163. package/build/android/jsx/TitleBar.js.map +1 -0
  164. package/build/android/jsx/baseProps.d.ts +9 -0
  165. package/build/android/jsx/baseProps.d.ts.map +1 -0
  166. package/build/android/jsx/baseProps.js +2 -0
  167. package/build/android/jsx/baseProps.js.map +1 -0
  168. package/build/android/jsx/index.d.ts +2 -0
  169. package/build/android/jsx/index.d.ts.map +1 -0
  170. package/build/android/jsx/index.js +2 -0
  171. package/build/android/jsx/index.js.map +1 -0
  172. package/build/android/jsx/primitives.d.ts +21 -0
  173. package/build/android/jsx/primitives.d.ts.map +1 -0
  174. package/build/android/jsx/primitives.js +21 -0
  175. package/build/android/jsx/primitives.js.map +1 -0
  176. package/build/android/jsx/props/Box.d.ts +6 -0
  177. package/build/android/jsx/props/Box.d.ts.map +1 -0
  178. package/build/android/jsx/props/Box.js +2 -0
  179. package/build/android/jsx/props/Box.js.map +1 -0
  180. package/build/android/jsx/props/Button.d.ts +6 -0
  181. package/build/android/jsx/props/Button.d.ts.map +1 -0
  182. package/build/android/jsx/props/Button.js +2 -0
  183. package/build/android/jsx/props/Button.js.map +1 -0
  184. package/build/android/jsx/props/CheckBox.d.ts +17 -0
  185. package/build/android/jsx/props/CheckBox.d.ts.map +1 -0
  186. package/build/android/jsx/props/CheckBox.js +2 -0
  187. package/build/android/jsx/props/CheckBox.js.map +1 -0
  188. package/build/android/jsx/props/CircleIconButton.d.ts +15 -0
  189. package/build/android/jsx/props/CircleIconButton.d.ts.map +1 -0
  190. package/build/android/jsx/props/CircleIconButton.js +2 -0
  191. package/build/android/jsx/props/CircleIconButton.js.map +1 -0
  192. package/build/android/jsx/props/CircularProgressIndicator.d.ts +12 -0
  193. package/build/android/jsx/props/CircularProgressIndicator.d.ts.map +1 -0
  194. package/build/android/jsx/props/CircularProgressIndicator.js +2 -0
  195. package/build/android/jsx/props/CircularProgressIndicator.js.map +1 -0
  196. package/build/android/jsx/props/Column.d.ts +8 -0
  197. package/build/android/jsx/props/Column.d.ts.map +1 -0
  198. package/build/android/jsx/props/Column.js +2 -0
  199. package/build/android/jsx/props/Column.js.map +1 -0
  200. package/build/android/jsx/props/FilledButton.d.ts +17 -0
  201. package/build/android/jsx/props/FilledButton.d.ts.map +1 -0
  202. package/build/android/jsx/props/FilledButton.js +2 -0
  203. package/build/android/jsx/props/FilledButton.js.map +1 -0
  204. package/build/android/jsx/props/Image.d.ts +16 -0
  205. package/build/android/jsx/props/Image.d.ts.map +1 -0
  206. package/build/android/jsx/props/Image.js +5 -0
  207. package/build/android/jsx/props/Image.js.map +1 -0
  208. package/build/android/jsx/props/LazyColumn.d.ts +6 -0
  209. package/build/android/jsx/props/LazyColumn.d.ts.map +1 -0
  210. package/build/android/jsx/props/LazyColumn.js +2 -0
  211. package/build/android/jsx/props/LazyColumn.js.map +1 -0
  212. package/build/android/jsx/props/LazyVerticalGrid.d.ts +12 -0
  213. package/build/android/jsx/props/LazyVerticalGrid.d.ts.map +1 -0
  214. package/build/android/jsx/props/LazyVerticalGrid.js +2 -0
  215. package/build/android/jsx/props/LazyVerticalGrid.js.map +1 -0
  216. package/build/android/jsx/props/LinearProgressIndicator.d.ts +10 -0
  217. package/build/android/jsx/props/LinearProgressIndicator.d.ts.map +1 -0
  218. package/build/android/jsx/props/LinearProgressIndicator.js +2 -0
  219. package/build/android/jsx/props/LinearProgressIndicator.js.map +1 -0
  220. package/build/android/jsx/props/OutlineButton.d.ts +15 -0
  221. package/build/android/jsx/props/OutlineButton.d.ts.map +1 -0
  222. package/build/android/jsx/props/OutlineButton.js +2 -0
  223. package/build/android/jsx/props/OutlineButton.js.map +1 -0
  224. package/build/android/jsx/props/RadioButton.d.ts +19 -0
  225. package/build/android/jsx/props/RadioButton.d.ts.map +1 -0
  226. package/build/android/jsx/props/RadioButton.js +2 -0
  227. package/build/android/jsx/props/RadioButton.js.map +1 -0
  228. package/build/android/jsx/props/Row.d.ts +8 -0
  229. package/build/android/jsx/props/Row.d.ts.map +1 -0
  230. package/build/android/jsx/props/Row.js +2 -0
  231. package/build/android/jsx/props/Row.js.map +1 -0
  232. package/build/android/jsx/props/Scaffold.d.ts +8 -0
  233. package/build/android/jsx/props/Scaffold.d.ts.map +1 -0
  234. package/build/android/jsx/props/Scaffold.js +2 -0
  235. package/build/android/jsx/props/Scaffold.js.map +1 -0
  236. package/build/android/jsx/props/Spacer.d.ts +6 -0
  237. package/build/android/jsx/props/Spacer.d.ts.map +1 -0
  238. package/build/android/jsx/props/Spacer.js +2 -0
  239. package/build/android/jsx/props/Spacer.js.map +1 -0
  240. package/build/android/jsx/props/SquareIconButton.d.ts +15 -0
  241. package/build/android/jsx/props/SquareIconButton.d.ts.map +1 -0
  242. package/build/android/jsx/props/SquareIconButton.js +2 -0
  243. package/build/android/jsx/props/SquareIconButton.js.map +1 -0
  244. package/build/android/jsx/props/Switch.d.ts +21 -0
  245. package/build/android/jsx/props/Switch.d.ts.map +1 -0
  246. package/build/android/jsx/props/Switch.js +2 -0
  247. package/build/android/jsx/props/Switch.js.map +1 -0
  248. package/build/android/jsx/props/Text.d.ts +6 -0
  249. package/build/android/jsx/props/Text.d.ts.map +1 -0
  250. package/build/android/jsx/props/Text.js +2 -0
  251. package/build/android/jsx/props/Text.js.map +1 -0
  252. package/build/android/jsx/props/TitleBar.d.ts +15 -0
  253. package/build/android/jsx/props/TitleBar.d.ts.map +1 -0
  254. package/build/android/jsx/props/TitleBar.js +2 -0
  255. package/build/android/jsx/props/TitleBar.js.map +1 -0
  256. package/build/android/live-update/api.d.ts +126 -0
  257. package/build/android/live-update/api.d.ts.map +1 -0
  258. package/build/android/live-update/api.js +203 -0
  259. package/build/android/live-update/api.js.map +1 -0
  260. package/build/android/live-update/renderer.d.ts +11 -0
  261. package/build/android/live-update/renderer.d.ts.map +1 -0
  262. package/build/android/live-update/renderer.js +41 -0
  263. package/build/android/live-update/renderer.js.map +1 -0
  264. package/build/android/live-update/types.d.ts +100 -0
  265. package/build/android/live-update/types.d.ts.map +1 -0
  266. package/build/android/live-update/types.js +2 -0
  267. package/build/android/live-update/types.js.map +1 -0
  268. package/build/android/payload/component-ids.d.ts +20 -0
  269. package/build/android/payload/component-ids.d.ts.map +1 -0
  270. package/build/android/payload/component-ids.js +78 -0
  271. package/build/android/payload/component-ids.js.map +1 -0
  272. package/build/android/preload.d.ts +45 -0
  273. package/build/android/preload.d.ts.map +1 -0
  274. package/build/android/preload.js +72 -0
  275. package/build/android/preload.js.map +1 -0
  276. package/build/android/server.d.ts +3 -0
  277. package/build/android/server.d.ts.map +1 -0
  278. package/build/android/server.js +3 -0
  279. package/build/android/server.js.map +1 -0
  280. package/build/android/styles/types.d.ts +114 -0
  281. package/build/android/styles/types.d.ts.map +1 -0
  282. package/build/android/styles/types.js +6 -0
  283. package/build/android/styles/types.js.map +1 -0
  284. package/build/android/widgets/api.d.ts +119 -0
  285. package/build/android/widgets/api.d.ts.map +1 -0
  286. package/build/android/widgets/api.js +129 -0
  287. package/build/android/widgets/api.js.map +1 -0
  288. package/build/android/widgets/index.d.ts +3 -0
  289. package/build/android/widgets/index.d.ts.map +1 -0
  290. package/build/android/widgets/index.js +3 -0
  291. package/build/android/widgets/index.js.map +1 -0
  292. package/build/android/widgets/renderer.d.ts +22 -0
  293. package/build/android/widgets/renderer.d.ts.map +1 -0
  294. package/build/android/widgets/renderer.js +51 -0
  295. package/build/android/widgets/renderer.js.map +1 -0
  296. package/build/android/widgets/types.d.ts +42 -0
  297. package/build/android/widgets/types.d.ts.map +1 -0
  298. package/build/android/widgets/types.js +2 -0
  299. package/build/android/widgets/types.js.map +1 -0
  300. package/build/client.d.ts +1 -1
  301. package/build/client.d.ts.map +1 -1
  302. package/build/client.js +1 -1
  303. package/build/client.js.map +1 -1
  304. package/build/events.d.ts +16 -0
  305. package/build/events.d.ts.map +1 -1
  306. package/build/events.js +19 -2
  307. package/build/events.js.map +1 -1
  308. package/build/index.d.ts +1 -0
  309. package/build/index.d.ts.map +1 -1
  310. package/build/index.js +2 -0
  311. package/build/index.js.map +1 -1
  312. package/build/jsx/Link.d.ts +4 -0
  313. package/build/jsx/Link.d.ts.map +1 -0
  314. package/build/jsx/Link.js +3 -0
  315. package/build/jsx/Link.js.map +1 -0
  316. package/build/jsx/primitives.d.ts +1 -0
  317. package/build/jsx/primitives.d.ts.map +1 -1
  318. package/build/jsx/primitives.js +1 -0
  319. package/build/jsx/primitives.js.map +1 -1
  320. package/build/jsx/props/AndroidBox.d.ts +6 -0
  321. package/build/jsx/props/AndroidBox.d.ts.map +1 -0
  322. package/build/jsx/props/AndroidBox.js +5 -0
  323. package/build/jsx/props/AndroidBox.js.map +1 -0
  324. package/build/jsx/props/AndroidButton.d.ts +6 -0
  325. package/build/jsx/props/AndroidButton.d.ts.map +1 -0
  326. package/build/jsx/props/AndroidButton.js +5 -0
  327. package/build/jsx/props/AndroidButton.js.map +1 -0
  328. package/build/jsx/props/AndroidCheckBox.d.ts +10 -0
  329. package/build/jsx/props/AndroidCheckBox.d.ts.map +1 -0
  330. package/build/jsx/props/AndroidCheckBox.js +5 -0
  331. package/build/jsx/props/AndroidCheckBox.js.map +1 -0
  332. package/build/jsx/props/AndroidCircleIconButton.d.ts +14 -0
  333. package/build/jsx/props/AndroidCircleIconButton.d.ts.map +1 -0
  334. package/build/jsx/props/AndroidCircleIconButton.js +5 -0
  335. package/build/jsx/props/AndroidCircleIconButton.js.map +1 -0
  336. package/build/jsx/props/AndroidCircularProgressIndicator.d.ts +6 -0
  337. package/build/jsx/props/AndroidCircularProgressIndicator.d.ts.map +1 -0
  338. package/build/jsx/props/AndroidCircularProgressIndicator.js +5 -0
  339. package/build/jsx/props/AndroidCircularProgressIndicator.js.map +1 -0
  340. package/build/jsx/props/AndroidColumn.d.ts +8 -0
  341. package/build/jsx/props/AndroidColumn.d.ts.map +1 -0
  342. package/build/jsx/props/AndroidColumn.js +5 -0
  343. package/build/jsx/props/AndroidColumn.js.map +1 -0
  344. package/build/jsx/props/AndroidFilledButton.d.ts +16 -0
  345. package/build/jsx/props/AndroidFilledButton.d.ts.map +1 -0
  346. package/build/jsx/props/AndroidFilledButton.js +5 -0
  347. package/build/jsx/props/AndroidFilledButton.js.map +1 -0
  348. package/build/jsx/props/AndroidImage.d.ts +8 -0
  349. package/build/jsx/props/AndroidImage.d.ts.map +1 -0
  350. package/build/jsx/props/AndroidImage.js +5 -0
  351. package/build/jsx/props/AndroidImage.js.map +1 -0
  352. package/build/jsx/props/AndroidLazyColumn.d.ts +6 -0
  353. package/build/jsx/props/AndroidLazyColumn.d.ts.map +1 -0
  354. package/build/jsx/props/AndroidLazyColumn.js +5 -0
  355. package/build/jsx/props/AndroidLazyColumn.js.map +1 -0
  356. package/build/jsx/props/AndroidLazyVerticalGrid.d.ts +3 -0
  357. package/build/jsx/props/AndroidLazyVerticalGrid.d.ts.map +1 -0
  358. package/build/jsx/props/AndroidLazyVerticalGrid.js +5 -0
  359. package/build/jsx/props/AndroidLazyVerticalGrid.js.map +1 -0
  360. package/build/jsx/props/AndroidLinearProgressIndicator.d.ts +8 -0
  361. package/build/jsx/props/AndroidLinearProgressIndicator.d.ts.map +1 -0
  362. package/build/jsx/props/AndroidLinearProgressIndicator.js +5 -0
  363. package/build/jsx/props/AndroidLinearProgressIndicator.js.map +1 -0
  364. package/build/jsx/props/AndroidOutlineButton.d.ts +14 -0
  365. package/build/jsx/props/AndroidOutlineButton.d.ts.map +1 -0
  366. package/build/jsx/props/AndroidOutlineButton.js +5 -0
  367. package/build/jsx/props/AndroidOutlineButton.js.map +1 -0
  368. package/build/jsx/props/AndroidRadioButton.d.ts +10 -0
  369. package/build/jsx/props/AndroidRadioButton.d.ts.map +1 -0
  370. package/build/jsx/props/AndroidRadioButton.js +5 -0
  371. package/build/jsx/props/AndroidRadioButton.js.map +1 -0
  372. package/build/jsx/props/AndroidRow.d.ts +8 -0
  373. package/build/jsx/props/AndroidRow.d.ts.map +1 -0
  374. package/build/jsx/props/AndroidRow.js +5 -0
  375. package/build/jsx/props/AndroidRow.js.map +1 -0
  376. package/build/jsx/props/AndroidScaffold.d.ts +8 -0
  377. package/build/jsx/props/AndroidScaffold.d.ts.map +1 -0
  378. package/build/jsx/props/AndroidScaffold.js +5 -0
  379. package/build/jsx/props/AndroidScaffold.js.map +1 -0
  380. package/build/jsx/props/AndroidSpacer.d.ts +3 -0
  381. package/build/jsx/props/AndroidSpacer.d.ts.map +1 -0
  382. package/build/jsx/props/AndroidSpacer.js +5 -0
  383. package/build/jsx/props/AndroidSpacer.js.map +1 -0
  384. package/build/jsx/props/AndroidSquareIconButton.d.ts +14 -0
  385. package/build/jsx/props/AndroidSquareIconButton.d.ts.map +1 -0
  386. package/build/jsx/props/AndroidSquareIconButton.js +5 -0
  387. package/build/jsx/props/AndroidSquareIconButton.js.map +1 -0
  388. package/build/jsx/props/AndroidSwitch.d.ts +10 -0
  389. package/build/jsx/props/AndroidSwitch.d.ts.map +1 -0
  390. package/build/jsx/props/AndroidSwitch.js +5 -0
  391. package/build/jsx/props/AndroidSwitch.js.map +1 -0
  392. package/build/jsx/props/AndroidText.d.ts +12 -0
  393. package/build/jsx/props/AndroidText.d.ts.map +1 -0
  394. package/build/jsx/props/AndroidText.js +5 -0
  395. package/build/jsx/props/AndroidText.js.map +1 -0
  396. package/build/jsx/props/AndroidTitleBar.d.ts +10 -0
  397. package/build/jsx/props/AndroidTitleBar.d.ts.map +1 -0
  398. package/build/jsx/props/AndroidTitleBar.js +5 -0
  399. package/build/jsx/props/AndroidTitleBar.js.map +1 -0
  400. package/build/jsx/props/FilledButton.d.ts +16 -0
  401. package/build/jsx/props/FilledButton.d.ts.map +1 -0
  402. package/build/jsx/props/FilledButton.js +5 -0
  403. package/build/jsx/props/FilledButton.js.map +1 -0
  404. package/build/jsx/props/LegacyAndroidCheckBox.d.ts +8 -0
  405. package/build/jsx/props/LegacyAndroidCheckBox.d.ts.map +1 -0
  406. package/build/jsx/props/LegacyAndroidCheckBox.js +5 -0
  407. package/build/jsx/props/LegacyAndroidCheckBox.js.map +1 -0
  408. package/build/jsx/props/LegacyAndroidRadioButton.d.ts +8 -0
  409. package/build/jsx/props/LegacyAndroidRadioButton.d.ts.map +1 -0
  410. package/build/jsx/props/LegacyAndroidRadioButton.js +5 -0
  411. package/build/jsx/props/LegacyAndroidRadioButton.js.map +1 -0
  412. package/build/jsx/props/LegacyAndroidSwitch.d.ts +8 -0
  413. package/build/jsx/props/LegacyAndroidSwitch.d.ts.map +1 -0
  414. package/build/jsx/props/LegacyAndroidSwitch.js +5 -0
  415. package/build/jsx/props/LegacyAndroidSwitch.js.map +1 -0
  416. package/build/jsx/props/LegacyFilledButton.d.ts +8 -0
  417. package/build/jsx/props/LegacyFilledButton.d.ts.map +1 -0
  418. package/build/jsx/props/LegacyFilledButton.js +5 -0
  419. package/build/jsx/props/LegacyFilledButton.js.map +1 -0
  420. package/build/jsx/props/LegacyImage.d.ts +8 -0
  421. package/build/jsx/props/LegacyImage.d.ts.map +1 -0
  422. package/build/jsx/props/LegacyImage.js +5 -0
  423. package/build/jsx/props/LegacyImage.js.map +1 -0
  424. package/build/jsx/props/Link.d.ts +6 -0
  425. package/build/jsx/props/Link.d.ts.map +1 -0
  426. package/build/jsx/props/Link.js +5 -0
  427. package/build/jsx/props/Link.js.map +1 -0
  428. package/build/jsx/props/Timer.d.ts +2 -0
  429. package/build/jsx/props/Timer.d.ts.map +1 -1
  430. package/build/jsx/props/Timer.js.map +1 -1
  431. package/build/live-activity/renderer.d.ts.map +1 -1
  432. package/build/live-activity/renderer.js +4 -0
  433. package/build/live-activity/renderer.js.map +1 -1
  434. package/build/live-activity/types.d.ts +13 -0
  435. package/build/live-activity/types.d.ts.map +1 -1
  436. package/build/live-activity/types.js.map +1 -1
  437. package/build/payload/component-ids.d.ts.map +1 -1
  438. package/build/payload/component-ids.js +2 -0
  439. package/build/payload/component-ids.js.map +1 -1
  440. package/build/payload/short-names.d.ts.map +1 -1
  441. package/build/payload/short-names.js +40 -0
  442. package/build/payload/short-names.js.map +1 -1
  443. package/build/renderer/flatten-styles.d.ts +5 -1
  444. package/build/renderer/flatten-styles.d.ts.map +1 -1
  445. package/build/renderer/flatten-styles.js +4 -1
  446. package/build/renderer/flatten-styles.js.map +1 -1
  447. package/build/renderer/index.d.ts +1 -1
  448. package/build/renderer/index.d.ts.map +1 -1
  449. package/build/renderer/index.js +1 -1
  450. package/build/renderer/index.js.map +1 -1
  451. package/build/renderer/renderer.d.ts +20 -1
  452. package/build/renderer/renderer.d.ts.map +1 -1
  453. package/build/renderer/renderer.js +42 -8
  454. package/build/renderer/renderer.js.map +1 -1
  455. package/build/styles/types.d.ts +1 -1
  456. package/build/styles/types.d.ts.map +1 -1
  457. package/build/styles/types.js.map +1 -1
  458. package/build/widgets/types.d.ts +17 -0
  459. package/build/widgets/types.d.ts.map +1 -1
  460. package/build/widgets/types.js.map +1 -1
  461. package/build/widgets/widget-api.d.ts +57 -1
  462. package/build/widgets/widget-api.d.ts.map +1 -1
  463. package/build/widgets/widget-api.js +71 -0
  464. package/build/widgets/widget-api.js.map +1 -1
  465. package/expo-module.config.json +4 -1
  466. package/ios/app/VoltraActivity.swift +5 -0
  467. package/ios/app/VoltraLiveActivityService.swift +103 -7
  468. package/ios/app/VoltraModule.swift +29 -462
  469. package/ios/app/VoltraModuleImpl.swift +487 -0
  470. package/ios/shared/ComponentTypeID.swift +4 -0
  471. package/ios/shared/ShortNames.swift +21 -1
  472. package/ios/shared/VoltraElement.swift +6 -2
  473. package/ios/shared/VoltraNode.swift +3 -0
  474. package/ios/shared/VoltraRegion.swift +3 -0
  475. package/ios/target/VoltraHomeWidget.swift +174 -56
  476. package/ios/target/VoltraWidget.swift +125 -30
  477. package/ios/ui/Generated/Parameters/AndroidCheckBoxParameters.swift +29 -0
  478. package/ios/ui/Generated/Parameters/AndroidRadioButtonParameters.swift +29 -0
  479. package/ios/ui/Generated/Parameters/AndroidSwitchParameters.swift +29 -0
  480. package/ios/ui/Generated/Parameters/FilledButtonParameters.swift +29 -0
  481. package/ios/ui/Generated/Parameters/LinkParameters.swift +15 -0
  482. package/ios/ui/Generated/Parameters/TimerParameters.swift +5 -0
  483. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +19 -5
  484. package/ios/ui/Style/StyleConverter.swift +4 -0
  485. package/ios/ui/Style/TextStyle.swift +7 -1
  486. package/ios/ui/Views/VoltraLink.swift +25 -0
  487. package/ios/ui/Views/VoltraText.swift +16 -0
  488. package/ios/ui/Views/VoltraTimer.swift +31 -16
  489. package/package.json +22 -3
  490. package/plugin/build/constants/index.d.ts +1 -1
  491. package/plugin/build/constants/index.js +2 -1
  492. package/plugin/build/constants/paths.d.ts +2 -0
  493. package/plugin/build/constants/paths.js +3 -1
  494. package/plugin/build/features/android/files/assets/images.d.ts +20 -0
  495. package/plugin/build/features/android/files/assets/images.js +165 -0
  496. package/plugin/build/features/android/files/assets/index.d.ts +21 -0
  497. package/plugin/build/features/android/files/assets/index.js +95 -0
  498. package/plugin/build/features/android/files/assets/preview.d.ts +6 -0
  499. package/plugin/build/features/android/files/assets/preview.js +73 -0
  500. package/plugin/build/features/android/files/index.d.ts +19 -0
  501. package/plugin/build/features/android/files/index.js +58 -0
  502. package/plugin/build/features/android/files/initialStates.d.ts +13 -0
  503. package/plugin/build/features/android/files/initialStates.js +48 -0
  504. package/plugin/build/features/android/files/kotlin/index.d.ts +10 -0
  505. package/plugin/build/features/android/files/kotlin/index.js +59 -0
  506. package/plugin/build/features/android/files/kotlin/widgetReceiver.d.ts +5 -0
  507. package/plugin/build/features/android/files/kotlin/widgetReceiver.js +27 -0
  508. package/plugin/build/features/android/files/xml/index.d.ts +11 -0
  509. package/plugin/build/features/android/files/xml/index.js +76 -0
  510. package/plugin/build/features/android/files/xml/placeholderLayout.d.ts +5 -0
  511. package/plugin/build/features/android/files/xml/placeholderLayout.js +27 -0
  512. package/plugin/build/features/android/files/xml/previewLayout.d.ts +11 -0
  513. package/plugin/build/features/android/files/xml/previewLayout.js +106 -0
  514. package/plugin/build/features/android/files/xml/stringResources.d.ts +5 -0
  515. package/plugin/build/features/android/files/xml/stringResources.js +22 -0
  516. package/plugin/build/features/android/files/xml/widgetInfo.d.ts +5 -0
  517. package/plugin/build/features/android/files/xml/widgetInfo.js +43 -0
  518. package/plugin/build/features/android/index.d.ts +11 -0
  519. package/plugin/build/features/android/index.js +29 -0
  520. package/plugin/build/features/android/manifest/index.d.ts +14 -0
  521. package/plugin/build/features/android/manifest/index.js +62 -0
  522. package/plugin/build/features/ios/eas/index.d.ts +1 -1
  523. package/plugin/build/features/ios/eas/index.js +9 -7
  524. package/plugin/build/features/ios/files/entitlements.d.ts +2 -2
  525. package/plugin/build/features/ios/files/entitlements.js +3 -1
  526. package/plugin/build/features/ios/files/index.d.ts +1 -1
  527. package/plugin/build/features/ios/files/index.js +1 -1
  528. package/plugin/build/features/ios/files/swift/index.js +5 -2
  529. package/plugin/build/features/ios/files/swift/widgetBundle.js +2 -2
  530. package/plugin/build/features/ios/fonts.d.ts +21 -0
  531. package/plugin/build/features/ios/fonts.js +173 -0
  532. package/plugin/build/features/ios/index.d.ts +12 -5
  533. package/plugin/build/features/ios/index.js +21 -11
  534. package/plugin/build/features/ios/plist/index.d.ts +1 -1
  535. package/plugin/build/features/ios/plist/index.js +5 -1
  536. package/plugin/build/features/ios/xcode/build/phases.js +1 -1
  537. package/plugin/build/index.d.ts +2 -2
  538. package/plugin/build/index.js +17 -11
  539. package/plugin/build/types/index.d.ts +1 -1
  540. package/plugin/build/types/plugin.d.ts +108 -3
  541. package/plugin/build/utils/prerender.d.ts +24 -0
  542. package/plugin/build/{features/ios/files/swift → utils}/prerender.js +5 -5
  543. package/plugin/build/validation/validateAndroidWidget.d.ts +6 -0
  544. package/plugin/build/validation/validateAndroidWidget.js +123 -0
  545. package/plugin/build/validation/validateProps.d.ts +1 -1
  546. package/plugin/build/validation/validateProps.js +30 -14
  547. package/scripts/release-canary.js +65 -0
  548. package/plugin/build/features/ios/files/swift/prerender.d.ts +0 -13
package/README.md CHANGED
@@ -1,32 +1,33 @@
1
1
  ![voltra-banner](https://use-voltra.dev/voltra-baner.jpg)
2
2
 
3
- ### Build Live Activities with JSX in React Native
3
+ ### Build Live Activities and Widgets with JSX in React Native
4
4
 
5
5
  [![mit licence][license-badge]][license] [![npm downloads][npm-downloads-badge]][npm-downloads] [![PRs Welcome][prs-welcome-badge]][prs-welcome]
6
6
 
7
- Voltra turns React Native JSX into SwiftUI so you can ship custom Live Activities, Dynamic Island layouts without touching Xcode. Author everything in React, keep hot reload, and let the config plugin handle the extension targets.
7
+ Voltra turns React Native JSX into SwiftUI and Jetpack Compose Glance so you can ship custom Live Activities, Dynamic Island layouts, and Android Widgets without touching native code. Author everything in React, keep hot reload, and let the config plugin handle the native extension targets.
8
8
 
9
9
  ## Features
10
10
 
11
- - **Ship Native iOS Surfaces**: Create Live Activities, Dynamic Island variants, and static widgets directly from React components - no Swift or Xcode required.
11
+ - **Ship Native Surfaces**: Create iOS Live Activities, Dynamic Island variants, and Android Home Screen widgets directly from React components - no Swift, Kotlin, or Xcode/Android Studio UI work required.
12
12
 
13
- - **Fast Development Workflow**: Hooks respect Fast Refresh and both JS and native layers enforce ActivityKit payload budgets.
13
+ - **Fast Development Workflow**: Hooks respect Fast Refresh and both JS and native layers enforce platform-specific payload budgets.
14
14
 
15
- - **Production-Ready Push Notifications**: Collect ActivityKit push tokens and push-to-start tokens, stream lifecycle updates, and build server-driven refreshes.
15
+ - **Production-Ready Push Notifications**: Support for ActivityKit push tokens (iOS) and FCM (Android) to stream lifecycle updates and build server-driven refreshes.
16
16
 
17
- - **Familiar Styling**: Use React Native style props and ordered SwiftUI modifiers in one place.
17
+ - **Familiar Styling**: Use React Native style props and platform-native modifiers (SwiftUI/Glance) in one place.
18
18
 
19
19
  - **Type-Safe & Developer-Friendly**: The Voltra schema, hooks, and examples ship with TypeScript definitions, tests, and docs so AI coding agents stay productive.
20
20
 
21
- - **Works With Your Setup**: Compatible with Expo Dev Client and bare React Native projects. The config plugin automatically wires iOS extension targets for you.
21
+ - **Works With Your Setup**: Compatible with Expo Dev Client and bare React Native projects. The config plugin automatically wires native extension targets for you.
22
22
 
23
23
  ## Documentation
24
24
 
25
25
  The documentation is available at [use-voltra.dev](https://use-voltra.dev). You can also use the following links to jump to specific topics:
26
26
 
27
- - [Quick Start](https://use-voltra.dev/docs/getting-started/quick-start)
28
- - [API Reference](https://use-voltra.dev/docs/api/overview)
29
- - [Examples](https://use-voltra.dev/docs/examples)
27
+ - [Quick Start](https://use-voltra.dev/getting-started/quick-start)
28
+ - [Development](https://www.use-voltra.dev/development/developing-live-activities)
29
+ - [Components](https://www.use-voltra.dev/components/overview)
30
+ - [API Reference](https://use-voltra.dev/api/configuration)
30
31
 
31
32
  ## Getting started
32
33
 
@@ -49,9 +50,9 @@ Add the config plugin to your `app.json`:
49
50
  }
50
51
  ```
51
52
 
52
- Then run `npx expo prebuild --clean` to generate the iOS extension target.
53
+ Then run `npx expo prebuild --clean` to generate the native extension targets.
53
54
 
54
- See the [documentation](https://use-voltra.dev/docs/getting-started/quick-start) for detailed setup instructions.
55
+ See the [documentation](https://use-voltra.dev/getting-started/quick-start) for detailed setup instructions.
55
56
 
56
57
  ## Quick example
57
58
 
@@ -82,7 +83,10 @@ export function OrderTracker({ orderId }: { orderId: string }) {
82
83
 
83
84
  ## Platform compatibility
84
85
 
85
- **Note:** This module is intended for use on **iOS devices only**.
86
+ Voltra is a cross-platform library that supports:
87
+
88
+ - **iOS**: Live Activities and Dynamic Island (SwiftUI).
89
+ - **Android**: Home Screen Widgets (Jetpack Compose Glance).
86
90
 
87
91
  ## Authors
88
92
 
File without changes
@@ -0,0 +1,2 @@
1
+ #Wed Jan 28 15:59:43 CET 2026
2
+ gradle.version=8.9
File without changes
@@ -0,0 +1,84 @@
1
+ buildscript {
2
+ // 1. ADD THIS BLOCK TO RESOLVE THE PLUGIN
3
+ repositories {
4
+ google()
5
+ mavenCentral()
6
+ }
7
+ dependencies {
8
+ // Ensure this version matches your project's Kotlin version (e.g., 2.0.0, 2.0.20)
9
+ classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.0.0"
10
+ classpath "org.jetbrains.kotlin:kotlin-serialization:2.0.21"
11
+ }
12
+
13
+ // Existing helper
14
+ ext.safeExtGet = { prop, fallback ->
15
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
16
+ }
17
+ }
18
+
19
+ apply plugin: 'com.android.library'
20
+ apply plugin: 'org.jetbrains.kotlin.plugin.compose'
21
+ apply plugin: 'org.jetbrains.kotlin.plugin.serialization'
22
+
23
+ group = 'voltra'
24
+ version = '0.1.0'
25
+
26
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
27
+ apply from: expoModulesCorePlugin
28
+ applyKotlinExpoModulesCorePlugin()
29
+ useCoreDependencies()
30
+ useExpoPublishing()
31
+
32
+ // If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
33
+ // The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
34
+ // Most of the time, you may like to manage the Android SDK versions yourself.
35
+ def useManagedAndroidSdkVersions = false
36
+ if (useManagedAndroidSdkVersions) {
37
+ useDefaultAndroidSdkVersions()
38
+ } else {
39
+ buildscript {
40
+ // Simple helper that allows the root project to override versions declared by this library.
41
+ ext.safeExtGet = { prop, fallback ->
42
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
43
+ }
44
+ }
45
+ project.android {
46
+ compileSdkVersion safeExtGet("compileSdkVersion", 36)
47
+ defaultConfig {
48
+ minSdkVersion safeExtGet("minSdkVersion", 31)
49
+ targetSdkVersion safeExtGet("targetSdkVersion", 36)
50
+ }
51
+ }
52
+ }
53
+
54
+ android {
55
+ namespace "voltra"
56
+ defaultConfig {
57
+ versionCode 1
58
+ versionName "0.1.0"
59
+ }
60
+ lintOptions {
61
+ abortOnError false
62
+ }
63
+ buildFeatures {
64
+ compose true
65
+ }
66
+ }
67
+
68
+ dependencies {
69
+ // Jetpack Glance - use 'api' instead of 'implementation' to make these available to consuming apps
70
+ api "androidx.glance:glance:1.2.0-rc01"
71
+ api "androidx.glance:glance-appwidget:1.2.0-rc01"
72
+
73
+ // Compose runtime (required for Glance)
74
+ api "androidx.compose.runtime:runtime:1.6.8"
75
+
76
+ // JSON parsing
77
+ implementation "com.google.code.gson:gson:2.10.1"
78
+
79
+ // Coroutines
80
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
81
+
82
+ // Kotlinx Serialization
83
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
84
+ }
@@ -0,0 +1,15 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
3
+
4
+ <application>
5
+ <provider
6
+ android:name="androidx.core.content.FileProvider"
7
+ android:authorities="${applicationId}.voltra.fileprovider"
8
+ android:exported="false"
9
+ android:grantUriPermissions="true">
10
+ <meta-data
11
+ android:name="android.support.FILE_PROVIDER_PATHS"
12
+ android:resource="@xml/voltra_file_paths" />
13
+ </provider>
14
+ </application>
15
+ </manifest>
@@ -0,0 +1,296 @@
1
+ package voltra
2
+
3
+ import android.util.Log
4
+ import androidx.compose.ui.unit.DpSize
5
+ import androidx.compose.ui.unit.dp
6
+ import androidx.glance.appwidget.GlanceAppWidgetManager
7
+ import expo.modules.kotlin.modules.Module
8
+ import expo.modules.kotlin.modules.ModuleDefinition
9
+ import kotlinx.coroutines.async
10
+ import kotlinx.coroutines.awaitAll
11
+ import kotlinx.coroutines.runBlocking
12
+ import voltra.events.VoltraEventBus
13
+ import voltra.images.VoltraImageManager
14
+ import voltra.widget.VoltraGlanceWidget
15
+ import voltra.widget.VoltraWidgetManager
16
+
17
+ class VoltraModule : Module() {
18
+ companion object {
19
+ private const val TAG = "VoltraModule"
20
+ }
21
+
22
+ private val notificationManager by lazy {
23
+ VoltraNotificationManager(appContext.reactContext!!)
24
+ }
25
+
26
+ private val widgetManager by lazy {
27
+ VoltraWidgetManager(appContext.reactContext!!)
28
+ }
29
+
30
+ private val imageManager by lazy {
31
+ VoltraImageManager(appContext.reactContext!!)
32
+ }
33
+
34
+ private val eventBus by lazy {
35
+ VoltraEventBus.getInstance(appContext.reactContext!!)
36
+ }
37
+
38
+ private var eventBusUnsubscribe: (() -> Unit)? = null
39
+
40
+ override fun definition() =
41
+ ModuleDefinition {
42
+ Name("VoltraModule")
43
+
44
+ OnStartObserving {
45
+ Log.d(TAG, "OnStartObserving: Starting event bus subscription")
46
+
47
+ // Replay any persisted events from SharedPreferences (cold start)
48
+ val persistedEvents = eventBus.popAll()
49
+ Log.d(TAG, "Replaying ${persistedEvents.size} persisted events")
50
+
51
+ persistedEvents.forEach { event ->
52
+ sendEvent(event.type, event.toMap())
53
+ }
54
+
55
+ // Subscribe to hot event delivery (broadcast receiver)
56
+ eventBusUnsubscribe =
57
+ eventBus.addListener { event ->
58
+ Log.d(TAG, "Received hot event: ${event.type}")
59
+ sendEvent(event.type, event.toMap())
60
+ }
61
+ }
62
+
63
+ OnStopObserving {
64
+ Log.d(TAG, "OnStopObserving: Unsubscribing from event bus")
65
+ eventBusUnsubscribe?.invoke()
66
+ eventBusUnsubscribe = null
67
+ }
68
+
69
+ // Android Live Update APIs
70
+
71
+ AsyncFunction("startAndroidLiveUpdate") {
72
+ payload: String,
73
+ options: Map<String, Any?>,
74
+ ->
75
+
76
+ Log.d(TAG, "startAndroidLiveUpdate called")
77
+
78
+ val updateName = options["updateName"] as? String
79
+ val channelId = options["channelId"] as? String ?: "voltra_live_updates"
80
+
81
+ Log.d(TAG, "updateName=$updateName, channelId=$channelId")
82
+
83
+ val result =
84
+ runBlocking {
85
+ notificationManager.startLiveUpdate(payload, updateName, channelId)
86
+ }
87
+
88
+ Log.d(TAG, "startAndroidLiveUpdate returning: $result")
89
+ result
90
+ }
91
+
92
+ AsyncFunction("updateAndroidLiveUpdate") {
93
+ notificationId: String,
94
+ payload: String,
95
+ ->
96
+
97
+ Log.d(TAG, "updateAndroidLiveUpdate called with notificationId=$notificationId")
98
+
99
+ runBlocking {
100
+ notificationManager.updateLiveUpdate(notificationId, payload)
101
+ }
102
+
103
+ Log.d(TAG, "updateAndroidLiveUpdate completed")
104
+ }
105
+
106
+ AsyncFunction("stopAndroidLiveUpdate") { notificationId: String ->
107
+ Log.d(TAG, "stopAndroidLiveUpdate called with notificationId=$notificationId")
108
+ notificationManager.stopLiveUpdate(notificationId)
109
+ }
110
+
111
+ Function("isAndroidLiveUpdateActive") { updateName: String ->
112
+ notificationManager.isLiveUpdateActive(updateName)
113
+ }
114
+
115
+ AsyncFunction("endAllAndroidLiveUpdates") {
116
+ notificationManager.endAllLiveUpdates()
117
+ }
118
+
119
+ // Android Widget APIs
120
+
121
+ AsyncFunction("updateAndroidWidget") {
122
+ widgetId: String,
123
+ jsonString: String,
124
+ options: Map<String, Any?>,
125
+ ->
126
+
127
+ Log.d(TAG, "updateAndroidWidget called with widgetId=$widgetId")
128
+
129
+ val deepLinkUrl = options["deepLinkUrl"] as? String
130
+
131
+ widgetManager.writeWidgetData(widgetId, jsonString, deepLinkUrl)
132
+
133
+ runBlocking {
134
+ widgetManager.updateWidget(widgetId)
135
+ }
136
+
137
+ Log.d(TAG, "updateAndroidWidget completed")
138
+ }
139
+
140
+ AsyncFunction("reloadAndroidWidgets") { widgetIds: ArrayList<String>? ->
141
+ Log.d(TAG, "reloadAndroidWidgets called with widgetIds=$widgetIds")
142
+
143
+ runBlocking {
144
+ widgetManager.reloadWidgets(widgetIds)
145
+ }
146
+
147
+ Log.d(TAG, "reloadAndroidWidgets completed")
148
+ }
149
+
150
+ AsyncFunction("clearAndroidWidget") { widgetId: String ->
151
+ Log.d(TAG, "clearAndroidWidget called with widgetId=$widgetId")
152
+
153
+ widgetManager.clearWidgetData(widgetId)
154
+
155
+ runBlocking {
156
+ widgetManager.updateWidget(widgetId)
157
+ }
158
+
159
+ Log.d(TAG, "clearAndroidWidget completed")
160
+ }
161
+
162
+ AsyncFunction("clearAllAndroidWidgets") {
163
+ Log.d(TAG, "clearAllAndroidWidgets called")
164
+
165
+ widgetManager.clearAllWidgetData()
166
+
167
+ runBlocking {
168
+ widgetManager.reloadAllWidgets()
169
+ }
170
+
171
+ Log.d(TAG, "clearAllAndroidWidgets completed")
172
+ }
173
+
174
+ AsyncFunction("requestPinGlanceAppWidget") {
175
+ widgetId: String,
176
+ options: Map<String, Any?>?,
177
+ ->
178
+
179
+ Log.d(TAG, "requestPinGlanceAppWidget called with widgetId=$widgetId")
180
+
181
+ val context = appContext.reactContext!!
182
+
183
+ // Construct the receiver class name following the convention
184
+ val receiverClassName = "${context.packageName}.widget.VoltraWidget_${widgetId}Receiver"
185
+
186
+ Log.d(TAG, "Looking for receiver: $receiverClassName")
187
+
188
+ // Get the receiver class using reflection
189
+ val receiverClass =
190
+ try {
191
+ Class.forName(receiverClassName) as Class<out androidx.glance.appwidget.GlanceAppWidgetReceiver>
192
+ } catch (e: ClassNotFoundException) {
193
+ Log.e(TAG, "Widget receiver class not found: $receiverClassName", e)
194
+ throw IllegalArgumentException("Widget receiver not found for id: $widgetId")
195
+ }
196
+
197
+ // Get GlanceAppWidgetManager and request pin
198
+ val glanceManager = GlanceAppWidgetManager(context)
199
+
200
+ // Parse preview size from options (optional)
201
+ // See: https://developer.android.com/develop/ui/compose/glance/pin-in-app
202
+ val previewSize =
203
+ if (options != null) {
204
+ val width = (options["previewWidth"] as? Number)?.toFloat()
205
+ val height = (options["previewHeight"] as? Number)?.toFloat()
206
+ if (width != null && height != null) {
207
+ DpSize(width.dp, height.dp)
208
+ } else {
209
+ null
210
+ }
211
+ } else {
212
+ null
213
+ }
214
+
215
+ val result =
216
+ runBlocking {
217
+ // requestPinGlanceAppWidget is a suspend function
218
+ // See: https://developer.android.com/develop/ui/compose/glance/pin-in-app
219
+ if (previewSize != null) {
220
+ // Create preview widget with preview dimensions
221
+ val previewWidget = VoltraGlanceWidget(widgetId)
222
+ glanceManager.requestPinGlanceAppWidget(
223
+ receiver = receiverClass,
224
+ preview = previewWidget,
225
+ previewState = previewSize,
226
+ )
227
+ } else {
228
+ // Basic pin request without preview
229
+ glanceManager.requestPinGlanceAppWidget(receiverClass)
230
+ }
231
+ }
232
+
233
+ Log.d(TAG, "requestPinGlanceAppWidget completed with result=$result")
234
+ result
235
+ }
236
+
237
+ AsyncFunction("preloadImages") { images: List<Map<String, Any>> ->
238
+ Log.d(TAG, "preloadImages called with ${images.size} images")
239
+
240
+ runBlocking {
241
+ val results =
242
+ images
243
+ .map { img ->
244
+ async {
245
+ val url = img["url"] as String
246
+ val key = img["key"] as String
247
+ val method = (img["method"] as? String) ?: "GET"
248
+
249
+ @Suppress("UNCHECKED_CAST")
250
+ val headers = img["headers"] as? Map<String, String>
251
+
252
+ val resultKey = imageManager.preloadImage(url, key, method, headers)
253
+ if (resultKey != null) {
254
+ Pair(key, null)
255
+ } else {
256
+ Pair(key, "Failed to download image")
257
+ }
258
+ }
259
+ }.awaitAll()
260
+
261
+ val succeeded = results.filter { it.second == null }.map { it.first }
262
+ val failed =
263
+ results.filter { it.second != null }.map {
264
+ mapOf("key" to it.first, "error" to it.second)
265
+ }
266
+
267
+ mapOf(
268
+ "succeeded" to succeeded,
269
+ "failed" to failed,
270
+ )
271
+ }
272
+ }
273
+
274
+ AsyncFunction("clearPreloadedImages") { keys: List<String>? ->
275
+ Log.d(TAG, "clearPreloadedImages called with keys=$keys")
276
+ imageManager.clearPreloadedImages(keys)
277
+ }
278
+
279
+ AsyncFunction("reloadLiveActivities") { activityNames: List<String>? ->
280
+ // On Android, we don't have "Live Activities" in the same sense as iOS,
281
+ // but we might want to refresh widgets or notifications.
282
+ // For now, this is a no-op to match iOS API if called.
283
+ Log.d(TAG, "reloadLiveActivities called (no-op on Android)")
284
+ }
285
+
286
+ View(VoltraRN::class) {
287
+ Prop("payload") { view, payload: String ->
288
+ view.setPayload(payload)
289
+ }
290
+
291
+ Prop("viewId") { view, viewId: String ->
292
+ view.setViewId(viewId)
293
+ }
294
+ }
295
+ }
296
+ }
@@ -0,0 +1,157 @@
1
+ package voltra
2
+
3
+ import android.app.NotificationChannel
4
+ import android.app.NotificationManager
5
+ import android.content.Context
6
+ import android.os.Build
7
+ import android.util.Log
8
+ import androidx.core.app.NotificationCompat
9
+ import kotlinx.coroutines.Dispatchers
10
+ import kotlinx.coroutines.withContext
11
+ import voltra.glance.RemoteViewsGenerator
12
+ import voltra.parsing.VoltraPayloadParser
13
+ import java.util.concurrent.ConcurrentHashMap
14
+ import java.util.concurrent.atomic.AtomicInteger
15
+
16
+ class VoltraNotificationManager(
17
+ private val context: Context,
18
+ ) {
19
+ companion object {
20
+ private const val TAG = "VoltraNotificationMgr"
21
+ }
22
+
23
+ private val notificationManager =
24
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
25
+ private val activeNotifications = ConcurrentHashMap<String, Int>()
26
+ private val idCounter = AtomicInteger(10000)
27
+
28
+ suspend fun startLiveUpdate(
29
+ payload: String,
30
+ updateName: String?,
31
+ channelId: String,
32
+ ): String =
33
+ withContext(Dispatchers.Default) {
34
+ Log.d(TAG, "startLiveUpdate called with updateName=$updateName, channelId=$channelId")
35
+ Log.d(TAG, "Payload (first 200 chars): ${payload.take(200)}")
36
+
37
+ val voltraPayload = VoltraPayloadParser.parse(payload)
38
+ val notificationId = updateName ?: "live-update-${idCounter.getAndIncrement()}"
39
+ val intId = notificationId.hashCode().and(0x7FFFFFFF) // Ensure positive
40
+
41
+ Log.d(TAG, "Parsed payload, notificationId=$notificationId, intId=$intId")
42
+
43
+ createNotificationChannel(channelId)
44
+
45
+ val collapsedView = RemoteViewsGenerator.generateCollapsed(context, voltraPayload)
46
+ val expandedView = RemoteViewsGenerator.generateExpanded(context, voltraPayload)
47
+
48
+ Log.d(TAG, "Generated views: collapsed=${collapsedView != null}, expanded=${expandedView != null}")
49
+
50
+ val notification =
51
+ NotificationCompat
52
+ .Builder(context, channelId)
53
+ .setSmallIcon(getSmallIcon(voltraPayload.smallIcon))
54
+ .setOngoing(true)
55
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
56
+ .apply {
57
+ collapsedView?.let { setCustomContentView(it) }
58
+ expandedView?.let { setCustomBigContentView(it) }
59
+ }.build()
60
+
61
+ notificationManager.notify(intId, notification)
62
+ activeNotifications[notificationId] = intId
63
+
64
+ Log.d(TAG, "Notification posted. Active notifications: ${activeNotifications.keys}")
65
+
66
+ notificationId
67
+ }
68
+
69
+ suspend fun updateLiveUpdate(
70
+ notificationId: String,
71
+ payload: String,
72
+ ) = withContext(Dispatchers.Default) {
73
+ Log.d(TAG, "updateLiveUpdate called with notificationId=$notificationId")
74
+ Log.d(TAG, "Active notifications: ${activeNotifications.keys}")
75
+
76
+ val intId = activeNotifications[notificationId]
77
+ if (intId == null) {
78
+ Log.e(TAG, "Notification $notificationId not found in activeNotifications!")
79
+ return@withContext
80
+ }
81
+
82
+ Log.d(TAG, "Found intId=$intId for notificationId=$notificationId")
83
+
84
+ val voltraPayload = VoltraPayloadParser.parse(payload)
85
+ val channelId = voltraPayload.channelId ?: "voltra_live_updates"
86
+
87
+ val collapsedView = RemoteViewsGenerator.generateCollapsed(context, voltraPayload)
88
+ val expandedView = RemoteViewsGenerator.generateExpanded(context, voltraPayload)
89
+
90
+ Log.d(TAG, "Update generated views: collapsed=${collapsedView != null}, expanded=${expandedView != null}")
91
+
92
+ val notification =
93
+ NotificationCompat
94
+ .Builder(context, channelId)
95
+ .setSmallIcon(getSmallIcon(voltraPayload.smallIcon))
96
+ .setOngoing(true)
97
+ .setOnlyAlertOnce(true) // Don't make sound/vibration on updates
98
+ .setWhen(System.currentTimeMillis()) // Force timestamp update
99
+ .setShowWhen(false) // But don't show the time
100
+ .apply {
101
+ collapsedView?.let { setCustomContentView(it) }
102
+ expandedView?.let { setCustomBigContentView(it) }
103
+ }.build()
104
+
105
+ // Force notification flags to allow updates
106
+ notification.flags = notification.flags or android.app.Notification.FLAG_ONGOING_EVENT
107
+
108
+ notificationManager.notify(intId, notification)
109
+ Log.d(TAG, "Notification updated successfully")
110
+ }
111
+
112
+ fun stopLiveUpdate(notificationId: String) {
113
+ Log.d(TAG, "stopLiveUpdate called with notificationId=$notificationId")
114
+ activeNotifications.remove(notificationId)?.let { intId ->
115
+ notificationManager.cancel(intId)
116
+ Log.d(TAG, "Notification cancelled")
117
+ }
118
+ }
119
+
120
+ fun isLiveUpdateActive(updateName: String): Boolean = activeNotifications.containsKey(updateName)
121
+
122
+ fun endAllLiveUpdates() {
123
+ Log.d(TAG, "endAllLiveUpdates called")
124
+ activeNotifications.forEach { (_, intId) ->
125
+ notificationManager.cancel(intId)
126
+ }
127
+ activeNotifications.clear()
128
+ }
129
+
130
+ private fun createNotificationChannel(channelId: String) {
131
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
132
+ val channel =
133
+ NotificationChannel(
134
+ channelId,
135
+ "Voltra Live Updates",
136
+ NotificationManager.IMPORTANCE_DEFAULT,
137
+ ).apply {
138
+ description = "Live update notifications from Voltra"
139
+ }
140
+ notificationManager.createNotificationChannel(channel)
141
+ Log.d(TAG, "Notification channel created: $channelId")
142
+ }
143
+ }
144
+
145
+ private fun getSmallIcon(iconName: String?): Int {
146
+ if (iconName != null) {
147
+ val resId =
148
+ context.resources.getIdentifier(
149
+ iconName,
150
+ "drawable",
151
+ context.packageName,
152
+ )
153
+ if (resId != 0) return resId
154
+ }
155
+ return context.applicationInfo.icon
156
+ }
157
+ }