@syra.fm/sdk 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/lib/commonjs/client.js +268 -0
  2. package/lib/commonjs/client.js.map +1 -0
  3. package/lib/commonjs/errors.js +22 -0
  4. package/lib/commonjs/errors.js.map +1 -0
  5. package/lib/commonjs/index.js +63 -0
  6. package/lib/commonjs/index.js.map +1 -0
  7. package/lib/commonjs/index.native.js +28 -0
  8. package/lib/commonjs/index.native.js.map +1 -0
  9. package/lib/commonjs/live/assets/icons/spaces-icon.js +42 -0
  10. package/lib/commonjs/live/assets/icons/spaces-icon.js.map +1 -0
  11. package/lib/commonjs/live/assets/icons/syra-icon.js +43 -0
  12. package/lib/commonjs/live/assets/icons/syra-icon.js.map +1 -0
  13. package/lib/commonjs/live/components/AnimatedPulse.js +38 -0
  14. package/lib/commonjs/live/components/AnimatedPulse.js.map +1 -0
  15. package/lib/commonjs/live/components/AnimatedSpeakerRing.js +90 -0
  16. package/lib/commonjs/live/components/AnimatedSpeakerRing.js.map +1 -0
  17. package/lib/commonjs/live/components/CreateRoomSheet.js +688 -0
  18. package/lib/commonjs/live/components/CreateRoomSheet.js.map +1 -0
  19. package/lib/commonjs/live/components/InsightsPanel.js +333 -0
  20. package/lib/commonjs/live/components/InsightsPanel.js.map +1 -0
  21. package/lib/commonjs/live/components/LiveRoomSheet.js +1195 -0
  22. package/lib/commonjs/live/components/LiveRoomSheet.js.map +1 -0
  23. package/lib/commonjs/live/components/MiniRoomBar.js +161 -0
  24. package/lib/commonjs/live/components/MiniRoomBar.js.map +1 -0
  25. package/lib/commonjs/live/components/PanelHeader.js +57 -0
  26. package/lib/commonjs/live/components/PanelHeader.js.map +1 -0
  27. package/lib/commonjs/live/components/PodcastStreamPicker.js +1190 -0
  28. package/lib/commonjs/live/components/PodcastStreamPicker.js.map +1 -0
  29. package/lib/commonjs/live/components/RecordingCard.js +192 -0
  30. package/lib/commonjs/live/components/RecordingCard.js.map +1 -0
  31. package/lib/commonjs/live/components/RecordingsPanel.js +304 -0
  32. package/lib/commonjs/live/components/RecordingsPanel.js.map +1 -0
  33. package/lib/commonjs/live/components/RoomCard.js +553 -0
  34. package/lib/commonjs/live/components/RoomCard.js.map +1 -0
  35. package/lib/commonjs/live/components/StreamConfigModal.js +656 -0
  36. package/lib/commonjs/live/components/StreamConfigModal.js.map +1 -0
  37. package/lib/commonjs/live/components/StreamConfigPanel.js +822 -0
  38. package/lib/commonjs/live/components/StreamConfigPanel.js.map +1 -0
  39. package/lib/commonjs/live/context/LiveConfigContext.js +46 -0
  40. package/lib/commonjs/live/context/LiveConfigContext.js.map +1 -0
  41. package/lib/commonjs/live/context/LiveRoomContext.js +195 -0
  42. package/lib/commonjs/live/context/LiveRoomContext.js.map +1 -0
  43. package/lib/commonjs/live/hooks/useActiveSpeakers.js +35 -0
  44. package/lib/commonjs/live/hooks/useActiveSpeakers.js.map +1 -0
  45. package/lib/commonjs/live/hooks/useRoomAudio.js +129 -0
  46. package/lib/commonjs/live/hooks/useRoomAudio.js.map +1 -0
  47. package/lib/commonjs/live/hooks/useRoomConnection.js +177 -0
  48. package/lib/commonjs/live/hooks/useRoomConnection.js.map +1 -0
  49. package/lib/commonjs/live/hooks/useRoomManager.js +37 -0
  50. package/lib/commonjs/live/hooks/useRoomManager.js.map +1 -0
  51. package/lib/commonjs/live/hooks/useRoomUsers.js +52 -0
  52. package/lib/commonjs/live/hooks/useRoomUsers.js.map +1 -0
  53. package/lib/commonjs/live/index.js +310 -0
  54. package/lib/commonjs/live/index.js.map +1 -0
  55. package/lib/commonjs/live/services/livekitService.js +20 -0
  56. package/lib/commonjs/live/services/livekitService.js.map +1 -0
  57. package/lib/commonjs/live/services/spaceSocketService.js +181 -0
  58. package/lib/commonjs/live/services/spaceSocketService.js.map +1 -0
  59. package/lib/commonjs/live/services/spacesService.js +642 -0
  60. package/lib/commonjs/live/services/spacesService.js.map +1 -0
  61. package/lib/commonjs/live/types.js +6 -0
  62. package/lib/commonjs/live/types.js.map +1 -0
  63. package/lib/commonjs/live/validation.js +238 -0
  64. package/lib/commonjs/live/validation.js.map +1 -0
  65. package/lib/commonjs/package.json +1 -0
  66. package/{dist/cjs → lib/commonjs}/schema.js +55 -47
  67. package/lib/commonjs/schema.js.map +1 -0
  68. package/lib/module/client.js +264 -0
  69. package/lib/module/client.js.map +1 -0
  70. package/lib/module/errors.js +17 -0
  71. package/lib/module/errors.js.map +1 -0
  72. package/lib/module/index.js +6 -0
  73. package/lib/module/index.js.map +1 -0
  74. package/lib/module/index.native.js +5 -0
  75. package/lib/module/index.native.js.map +1 -0
  76. package/lib/module/live/assets/icons/spaces-icon.js +34 -0
  77. package/lib/module/live/assets/icons/spaces-icon.js.map +1 -0
  78. package/lib/module/live/assets/icons/syra-icon.js +36 -0
  79. package/lib/module/live/assets/icons/syra-icon.js.map +1 -0
  80. package/lib/module/live/components/AnimatedPulse.js +33 -0
  81. package/lib/module/live/components/AnimatedPulse.js.map +1 -0
  82. package/lib/module/live/components/AnimatedSpeakerRing.js +85 -0
  83. package/lib/module/live/components/AnimatedSpeakerRing.js.map +1 -0
  84. package/lib/module/live/components/CreateRoomSheet.js +682 -0
  85. package/lib/module/live/components/CreateRoomSheet.js.map +1 -0
  86. package/lib/module/live/components/InsightsPanel.js +327 -0
  87. package/lib/module/live/components/InsightsPanel.js.map +1 -0
  88. package/lib/module/live/components/LiveRoomSheet.js +1189 -0
  89. package/lib/module/live/components/LiveRoomSheet.js.map +1 -0
  90. package/lib/module/live/components/MiniRoomBar.js +154 -0
  91. package/lib/module/live/components/MiniRoomBar.js.map +1 -0
  92. package/lib/module/live/components/PanelHeader.js +52 -0
  93. package/lib/module/live/components/PanelHeader.js.map +1 -0
  94. package/lib/module/live/components/PodcastStreamPicker.js +1183 -0
  95. package/lib/module/live/components/PodcastStreamPicker.js.map +1 -0
  96. package/lib/module/live/components/RecordingCard.js +187 -0
  97. package/lib/module/live/components/RecordingCard.js.map +1 -0
  98. package/lib/module/live/components/RecordingsPanel.js +298 -0
  99. package/lib/module/live/components/RecordingsPanel.js.map +1 -0
  100. package/lib/module/live/components/RoomCard.js +548 -0
  101. package/lib/module/live/components/RoomCard.js.map +1 -0
  102. package/lib/module/live/components/StreamConfigModal.js +650 -0
  103. package/lib/module/live/components/StreamConfigModal.js.map +1 -0
  104. package/lib/module/live/components/StreamConfigPanel.js +816 -0
  105. package/lib/module/live/components/StreamConfigPanel.js.map +1 -0
  106. package/lib/module/live/context/LiveConfigContext.js +40 -0
  107. package/lib/module/live/context/LiveConfigContext.js.map +1 -0
  108. package/lib/module/live/context/LiveRoomContext.js +189 -0
  109. package/lib/module/live/context/LiveRoomContext.js.map +1 -0
  110. package/lib/module/live/hooks/useActiveSpeakers.js +31 -0
  111. package/lib/module/live/hooks/useActiveSpeakers.js.map +1 -0
  112. package/lib/module/live/hooks/useRoomAudio.js +125 -0
  113. package/lib/module/live/hooks/useRoomAudio.js.map +1 -0
  114. package/lib/module/live/hooks/useRoomConnection.js +173 -0
  115. package/lib/module/live/hooks/useRoomConnection.js.map +1 -0
  116. package/lib/module/live/hooks/useRoomManager.js +32 -0
  117. package/lib/module/live/hooks/useRoomManager.js.map +1 -0
  118. package/lib/module/live/hooks/useRoomUsers.js +46 -0
  119. package/lib/module/live/hooks/useRoomUsers.js.map +1 -0
  120. package/lib/module/live/index.js +38 -0
  121. package/lib/module/live/index.js.map +1 -0
  122. package/lib/module/live/services/livekitService.js +16 -0
  123. package/lib/module/live/services/livekitService.js.map +1 -0
  124. package/lib/module/live/services/spaceSocketService.js +176 -0
  125. package/lib/module/live/services/spaceSocketService.js.map +1 -0
  126. package/lib/module/live/services/spacesService.js +639 -0
  127. package/lib/module/live/services/spacesService.js.map +1 -0
  128. package/lib/module/live/types.js +4 -0
  129. package/lib/module/live/types.js.map +1 -0
  130. package/lib/module/live/validation.js +229 -0
  131. package/lib/module/live/validation.js.map +1 -0
  132. package/lib/module/package.json +1 -0
  133. package/{dist/esm → lib/module}/schema.js +47 -39
  134. package/lib/module/schema.js.map +1 -0
  135. package/{dist/types → lib/typescript/commonjs}/client.d.ts +1 -0
  136. package/lib/typescript/commonjs/client.d.ts.map +1 -0
  137. package/{dist/types → lib/typescript/commonjs}/errors.d.ts +1 -0
  138. package/lib/typescript/commonjs/errors.d.ts.map +1 -0
  139. package/{dist/types → lib/typescript/commonjs}/index.d.ts +1 -0
  140. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/index.native.d.ts +3 -0
  142. package/lib/typescript/commonjs/index.native.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/live/assets/icons/spaces-icon.d.ts +13 -0
  144. package/lib/typescript/commonjs/live/assets/icons/spaces-icon.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/live/assets/icons/syra-icon.d.ts +13 -0
  146. package/lib/typescript/commonjs/live/assets/icons/syra-icon.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/live/components/AnimatedPulse.d.ts +8 -0
  148. package/lib/typescript/commonjs/live/components/AnimatedPulse.d.ts.map +1 -0
  149. package/lib/typescript/commonjs/live/components/AnimatedSpeakerRing.d.ts +10 -0
  150. package/lib/typescript/commonjs/live/components/AnimatedSpeakerRing.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/live/components/CreateRoomSheet.d.ts +26 -0
  152. package/lib/typescript/commonjs/live/components/CreateRoomSheet.d.ts.map +1 -0
  153. package/lib/typescript/commonjs/live/components/InsightsPanel.d.ts +11 -0
  154. package/lib/typescript/commonjs/live/components/InsightsPanel.d.ts.map +1 -0
  155. package/lib/typescript/commonjs/live/components/LiveRoomSheet.d.ts +11 -0
  156. package/lib/typescript/commonjs/live/components/LiveRoomSheet.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/live/components/MiniRoomBar.d.ts +15 -0
  158. package/lib/typescript/commonjs/live/components/MiniRoomBar.d.ts.map +1 -0
  159. package/lib/typescript/commonjs/live/components/PanelHeader.d.ts +10 -0
  160. package/lib/typescript/commonjs/live/components/PanelHeader.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/live/components/PodcastStreamPicker.d.ts +54 -0
  162. package/lib/typescript/commonjs/live/components/PodcastStreamPicker.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/live/components/RecordingCard.d.ts +11 -0
  164. package/lib/typescript/commonjs/live/components/RecordingCard.d.ts.map +1 -0
  165. package/lib/typescript/commonjs/live/components/RecordingsPanel.d.ts +12 -0
  166. package/lib/typescript/commonjs/live/components/RecordingsPanel.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/live/components/RoomCard.d.ts +38 -0
  168. package/lib/typescript/commonjs/live/components/RoomCard.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/live/components/StreamConfigModal.d.ts +11 -0
  170. package/lib/typescript/commonjs/live/components/StreamConfigModal.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/live/components/StreamConfigPanel.d.ts +13 -0
  172. package/lib/typescript/commonjs/live/components/StreamConfigPanel.d.ts.map +1 -0
  173. package/lib/typescript/commonjs/live/context/LiveConfigContext.d.ts +78 -0
  174. package/lib/typescript/commonjs/live/context/LiveConfigContext.d.ts.map +1 -0
  175. package/lib/typescript/commonjs/live/context/LiveRoomContext.d.ts +12 -0
  176. package/lib/typescript/commonjs/live/context/LiveRoomContext.d.ts.map +1 -0
  177. package/lib/typescript/commonjs/live/hooks/useActiveSpeakers.d.ts +3 -0
  178. package/lib/typescript/commonjs/live/hooks/useActiveSpeakers.d.ts.map +1 -0
  179. package/lib/typescript/commonjs/live/hooks/useRoomAudio.d.ts +16 -0
  180. package/lib/typescript/commonjs/live/hooks/useRoomAudio.d.ts.map +1 -0
  181. package/lib/typescript/commonjs/live/hooks/useRoomConnection.d.ts +29 -0
  182. package/lib/typescript/commonjs/live/hooks/useRoomConnection.d.ts.map +1 -0
  183. package/lib/typescript/commonjs/live/hooks/useRoomManager.d.ts +11 -0
  184. package/lib/typescript/commonjs/live/hooks/useRoomManager.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/live/hooks/useRoomUsers.d.ts +5 -0
  186. package/lib/typescript/commonjs/live/hooks/useRoomUsers.d.ts.map +1 -0
  187. package/lib/typescript/commonjs/live/index.d.ts +24 -0
  188. package/lib/typescript/commonjs/live/index.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/live/services/livekitService.d.ts +7 -0
  190. package/lib/typescript/commonjs/live/services/livekitService.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/live/services/spaceSocketService.d.ts +69 -0
  192. package/lib/typescript/commonjs/live/services/spaceSocketService.d.ts.map +1 -0
  193. package/lib/typescript/commonjs/live/services/spacesService.d.ts +181 -0
  194. package/lib/typescript/commonjs/live/services/spacesService.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/live/types.d.ts +100 -0
  196. package/lib/typescript/commonjs/live/types.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/live/validation.d.ts +658 -0
  198. package/lib/typescript/commonjs/live/validation.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/package.json +1 -0
  200. package/{dist/types → lib/typescript/commonjs}/schema.d.ts +1 -0
  201. package/lib/typescript/commonjs/schema.d.ts.map +1 -0
  202. package/lib/typescript/module/client.d.ts +141 -0
  203. package/lib/typescript/module/client.d.ts.map +1 -0
  204. package/lib/typescript/module/errors.d.ts +9 -0
  205. package/lib/typescript/module/errors.d.ts.map +1 -0
  206. package/lib/typescript/module/index.d.ts +6 -0
  207. package/lib/typescript/module/index.d.ts.map +1 -0
  208. package/lib/typescript/module/index.native.d.ts +3 -0
  209. package/lib/typescript/module/index.native.d.ts.map +1 -0
  210. package/lib/typescript/module/live/assets/icons/spaces-icon.d.ts +13 -0
  211. package/lib/typescript/module/live/assets/icons/spaces-icon.d.ts.map +1 -0
  212. package/lib/typescript/module/live/assets/icons/syra-icon.d.ts +13 -0
  213. package/lib/typescript/module/live/assets/icons/syra-icon.d.ts.map +1 -0
  214. package/lib/typescript/module/live/components/AnimatedPulse.d.ts +8 -0
  215. package/lib/typescript/module/live/components/AnimatedPulse.d.ts.map +1 -0
  216. package/lib/typescript/module/live/components/AnimatedSpeakerRing.d.ts +10 -0
  217. package/lib/typescript/module/live/components/AnimatedSpeakerRing.d.ts.map +1 -0
  218. package/lib/typescript/module/live/components/CreateRoomSheet.d.ts +26 -0
  219. package/lib/typescript/module/live/components/CreateRoomSheet.d.ts.map +1 -0
  220. package/lib/typescript/module/live/components/InsightsPanel.d.ts +11 -0
  221. package/lib/typescript/module/live/components/InsightsPanel.d.ts.map +1 -0
  222. package/lib/typescript/module/live/components/LiveRoomSheet.d.ts +11 -0
  223. package/lib/typescript/module/live/components/LiveRoomSheet.d.ts.map +1 -0
  224. package/lib/typescript/module/live/components/MiniRoomBar.d.ts +15 -0
  225. package/lib/typescript/module/live/components/MiniRoomBar.d.ts.map +1 -0
  226. package/lib/typescript/module/live/components/PanelHeader.d.ts +10 -0
  227. package/lib/typescript/module/live/components/PanelHeader.d.ts.map +1 -0
  228. package/lib/typescript/module/live/components/PodcastStreamPicker.d.ts +54 -0
  229. package/lib/typescript/module/live/components/PodcastStreamPicker.d.ts.map +1 -0
  230. package/lib/typescript/module/live/components/RecordingCard.d.ts +11 -0
  231. package/lib/typescript/module/live/components/RecordingCard.d.ts.map +1 -0
  232. package/lib/typescript/module/live/components/RecordingsPanel.d.ts +12 -0
  233. package/lib/typescript/module/live/components/RecordingsPanel.d.ts.map +1 -0
  234. package/lib/typescript/module/live/components/RoomCard.d.ts +38 -0
  235. package/lib/typescript/module/live/components/RoomCard.d.ts.map +1 -0
  236. package/lib/typescript/module/live/components/StreamConfigModal.d.ts +11 -0
  237. package/lib/typescript/module/live/components/StreamConfigModal.d.ts.map +1 -0
  238. package/lib/typescript/module/live/components/StreamConfigPanel.d.ts +13 -0
  239. package/lib/typescript/module/live/components/StreamConfigPanel.d.ts.map +1 -0
  240. package/lib/typescript/module/live/context/LiveConfigContext.d.ts +78 -0
  241. package/lib/typescript/module/live/context/LiveConfigContext.d.ts.map +1 -0
  242. package/lib/typescript/module/live/context/LiveRoomContext.d.ts +12 -0
  243. package/lib/typescript/module/live/context/LiveRoomContext.d.ts.map +1 -0
  244. package/lib/typescript/module/live/hooks/useActiveSpeakers.d.ts +3 -0
  245. package/lib/typescript/module/live/hooks/useActiveSpeakers.d.ts.map +1 -0
  246. package/lib/typescript/module/live/hooks/useRoomAudio.d.ts +16 -0
  247. package/lib/typescript/module/live/hooks/useRoomAudio.d.ts.map +1 -0
  248. package/lib/typescript/module/live/hooks/useRoomConnection.d.ts +29 -0
  249. package/lib/typescript/module/live/hooks/useRoomConnection.d.ts.map +1 -0
  250. package/lib/typescript/module/live/hooks/useRoomManager.d.ts +11 -0
  251. package/lib/typescript/module/live/hooks/useRoomManager.d.ts.map +1 -0
  252. package/lib/typescript/module/live/hooks/useRoomUsers.d.ts +5 -0
  253. package/lib/typescript/module/live/hooks/useRoomUsers.d.ts.map +1 -0
  254. package/lib/typescript/module/live/index.d.ts +24 -0
  255. package/lib/typescript/module/live/index.d.ts.map +1 -0
  256. package/lib/typescript/module/live/services/livekitService.d.ts +7 -0
  257. package/lib/typescript/module/live/services/livekitService.d.ts.map +1 -0
  258. package/lib/typescript/module/live/services/spaceSocketService.d.ts +69 -0
  259. package/lib/typescript/module/live/services/spaceSocketService.d.ts.map +1 -0
  260. package/lib/typescript/module/live/services/spacesService.d.ts +181 -0
  261. package/lib/typescript/module/live/services/spacesService.d.ts.map +1 -0
  262. package/lib/typescript/module/live/types.d.ts +100 -0
  263. package/lib/typescript/module/live/types.d.ts.map +1 -0
  264. package/lib/typescript/module/live/validation.d.ts +658 -0
  265. package/lib/typescript/module/live/validation.d.ts.map +1 -0
  266. package/lib/typescript/module/package.json +1 -0
  267. package/lib/typescript/module/schema.d.ts +1072 -0
  268. package/lib/typescript/module/schema.d.ts.map +1 -0
  269. package/package.json +133 -21
  270. package/src/index.native.ts +2 -0
  271. package/src/live/assets/icons/spaces-icon.tsx +15 -0
  272. package/src/live/assets/icons/syra-icon.tsx +13 -0
  273. package/src/live/assets/sounds/intro.mp3 +0 -0
  274. package/src/live/components/AnimatedPulse.tsx +52 -0
  275. package/src/live/components/AnimatedSpeakerRing.tsx +101 -0
  276. package/src/live/components/CreateRoomSheet.tsx +654 -0
  277. package/src/live/components/InsightsPanel.tsx +202 -0
  278. package/src/live/components/LiveRoomSheet.tsx +969 -0
  279. package/src/live/components/MiniRoomBar.tsx +166 -0
  280. package/src/live/components/PanelHeader.tsx +36 -0
  281. package/src/live/components/PodcastStreamPicker.tsx +1155 -0
  282. package/src/live/components/RecordingCard.tsx +154 -0
  283. package/src/live/components/RecordingsPanel.tsx +251 -0
  284. package/src/live/components/RoomCard.tsx +494 -0
  285. package/src/live/components/StreamConfigModal.tsx +600 -0
  286. package/src/live/components/StreamConfigPanel.tsx +729 -0
  287. package/src/live/context/LiveConfigContext.tsx +96 -0
  288. package/src/live/context/LiveRoomContext.tsx +235 -0
  289. package/src/live/hooks/useActiveSpeakers.ts +39 -0
  290. package/src/live/hooks/useRoomAudio.ts +103 -0
  291. package/src/live/hooks/useRoomConnection.ts +162 -0
  292. package/src/live/hooks/useRoomManager.ts +17 -0
  293. package/src/live/hooks/useRoomUsers.ts +52 -0
  294. package/src/live/index.ts +92 -0
  295. package/src/live/services/livekitService.ts +11 -0
  296. package/src/live/services/spaceSocketService.ts +136 -0
  297. package/src/live/services/spacesService.ts +692 -0
  298. package/src/live/types.ts +119 -0
  299. package/src/live/validation.ts +279 -0
  300. package/dist/cjs/client.js +0 -244
  301. package/dist/cjs/errors.js +0 -16
  302. package/dist/cjs/index.js +0 -15
  303. package/dist/cjs/package.json +0 -3
  304. package/dist/esm/client.js +0 -240
  305. package/dist/esm/errors.js +0 -12
  306. package/dist/esm/index.js +0 -3
  307. package/dist/esm/package.json +0 -3
@@ -0,0 +1,1189 @@
1
+ "use strict";
2
+
3
+ import React, { useCallback, useEffect, useState, useMemo } from 'react';
4
+ import { View, Text, Image, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
5
+ import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
6
+ import { useAuth } from '@oxyhq/services';
7
+ import { useLiveConfig } from "../context/LiveConfigContext.js";
8
+ import { MiniRoomBar } from "./MiniRoomBar.js";
9
+ import { StreamConfigPanel } from "./StreamConfigPanel.js";
10
+ import { InsightsPanel } from "./InsightsPanel.js";
11
+ import { PanelHeader } from "./PanelHeader.js";
12
+ import { AnimatedSpeakerRing } from "./AnimatedSpeakerRing.js";
13
+ import { AnimatedPulse } from "./AnimatedPulse.js";
14
+ import { useRoomConnection } from "../hooks/useRoomConnection.js";
15
+ import { useRoomAudio } from "../hooks/useRoomAudio.js";
16
+ import { useActiveSpeakers } from "../hooks/useActiveSpeakers.js";
17
+ import { useRoomUsers, getDisplayName, getAvatarUrl } from "../hooks/useRoomUsers.js";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ /**
20
+ * English source copy for the podcast host-control strings added to the stream
21
+ * card. Hosts with an i18n layer inject `t`; hosts without one fall back here.
22
+ * Keys mirror the `agora.podcastStream.*` entries in the app locale files.
23
+ */
24
+ const LIVE_ROOM_STRINGS = {
25
+ 'agora.podcastStream.skipNext': 'Skip to next episode',
26
+ 'agora.podcastStream.skipped': 'Skipped to the next episode',
27
+ 'agora.podcastStream.queueEnded': 'Podcast queue finished',
28
+ 'agora.podcastStream.skipFailed': "Couldn't skip to the next episode"
29
+ };
30
+
31
+ /** Format a second count as `m:ss` (or `h:mm:ss` when hours are relevant). */
32
+ function formatClock(totalSeconds, withHours) {
33
+ const s = Math.max(0, Math.floor(totalSeconds));
34
+ const hours = Math.floor(s / 3600);
35
+ const minutes = Math.floor(s % 3600 / 60);
36
+ const secs = s % 60;
37
+ const pad = n => String(n).padStart(2, '0');
38
+ return withHours ? `${hours}:${pad(minutes)}:${pad(secs)}` : `${minutes}:${pad(secs)}`;
39
+ }
40
+ const RoleBadge = ({
41
+ role,
42
+ theme
43
+ }) => {
44
+ if (role === 'host') {
45
+ return /*#__PURE__*/_jsx(View, {
46
+ style: [styles.roleBadge, {
47
+ backgroundColor: theme.colors.primary
48
+ }],
49
+ children: /*#__PURE__*/_jsx(Text, {
50
+ style: styles.roleBadgeText,
51
+ children: "Host"
52
+ })
53
+ });
54
+ }
55
+ if (role === 'speaker') {
56
+ return /*#__PURE__*/_jsx(View, {
57
+ style: [styles.roleBadge, {
58
+ backgroundColor: theme.colors.backgroundSecondary
59
+ }],
60
+ children: /*#__PURE__*/_jsx(Text, {
61
+ style: [styles.roleBadgeText, {
62
+ color: theme.colors.text
63
+ }],
64
+ children: "Speaker"
65
+ })
66
+ });
67
+ }
68
+ return null;
69
+ };
70
+ const SpeakerTile = ({
71
+ participant,
72
+ isCurrentUser,
73
+ isSpeaking,
74
+ theme,
75
+ userProfile,
76
+ oxyServices,
77
+ AvatarComponent,
78
+ getCachedFileDownloadUrlSync
79
+ }) => {
80
+ const displayName = getDisplayName(userProfile, participant.userId, isCurrentUser);
81
+ const avatarUri = getAvatarUrl(userProfile, oxyServices, getCachedFileDownloadUrlSync);
82
+ return /*#__PURE__*/_jsxs(View, {
83
+ style: styles.speakerTile,
84
+ children: [/*#__PURE__*/_jsxs(AnimatedSpeakerRing, {
85
+ isSpeaking: isSpeaking,
86
+ isMuted: participant.isMuted,
87
+ primaryColor: theme.colors.primary,
88
+ children: [/*#__PURE__*/_jsx(AvatarComponent, {
89
+ size: 64,
90
+ source: avatarUri,
91
+ shape: "squircle"
92
+ }), participant.isMuted && /*#__PURE__*/_jsx(View, {
93
+ style: [styles.muteIndicator, {
94
+ backgroundColor: '#FF4458'
95
+ }],
96
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
97
+ name: "microphone-off",
98
+ size: 12,
99
+ color: "#FFFFFF"
100
+ })
101
+ })]
102
+ }), /*#__PURE__*/_jsx(Text, {
103
+ style: [styles.speakerName, {
104
+ color: theme.colors.text
105
+ }],
106
+ numberOfLines: 1,
107
+ children: displayName
108
+ }), /*#__PURE__*/_jsx(RoleBadge, {
109
+ role: participant.role,
110
+ theme: theme
111
+ })]
112
+ });
113
+ };
114
+ const ListenerAvatar = ({
115
+ participant,
116
+ userProfile,
117
+ oxyServices,
118
+ AvatarComponent,
119
+ getCachedFileDownloadUrlSync
120
+ }) => {
121
+ return /*#__PURE__*/_jsx(View, {
122
+ style: styles.listenerItem,
123
+ children: /*#__PURE__*/_jsx(AvatarComponent, {
124
+ size: 40,
125
+ source: getAvatarUrl(userProfile, oxyServices, getCachedFileDownloadUrlSync),
126
+ shape: "squircle"
127
+ })
128
+ });
129
+ };
130
+ const ConnectedSpeakerTile = ({
131
+ participant,
132
+ isCurrentUser,
133
+ isSpeaking,
134
+ theme,
135
+ oxyServices,
136
+ AvatarComponent,
137
+ getCachedFileDownloadUrlSync,
138
+ useUserById
139
+ }) => {
140
+ const userProfile = useUserById(participant.userId);
141
+ return /*#__PURE__*/_jsx(SpeakerTile, {
142
+ participant: participant,
143
+ isCurrentUser: isCurrentUser,
144
+ isSpeaking: isSpeaking,
145
+ theme: theme,
146
+ userProfile: userProfile,
147
+ oxyServices: oxyServices,
148
+ AvatarComponent: AvatarComponent,
149
+ getCachedFileDownloadUrlSync: getCachedFileDownloadUrlSync
150
+ });
151
+ };
152
+ const ConnectedListenerAvatar = ({
153
+ participant,
154
+ oxyServices,
155
+ AvatarComponent,
156
+ getCachedFileDownloadUrlSync,
157
+ useUserById
158
+ }) => {
159
+ const userProfile = useUserById(participant.userId);
160
+ return /*#__PURE__*/_jsx(ListenerAvatar, {
161
+ participant: participant,
162
+ userProfile: userProfile,
163
+ oxyServices: oxyServices,
164
+ AvatarComponent: AvatarComponent,
165
+ getCachedFileDownloadUrlSync: getCachedFileDownloadUrlSync
166
+ });
167
+ };
168
+ const ConnectedRequestRow = ({
169
+ request,
170
+ theme,
171
+ oxyServices,
172
+ onApprove,
173
+ onDeny,
174
+ AvatarComponent,
175
+ getCachedFileDownloadUrlSync,
176
+ useUserById
177
+ }) => {
178
+ const userProfile = useUserById(request.userId);
179
+ const displayName = getDisplayName(userProfile, request.userId, false);
180
+ const avatarUri = getAvatarUrl(userProfile, oxyServices, getCachedFileDownloadUrlSync);
181
+ return /*#__PURE__*/_jsxs(View, {
182
+ style: [styles.requestRow, {
183
+ backgroundColor: `${theme.colors.card}80`,
184
+ borderColor: theme.colors.border
185
+ }],
186
+ children: [/*#__PURE__*/_jsx(AvatarComponent, {
187
+ size: 36,
188
+ source: avatarUri,
189
+ shape: "squircle"
190
+ }), /*#__PURE__*/_jsx(Text, {
191
+ style: [styles.requestName, {
192
+ color: theme.colors.text
193
+ }],
194
+ numberOfLines: 1,
195
+ children: displayName
196
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
197
+ onPress: () => onApprove(request.userId),
198
+ style: [styles.approveBtn, {
199
+ backgroundColor: theme.colors.primary
200
+ }],
201
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
202
+ name: "check",
203
+ size: 18,
204
+ color: "#FFFFFF"
205
+ })
206
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
207
+ onPress: () => onDeny(request.userId),
208
+ style: [styles.denyBtn, {
209
+ backgroundColor: theme.colors.backgroundSecondary
210
+ }],
211
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
212
+ name: "close",
213
+ size: 18,
214
+ color: theme.colors.text
215
+ })
216
+ })]
217
+ });
218
+ };
219
+ export function LiveRoomSheet({
220
+ roomId,
221
+ isExpanded,
222
+ onCollapse,
223
+ onExpand,
224
+ onLeave
225
+ }) {
226
+ const {
227
+ useTheme,
228
+ useUserById,
229
+ AvatarComponent,
230
+ roomsService,
231
+ toast,
232
+ getCachedFileDownloadUrl,
233
+ getCachedFileDownloadUrlSync,
234
+ onRoomChanged,
235
+ t
236
+ } = useLiveConfig();
237
+ const theme = useTheme();
238
+ const {
239
+ user,
240
+ oxyServices
241
+ } = useAuth();
242
+ const [room, setRoom] = useState(null);
243
+ const tr = useCallback(key => t ? t(key) : LIVE_ROOM_STRINGS[key] ?? key, [t]);
244
+ useEffect(() => {
245
+ if (roomId) {
246
+ roomsService.getRoom(roomId).then(setRoom);
247
+ }
248
+ }, [roomId]);
249
+ const {
250
+ isConnected,
251
+ participants,
252
+ myRole,
253
+ isMuted,
254
+ speakerRequests,
255
+ activeStream,
256
+ isRecording,
257
+ join,
258
+ leave,
259
+ toggleMute,
260
+ requestToSpeak,
261
+ approveSpeaker,
262
+ denySpeaker,
263
+ isRoomEnded
264
+ } = useRoomConnection({
265
+ roomId,
266
+ enabled: !!roomId
267
+ });
268
+ const isRoomLive = room?.status === 'live';
269
+ const {
270
+ isLiveKitConnected,
271
+ micPermissionDenied,
272
+ livekitRoom
273
+ } = useRoomAudio({
274
+ roomId,
275
+ isSpeaker: myRole === 'speaker' || myRole === 'host',
276
+ isMuted,
277
+ isConnected: isConnected && isRoomLive
278
+ });
279
+ const activeSpeakerIds = useActiveSpeakers(livekitRoom);
280
+ useEffect(() => {
281
+ if (isConnected && roomId) {
282
+ join();
283
+ }
284
+ }, [isConnected, roomId, join]);
285
+ useEffect(() => {
286
+ if (isRoomEnded) {
287
+ toast('Room ended');
288
+ leave();
289
+ onLeave();
290
+ }
291
+ }, [isRoomEnded]);
292
+ const handleLeave = () => {
293
+ leave();
294
+ onLeave();
295
+ };
296
+ const handleStopRoom = async () => {
297
+ if (!roomId) return;
298
+ const success = await roomsService.stopRoom(roomId);
299
+ if (success) {
300
+ onRoomChanged?.(roomId);
301
+ leave();
302
+ onLeave();
303
+ } else {
304
+ toast.error('Failed to stop session');
305
+ }
306
+ };
307
+ const handleDeleteRoom = async () => {
308
+ if (!roomId) return;
309
+ const success = await roomsService.deleteRoom(roomId);
310
+ if (success) {
311
+ onRoomChanged?.(roomId);
312
+ leave();
313
+ onLeave();
314
+ toast.success('Room deleted');
315
+ } else {
316
+ toast.error('Failed to delete room');
317
+ }
318
+ };
319
+ const [startingRoom, setStartingRoom] = useState(false);
320
+ const handleStartRoom = async () => {
321
+ if (!roomId || startingRoom) return;
322
+ setStartingRoom(true);
323
+ try {
324
+ const success = await roomsService.startRoom(roomId);
325
+ if (success) {
326
+ const updated = await roomsService.getRoom(roomId);
327
+ if (updated) setRoom(updated);
328
+ onRoomChanged?.(roomId);
329
+ toast.success('Room is now live!');
330
+ } else {
331
+ toast.error('Failed to start room');
332
+ }
333
+ } catch {
334
+ toast.error('Failed to start room');
335
+ } finally {
336
+ setStartingRoom(false);
337
+ }
338
+ };
339
+ const handleStartRecording = async () => {
340
+ if (!roomId) return;
341
+ const success = await roomsService.startRecording(roomId);
342
+ if (success) {
343
+ toast.success('Recording started');
344
+ } else {
345
+ toast.error('Failed to start recording');
346
+ }
347
+ };
348
+ const handleStopRecording = async () => {
349
+ if (!roomId) return;
350
+ const success = await roomsService.stopRecording(roomId);
351
+ if (success) {
352
+ toast.success('Recording saved');
353
+ } else {
354
+ toast.error('Failed to stop recording');
355
+ }
356
+ };
357
+ const [activePanel, setActivePanel] = useState(null);
358
+ const [streamLoading, setStreamLoading] = useState(false);
359
+ const effectiveStream = activeStream ?? (room?.streamTitle || room?.activeStreamUrl ? {
360
+ title: room.streamTitle ?? undefined,
361
+ image: room.streamImage ?? undefined,
362
+ description: room.streamDescription ?? undefined,
363
+ startedAt: room.streamStartedAt ?? undefined,
364
+ durationSec: room.streamDurationSec ?? undefined
365
+ } : null);
366
+ const [streamImageUrl, setStreamImageUrl] = useState(null);
367
+ useEffect(() => {
368
+ if (effectiveStream?.image) {
369
+ getCachedFileDownloadUrl(oxyServices, effectiveStream.image).then(setStreamImageUrl);
370
+ } else {
371
+ setStreamImageUrl(null);
372
+ }
373
+ }, [effectiveStream?.image, oxyServices]);
374
+
375
+ // Stream progress — only for length-known streams (e.g. podcast episodes).
376
+ const streamStartedAt = effectiveStream?.startedAt;
377
+ const streamDurationSec = effectiveStream?.durationSec ?? 0;
378
+ const hasProgress = !!streamStartedAt && streamDurationSec > 0;
379
+
380
+ // A lightweight 1s tick that advances the elapsed readout while a length-known
381
+ // stream plays. Runs only when there's progress to show; cleared on unmount
382
+ // and whenever the stream clears.
383
+ const [nowMs, setNowMs] = useState(() => Date.now());
384
+ useEffect(() => {
385
+ if (!hasProgress) return;
386
+ setNowMs(Date.now());
387
+ const id = setInterval(() => setNowMs(Date.now()), 1000);
388
+ return () => clearInterval(id);
389
+ }, [hasProgress]);
390
+ const elapsedSec = useMemo(() => {
391
+ if (!hasProgress || !streamStartedAt) return 0;
392
+ const startMs = new Date(streamStartedAt).getTime();
393
+ if (Number.isNaN(startMs)) return 0;
394
+ return Math.min(Math.max(Math.floor((nowMs - startMs) / 1000), 0), streamDurationSec);
395
+ }, [hasProgress, streamStartedAt, nowMs, streamDurationSec]);
396
+ const progressPct = hasProgress ? Math.min(Math.max(elapsedSec / streamDurationSec, 0), 1) * 100 : 0;
397
+ const progressFillStyle = {
398
+ backgroundColor: theme.colors.primary,
399
+ width: `${progressPct}%`
400
+ };
401
+ const withHours = streamDurationSec >= 3600;
402
+ const handleStopStream = async () => {
403
+ if (!roomId || streamLoading) return;
404
+ setStreamLoading(true);
405
+ try {
406
+ const success = await roomsService.stopStream(roomId);
407
+ if (success) {
408
+ toast.success('Stream stopped');
409
+ } else {
410
+ toast.error('Failed to stop stream');
411
+ }
412
+ } catch {
413
+ toast.error('Failed to stop stream');
414
+ } finally {
415
+ setStreamLoading(false);
416
+ }
417
+ };
418
+ const [skipLoading, setSkipLoading] = useState(false);
419
+ const handleSkipNext = async () => {
420
+ if (!roomId || skipLoading) return;
421
+ setSkipLoading(true);
422
+ try {
423
+ const result = await roomsService.skipPodcastNext(roomId);
424
+ if (!result) {
425
+ toast.error(tr('agora.podcastStream.skipFailed'));
426
+ } else {
427
+ toast.success(tr(result.ended ? 'agora.podcastStream.queueEnded' : 'agora.podcastStream.skipped'));
428
+ const updated = await roomsService.getRoom(roomId);
429
+ if (updated) setRoom(updated);
430
+ }
431
+ } catch {
432
+ toast.error(tr('agora.podcastStream.skipFailed'));
433
+ } finally {
434
+ setSkipLoading(false);
435
+ }
436
+ };
437
+ const participantIds = useMemo(() => participants.map(p => p.userId), [participants]);
438
+ useRoomUsers(participantIds);
439
+ const speakers = participants.filter(p => p.role === 'host' || p.role === 'speaker');
440
+ const listeners = participants.filter(p => p.role === 'listener');
441
+ const userId = user?.id;
442
+ const isHost = myRole === 'host' || !!userId && room?.host === userId;
443
+ const canSpeak = myRole === 'host' || myRole === 'speaker';
444
+ if (!isExpanded) {
445
+ return /*#__PURE__*/_jsx(MiniRoomBar, {
446
+ title: room?.title || 'Room',
447
+ participantCount: participants.length,
448
+ isMuted: isMuted,
449
+ canSpeak: canSpeak,
450
+ activeSpeakerCount: activeSpeakerIds.size,
451
+ onExpand: onExpand,
452
+ onToggleMute: toggleMute,
453
+ onLeave: handleLeave
454
+ });
455
+ }
456
+ if (activePanel === 'stream') {
457
+ return /*#__PURE__*/_jsx(StreamConfigPanel, {
458
+ roomId: roomId,
459
+ roomStatus: room?.status,
460
+ initialStreamUrl: room?.activeStreamUrl ?? undefined,
461
+ initialRtmpUrl: room?.rtmpUrl ?? undefined,
462
+ initialStreamKey: room?.rtmpStreamKey ?? undefined,
463
+ onClose: () => setActivePanel(null),
464
+ onStreamStarted: () => {
465
+ roomsService.getRoom(roomId).then(setRoom);
466
+ onRoomChanged?.(roomId);
467
+ setActivePanel(null);
468
+ }
469
+ });
470
+ }
471
+ if (activePanel === 'insights') {
472
+ return /*#__PURE__*/_jsx(InsightsPanel, {
473
+ room: room,
474
+ participants: participants,
475
+ theme: theme,
476
+ onClose: () => setActivePanel(null)
477
+ });
478
+ }
479
+ if (activePanel === 'settings') {
480
+ return /*#__PURE__*/_jsxs(View, {
481
+ style: styles.container,
482
+ children: [/*#__PURE__*/_jsx(PanelHeader, {
483
+ title: "Room Settings",
484
+ theme: theme,
485
+ onBack: () => setActivePanel(null)
486
+ }), /*#__PURE__*/_jsxs(View, {
487
+ style: styles.settingsContent,
488
+ children: [isRoomLive && /*#__PURE__*/_jsxs(View, {
489
+ style: styles.settingsItem,
490
+ children: [/*#__PURE__*/_jsx(MaterialCommunityIcons, {
491
+ name: isRecording ? 'record-circle' : 'record-circle-outline',
492
+ size: 22,
493
+ color: isRecording ? '#FF0000' : theme.colors.text
494
+ }), /*#__PURE__*/_jsxs(View, {
495
+ style: styles.settingsItemText,
496
+ children: [/*#__PURE__*/_jsx(Text, {
497
+ style: [styles.settingsItemTitle, {
498
+ color: theme.colors.text
499
+ }],
500
+ children: "Recording"
501
+ }), /*#__PURE__*/_jsx(Text, {
502
+ style: [styles.settingsItemDesc, {
503
+ color: theme.colors.textSecondary
504
+ }],
505
+ children: isRecording ? 'Currently recording (max 1h)' : 'Record room audio for replay'
506
+ })]
507
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
508
+ onPress: isRecording ? handleStopRecording : handleStartRecording,
509
+ style: [styles.recordingToggle, {
510
+ backgroundColor: isRecording ? '#FF4458' : theme.colors.primary
511
+ }],
512
+ children: /*#__PURE__*/_jsx(Text, {
513
+ style: {
514
+ color: '#FFFFFF',
515
+ fontWeight: '600',
516
+ fontSize: 13
517
+ },
518
+ children: isRecording ? 'Stop' : 'Start'
519
+ })
520
+ })]
521
+ }), /*#__PURE__*/_jsxs(TouchableOpacity, {
522
+ style: styles.settingsItem,
523
+ onPress: handleDeleteRoom,
524
+ children: [/*#__PURE__*/_jsx(MaterialCommunityIcons, {
525
+ name: "delete-outline",
526
+ size: 22,
527
+ color: "#FF4458"
528
+ }), /*#__PURE__*/_jsxs(View, {
529
+ style: styles.settingsItemText,
530
+ children: [/*#__PURE__*/_jsx(Text, {
531
+ style: [styles.settingsItemTitle, {
532
+ color: '#FF4458'
533
+ }],
534
+ children: "Delete Room"
535
+ }), /*#__PURE__*/_jsx(Text, {
536
+ style: [styles.settingsItemDesc, {
537
+ color: theme.colors.textSecondary
538
+ }],
539
+ children: "Permanently remove this room"
540
+ })]
541
+ })]
542
+ })]
543
+ })]
544
+ });
545
+ }
546
+ return /*#__PURE__*/_jsxs(View, {
547
+ style: styles.container,
548
+ children: [/*#__PURE__*/_jsxs(View, {
549
+ style: [styles.header, {
550
+ borderBottomColor: `${theme.colors.border}80`
551
+ }],
552
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
553
+ onPress: onCollapse,
554
+ style: styles.headerButton,
555
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
556
+ name: "chevron-down",
557
+ size: 24,
558
+ color: theme.colors.text
559
+ })
560
+ }), /*#__PURE__*/_jsxs(View, {
561
+ style: styles.headerCenter,
562
+ children: [isRoomLive ? /*#__PURE__*/_jsxs(View, {
563
+ style: [styles.liveBadge, {
564
+ backgroundColor: '#FF4458'
565
+ }],
566
+ children: [/*#__PURE__*/_jsx(AnimatedPulse, {}), /*#__PURE__*/_jsx(Text, {
567
+ style: styles.liveText,
568
+ children: "LIVE"
569
+ })]
570
+ }) : /*#__PURE__*/_jsx(View, {
571
+ style: [styles.liveBadge, {
572
+ backgroundColor: theme.colors.textSecondary
573
+ }],
574
+ children: /*#__PURE__*/_jsx(Text, {
575
+ style: styles.liveText,
576
+ children: "SCHEDULED"
577
+ })
578
+ }), isRecording && /*#__PURE__*/_jsxs(View, {
579
+ style: [styles.liveBadge, {
580
+ backgroundColor: '#FF0000'
581
+ }],
582
+ children: [/*#__PURE__*/_jsx(AnimatedPulse, {}), /*#__PURE__*/_jsx(Text, {
583
+ style: styles.liveText,
584
+ children: "REC"
585
+ })]
586
+ }), /*#__PURE__*/_jsxs(Text, {
587
+ style: [styles.listenerCount, {
588
+ color: theme.colors.textSecondary
589
+ }],
590
+ children: [participants.length, " in room"]
591
+ })]
592
+ }), /*#__PURE__*/_jsxs(View, {
593
+ style: styles.headerRight,
594
+ children: [isHost && isRoomLive && /*#__PURE__*/_jsx(TouchableOpacity, {
595
+ onPress: handleStopRoom,
596
+ style: styles.endButton,
597
+ children: /*#__PURE__*/_jsx(Text, {
598
+ style: styles.endButtonText,
599
+ children: "End"
600
+ })
601
+ }), isHost && !isRoomLive && room?.status === 'scheduled' && /*#__PURE__*/_jsx(TouchableOpacity, {
602
+ onPress: handleStartRoom,
603
+ disabled: startingRoom,
604
+ style: [styles.endButton, {
605
+ backgroundColor: theme.colors.primary
606
+ }],
607
+ children: /*#__PURE__*/_jsx(Text, {
608
+ style: [styles.endButtonText, {
609
+ color: '#FFFFFF'
610
+ }],
611
+ children: startingRoom ? 'Starting...' : 'Go Live'
612
+ })
613
+ })]
614
+ })]
615
+ }), /*#__PURE__*/_jsxs(View, {
616
+ style: styles.roomInfo,
617
+ children: [/*#__PURE__*/_jsx(Text, {
618
+ style: [styles.roomTitle, {
619
+ color: theme.colors.text
620
+ }],
621
+ numberOfLines: 2,
622
+ children: room?.title || 'Room'
623
+ }), room?.topic && /*#__PURE__*/_jsx(Text, {
624
+ style: [styles.roomTopic, {
625
+ color: theme.colors.textSecondary
626
+ }],
627
+ children: room.topic
628
+ })]
629
+ }), micPermissionDenied && canSpeak && /*#__PURE__*/_jsxs(View, {
630
+ style: [styles.micBanner, {
631
+ backgroundColor: '#FFF3CD',
632
+ borderColor: '#FFE69C'
633
+ }],
634
+ children: [/*#__PURE__*/_jsx(MaterialCommunityIcons, {
635
+ name: "microphone-off",
636
+ size: 18,
637
+ color: "#856404"
638
+ }), /*#__PURE__*/_jsx(Text, {
639
+ style: styles.micBannerText,
640
+ children: "Microphone access denied. Allow mic permission in your browser settings to speak."
641
+ })]
642
+ }), effectiveStream && /*#__PURE__*/_jsxs(View, {
643
+ style: [styles.streamCard, {
644
+ backgroundColor: `${theme.colors.card}80`,
645
+ borderColor: theme.colors.border
646
+ }],
647
+ children: [/*#__PURE__*/_jsxs(View, {
648
+ style: styles.streamCardRow,
649
+ children: [streamImageUrl ? /*#__PURE__*/_jsx(Image, {
650
+ source: {
651
+ uri: streamImageUrl
652
+ },
653
+ style: styles.streamCardImage
654
+ }) : /*#__PURE__*/_jsx(View, {
655
+ style: [styles.streamCardIconBox, {
656
+ backgroundColor: '#E8F5E9'
657
+ }],
658
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
659
+ name: "radio",
660
+ size: 20,
661
+ color: "#2E7D32"
662
+ })
663
+ }), /*#__PURE__*/_jsxs(View, {
664
+ style: styles.streamCardContent,
665
+ children: [/*#__PURE__*/_jsx(Text, {
666
+ style: [styles.streamCardTitle, {
667
+ color: theme.colors.text
668
+ }],
669
+ numberOfLines: 1,
670
+ children: effectiveStream.title || 'Live Stream'
671
+ }), effectiveStream.description ? /*#__PURE__*/_jsx(Text, {
672
+ style: [styles.streamCardDesc, {
673
+ color: theme.colors.textSecondary
674
+ }],
675
+ numberOfLines: 2,
676
+ children: effectiveStream.description
677
+ }) : null]
678
+ }), isHost && /*#__PURE__*/_jsxs(View, {
679
+ style: styles.streamCardActions,
680
+ children: [(room?.podcastQueue?.length ?? 0) > 0 && /*#__PURE__*/_jsx(TouchableOpacity, {
681
+ onPress: handleSkipNext,
682
+ disabled: skipLoading,
683
+ style: styles.streamCardAction,
684
+ accessibilityRole: "button",
685
+ accessibilityLabel: tr('agora.podcastStream.skipNext'),
686
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
687
+ name: "skip-next-circle",
688
+ size: 22,
689
+ color: theme.colors.primary
690
+ })
691
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
692
+ onPress: handleStopStream,
693
+ disabled: streamLoading,
694
+ style: styles.streamCardAction,
695
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
696
+ name: "close-circle",
697
+ size: 22,
698
+ color: "#C62828"
699
+ })
700
+ })]
701
+ })]
702
+ }), hasProgress && /*#__PURE__*/_jsxs(View, {
703
+ style: styles.streamProgress,
704
+ children: [/*#__PURE__*/_jsx(View, {
705
+ style: [styles.progressTrack, {
706
+ backgroundColor: theme.colors.border
707
+ }],
708
+ children: /*#__PURE__*/_jsx(View, {
709
+ style: [styles.progressFill, progressFillStyle]
710
+ })
711
+ }), /*#__PURE__*/_jsxs(Text, {
712
+ style: [styles.progressTime, {
713
+ color: theme.colors.textSecondary
714
+ }],
715
+ children: [formatClock(elapsedSec, withHours), " / ", formatClock(streamDurationSec, withHours)]
716
+ })]
717
+ })]
718
+ }), /*#__PURE__*/_jsxs(ScrollView, {
719
+ style: {
720
+ flex: 1
721
+ },
722
+ contentContainerStyle: styles.scrollContent,
723
+ showsVerticalScrollIndicator: false,
724
+ children: [/*#__PURE__*/_jsx(View, {
725
+ style: styles.speakerGrid,
726
+ children: speakers.map(p => /*#__PURE__*/_jsx(ConnectedSpeakerTile, {
727
+ participant: p,
728
+ isCurrentUser: p.userId === userId,
729
+ isSpeaking: activeSpeakerIds.has(p.userId),
730
+ theme: theme,
731
+ oxyServices: oxyServices,
732
+ AvatarComponent: AvatarComponent,
733
+ getCachedFileDownloadUrlSync: getCachedFileDownloadUrlSync,
734
+ useUserById: useUserById
735
+ }, p.userId))
736
+ }), listeners.length > 0 && /*#__PURE__*/_jsxs(View, {
737
+ style: styles.listenerSection,
738
+ children: [/*#__PURE__*/_jsxs(Text, {
739
+ style: [styles.listenerHeader, {
740
+ color: theme.colors.textSecondary
741
+ }],
742
+ children: ["Listeners (", listeners.length, ")"]
743
+ }), /*#__PURE__*/_jsx(View, {
744
+ style: styles.listenerGrid,
745
+ children: listeners.map(p => /*#__PURE__*/_jsx(ConnectedListenerAvatar, {
746
+ participant: p,
747
+ oxyServices: oxyServices,
748
+ AvatarComponent: AvatarComponent,
749
+ getCachedFileDownloadUrlSync: getCachedFileDownloadUrlSync,
750
+ useUserById: useUserById
751
+ }, p.userId))
752
+ })]
753
+ }), isHost && speakerRequests.length > 0 && /*#__PURE__*/_jsxs(View, {
754
+ style: styles.requestsSection,
755
+ children: [/*#__PURE__*/_jsx(Text, {
756
+ style: [styles.requestsHeader, {
757
+ color: theme.colors.textSecondary
758
+ }],
759
+ children: "Requests to speak"
760
+ }), speakerRequests.map(r => /*#__PURE__*/_jsx(ConnectedRequestRow, {
761
+ request: r,
762
+ theme: theme,
763
+ oxyServices: oxyServices,
764
+ onApprove: approveSpeaker,
765
+ onDeny: denySpeaker,
766
+ AvatarComponent: AvatarComponent,
767
+ getCachedFileDownloadUrlSync: getCachedFileDownloadUrlSync,
768
+ useUserById: useUserById
769
+ }, r.userId))]
770
+ })]
771
+ }), /*#__PURE__*/_jsxs(View, {
772
+ style: [styles.controlBar, {
773
+ borderTopColor: theme.colors.border
774
+ }],
775
+ children: [canSpeak ? /*#__PURE__*/_jsxs(TouchableOpacity, {
776
+ style: styles.controlItem,
777
+ onPress: toggleMute,
778
+ children: [/*#__PURE__*/_jsx(View, {
779
+ style: [styles.controlCircle, {
780
+ backgroundColor: isMuted ? theme.colors.backgroundSecondary : theme.colors.primary
781
+ }],
782
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
783
+ name: isMuted ? 'microphone-off' : 'microphone',
784
+ size: 24,
785
+ color: isMuted ? theme.colors.text : '#FFFFFF'
786
+ })
787
+ }), /*#__PURE__*/_jsx(Text, {
788
+ style: [styles.controlLabel, {
789
+ color: theme.colors.textSecondary
790
+ }],
791
+ children: isMuted ? 'Unmute' : 'Mute'
792
+ })]
793
+ }) : /*#__PURE__*/_jsxs(TouchableOpacity, {
794
+ style: styles.controlItem,
795
+ onPress: requestToSpeak,
796
+ children: [/*#__PURE__*/_jsx(View, {
797
+ style: [styles.controlCircle, {
798
+ backgroundColor: theme.colors.backgroundSecondary
799
+ }],
800
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
801
+ name: "hand-back-left",
802
+ size: 24,
803
+ color: theme.colors.text
804
+ })
805
+ }), /*#__PURE__*/_jsx(Text, {
806
+ style: [styles.controlLabel, {
807
+ color: theme.colors.textSecondary
808
+ }],
809
+ children: "Request"
810
+ })]
811
+ }), /*#__PURE__*/_jsxs(TouchableOpacity, {
812
+ style: styles.controlItem,
813
+ onPress: () => setActivePanel('insights'),
814
+ children: [/*#__PURE__*/_jsx(View, {
815
+ style: [styles.controlCircle, {
816
+ backgroundColor: theme.colors.backgroundSecondary
817
+ }],
818
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
819
+ name: "chart-box-outline",
820
+ size: 24,
821
+ color: theme.colors.text
822
+ })
823
+ }), /*#__PURE__*/_jsx(Text, {
824
+ style: [styles.controlLabel, {
825
+ color: theme.colors.textSecondary
826
+ }],
827
+ children: "Insights"
828
+ })]
829
+ }), isHost && /*#__PURE__*/_jsxs(TouchableOpacity, {
830
+ style: styles.controlItem,
831
+ onPress: () => setActivePanel('stream'),
832
+ children: [/*#__PURE__*/_jsx(View, {
833
+ style: [styles.controlCircle, {
834
+ backgroundColor: theme.colors.backgroundSecondary
835
+ }],
836
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
837
+ name: "radio",
838
+ size: 24,
839
+ color: theme.colors.text
840
+ })
841
+ }), /*#__PURE__*/_jsx(Text, {
842
+ style: [styles.controlLabel, {
843
+ color: theme.colors.textSecondary
844
+ }],
845
+ children: "Stream"
846
+ })]
847
+ }), isHost && /*#__PURE__*/_jsxs(TouchableOpacity, {
848
+ style: styles.controlItem,
849
+ onPress: () => setActivePanel('settings'),
850
+ children: [/*#__PURE__*/_jsx(View, {
851
+ style: [styles.controlCircle, {
852
+ backgroundColor: theme.colors.backgroundSecondary
853
+ }],
854
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
855
+ name: "cog-outline",
856
+ size: 24,
857
+ color: theme.colors.text
858
+ })
859
+ }), /*#__PURE__*/_jsx(Text, {
860
+ style: [styles.controlLabel, {
861
+ color: theme.colors.textSecondary
862
+ }],
863
+ children: "Settings"
864
+ })]
865
+ }), /*#__PURE__*/_jsxs(TouchableOpacity, {
866
+ style: styles.controlItem,
867
+ onPress: handleLeave,
868
+ children: [/*#__PURE__*/_jsx(View, {
869
+ style: [styles.leaveCircle, {
870
+ backgroundColor: '#FF4458'
871
+ }],
872
+ children: /*#__PURE__*/_jsx(MaterialCommunityIcons, {
873
+ name: "exit-run",
874
+ size: 24,
875
+ color: "#FFFFFF"
876
+ })
877
+ }), /*#__PURE__*/_jsx(Text, {
878
+ style: [styles.controlLabel, {
879
+ color: theme.colors.textSecondary
880
+ }],
881
+ children: "Leave"
882
+ })]
883
+ })]
884
+ })]
885
+ });
886
+ }
887
+ const styles = StyleSheet.create({
888
+ container: {
889
+ flex: 1
890
+ },
891
+ header: {
892
+ flexDirection: 'row',
893
+ alignItems: 'center',
894
+ paddingHorizontal: 16,
895
+ paddingVertical: 12,
896
+ borderBottomWidth: 1
897
+ },
898
+ headerButton: {
899
+ padding: 4
900
+ },
901
+ headerCenter: {
902
+ flex: 1,
903
+ flexDirection: 'row',
904
+ alignItems: 'center',
905
+ justifyContent: 'center',
906
+ gap: 8
907
+ },
908
+ headerRight: {
909
+ minWidth: 40,
910
+ alignItems: 'flex-end'
911
+ },
912
+ liveBadge: {
913
+ flexDirection: 'row',
914
+ alignItems: 'center',
915
+ paddingHorizontal: 10,
916
+ paddingVertical: 4,
917
+ borderRadius: 12,
918
+ gap: 5
919
+ },
920
+ liveText: {
921
+ fontSize: 12,
922
+ fontWeight: '700',
923
+ color: '#FFFFFF'
924
+ },
925
+ listenerCount: {
926
+ fontSize: 14,
927
+ fontWeight: '500'
928
+ },
929
+ endButton: {
930
+ paddingHorizontal: 16,
931
+ paddingVertical: 6,
932
+ borderRadius: 16,
933
+ backgroundColor: '#FF44581A'
934
+ },
935
+ endButtonText: {
936
+ fontSize: 15,
937
+ fontWeight: '600',
938
+ color: '#FF4458'
939
+ },
940
+ roomInfo: {
941
+ paddingHorizontal: 16,
942
+ paddingTop: 16,
943
+ paddingBottom: 8
944
+ },
945
+ roomTitle: {
946
+ fontSize: 32,
947
+ fontWeight: 'bold',
948
+ lineHeight: 38
949
+ },
950
+ roomTopic: {
951
+ fontSize: 14,
952
+ marginTop: 4
953
+ },
954
+ micBanner: {
955
+ flexDirection: 'row',
956
+ alignItems: 'center',
957
+ gap: 8,
958
+ marginHorizontal: 16,
959
+ marginBottom: 4,
960
+ paddingHorizontal: 12,
961
+ paddingVertical: 10,
962
+ borderRadius: 8,
963
+ borderWidth: 1
964
+ },
965
+ micBannerText: {
966
+ flex: 1,
967
+ fontSize: 13,
968
+ fontWeight: '500',
969
+ color: '#856404'
970
+ },
971
+ scrollContent: {
972
+ paddingBottom: 120
973
+ },
974
+ speakerGrid: {
975
+ flexDirection: 'row',
976
+ flexWrap: 'wrap',
977
+ paddingHorizontal: 12,
978
+ paddingTop: 16
979
+ },
980
+ speakerTile: {
981
+ width: '25%',
982
+ alignItems: 'center',
983
+ marginBottom: 20
984
+ },
985
+ muteIndicator: {
986
+ position: 'absolute',
987
+ bottom: 0,
988
+ right: 0,
989
+ width: 22,
990
+ height: 22,
991
+ borderRadius: 11,
992
+ alignItems: 'center',
993
+ justifyContent: 'center',
994
+ borderWidth: 2,
995
+ borderColor: '#FFFFFF'
996
+ },
997
+ speakerName: {
998
+ fontSize: 12,
999
+ fontWeight: '500',
1000
+ marginTop: 6,
1001
+ textAlign: 'center',
1002
+ maxWidth: 80
1003
+ },
1004
+ roleBadge: {
1005
+ paddingHorizontal: 6,
1006
+ paddingVertical: 2,
1007
+ borderRadius: 4,
1008
+ marginTop: 2
1009
+ },
1010
+ roleBadgeText: {
1011
+ fontSize: 10,
1012
+ fontWeight: '600',
1013
+ color: '#FFFFFF'
1014
+ },
1015
+ listenerSection: {
1016
+ paddingHorizontal: 16,
1017
+ marginTop: 8
1018
+ },
1019
+ listenerHeader: {
1020
+ fontSize: 14,
1021
+ fontWeight: '600',
1022
+ marginBottom: 12
1023
+ },
1024
+ listenerGrid: {
1025
+ flexDirection: 'row',
1026
+ flexWrap: 'wrap',
1027
+ gap: 12
1028
+ },
1029
+ listenerItem: {
1030
+ marginBottom: 4
1031
+ },
1032
+ requestsSection: {
1033
+ paddingHorizontal: 16,
1034
+ marginTop: 24
1035
+ },
1036
+ requestsHeader: {
1037
+ fontSize: 14,
1038
+ fontWeight: '600',
1039
+ marginBottom: 12
1040
+ },
1041
+ requestRow: {
1042
+ flexDirection: 'row',
1043
+ alignItems: 'center',
1044
+ padding: 12,
1045
+ borderRadius: 12,
1046
+ borderWidth: 1,
1047
+ marginBottom: 8,
1048
+ gap: 10
1049
+ },
1050
+ requestName: {
1051
+ flex: 1,
1052
+ fontSize: 14,
1053
+ fontWeight: '500'
1054
+ },
1055
+ approveBtn: {
1056
+ width: 32,
1057
+ height: 32,
1058
+ borderRadius: 16,
1059
+ alignItems: 'center',
1060
+ justifyContent: 'center'
1061
+ },
1062
+ denyBtn: {
1063
+ width: 32,
1064
+ height: 32,
1065
+ borderRadius: 16,
1066
+ alignItems: 'center',
1067
+ justifyContent: 'center'
1068
+ },
1069
+ controlBar: {
1070
+ flexDirection: 'row',
1071
+ justifyContent: 'center',
1072
+ alignItems: 'flex-start',
1073
+ paddingTop: 12,
1074
+ paddingBottom: 12,
1075
+ paddingHorizontal: 16,
1076
+ borderTopWidth: 1,
1077
+ gap: 20
1078
+ },
1079
+ controlItem: {
1080
+ alignItems: 'center',
1081
+ gap: 4
1082
+ },
1083
+ controlCircle: {
1084
+ width: 52,
1085
+ height: 52,
1086
+ borderRadius: 26,
1087
+ alignItems: 'center',
1088
+ justifyContent: 'center'
1089
+ },
1090
+ leaveCircle: {
1091
+ width: 52,
1092
+ height: 52,
1093
+ borderRadius: 26,
1094
+ alignItems: 'center',
1095
+ justifyContent: 'center'
1096
+ },
1097
+ controlLabel: {
1098
+ fontSize: 11,
1099
+ fontWeight: '500'
1100
+ },
1101
+ streamCard: {
1102
+ marginHorizontal: 16,
1103
+ marginBottom: 4,
1104
+ padding: 10,
1105
+ borderRadius: 12,
1106
+ borderWidth: 1,
1107
+ gap: 8
1108
+ },
1109
+ streamCardRow: {
1110
+ flexDirection: 'row',
1111
+ alignItems: 'center',
1112
+ gap: 10
1113
+ },
1114
+ streamCardImage: {
1115
+ width: 44,
1116
+ height: 44,
1117
+ borderRadius: 8
1118
+ },
1119
+ streamCardIconBox: {
1120
+ width: 44,
1121
+ height: 44,
1122
+ borderRadius: 8,
1123
+ alignItems: 'center',
1124
+ justifyContent: 'center'
1125
+ },
1126
+ streamCardContent: {
1127
+ flex: 1,
1128
+ gap: 2
1129
+ },
1130
+ streamCardTitle: {
1131
+ fontSize: 14,
1132
+ fontWeight: '600'
1133
+ },
1134
+ streamCardDesc: {
1135
+ fontSize: 12
1136
+ },
1137
+ streamCardActions: {
1138
+ flexDirection: 'row',
1139
+ alignItems: 'center',
1140
+ gap: 2
1141
+ },
1142
+ streamCardAction: {
1143
+ padding: 4
1144
+ },
1145
+ streamProgress: {
1146
+ gap: 4
1147
+ },
1148
+ progressTrack: {
1149
+ height: 4,
1150
+ borderRadius: 2,
1151
+ overflow: 'hidden'
1152
+ },
1153
+ progressFill: {
1154
+ height: 4,
1155
+ borderRadius: 2
1156
+ },
1157
+ progressTime: {
1158
+ fontSize: 11,
1159
+ fontWeight: '500',
1160
+ textAlign: 'right'
1161
+ },
1162
+ settingsContent: {
1163
+ paddingHorizontal: 16,
1164
+ paddingTop: 16
1165
+ },
1166
+ settingsItem: {
1167
+ flexDirection: 'row',
1168
+ alignItems: 'center',
1169
+ gap: 14,
1170
+ paddingVertical: 14
1171
+ },
1172
+ settingsItemText: {
1173
+ flex: 1
1174
+ },
1175
+ settingsItemTitle: {
1176
+ fontSize: 16,
1177
+ fontWeight: '600'
1178
+ },
1179
+ settingsItemDesc: {
1180
+ fontSize: 13,
1181
+ marginTop: 2
1182
+ },
1183
+ recordingToggle: {
1184
+ paddingHorizontal: 14,
1185
+ paddingVertical: 6,
1186
+ borderRadius: 14
1187
+ }
1188
+ });
1189
+ //# sourceMappingURL=LiveRoomSheet.js.map