@getontime/cli 4.3.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/client/assets/{Backstage-CDH53Q_N.js → Backstage-D2lEbqUt.js} +2 -2
  2. package/client/assets/Backstage-D2lEbqUt.js.br +0 -0
  3. package/client/assets/Backstage-D2lEbqUt.js.gz +0 -0
  4. package/client/assets/{Backstage-CDH53Q_N.js.map → Backstage-D2lEbqUt.js.map} +1 -1
  5. package/client/assets/{Countdown-B-MuMf1C.js → Countdown-VV03STbF.js} +2 -2
  6. package/client/assets/Countdown-VV03STbF.js.br +0 -0
  7. package/client/assets/Countdown-VV03STbF.js.gz +0 -0
  8. package/client/assets/{Countdown-B-MuMf1C.js.map → Countdown-VV03STbF.js.map} +1 -1
  9. package/client/assets/{CustomTranslationModal-DiQbmcgD.js → CustomTranslationModal-D1nM9W1Z.js} +2 -2
  10. package/client/assets/CustomTranslationModal-D1nM9W1Z.js.br +0 -0
  11. package/client/assets/CustomTranslationModal-D1nM9W1Z.js.gz +0 -0
  12. package/client/assets/{CustomTranslationModal-DiQbmcgD.js.map → CustomTranslationModal-D1nM9W1Z.js.map} +1 -1
  13. package/client/assets/{DelayIndicator-D--91EO3.js → DelayIndicator-Co5rMYw9.js} +2 -2
  14. package/client/assets/DelayIndicator-Co5rMYw9.js.br +0 -0
  15. package/client/assets/DelayIndicator-Co5rMYw9.js.gz +0 -0
  16. package/client/assets/{DelayIndicator-D--91EO3.js.map → DelayIndicator-Co5rMYw9.js.map} +1 -1
  17. package/client/assets/{EditorFeatureWrapper-DwXUAV4k.js → EditorFeatureWrapper-_t_4D7Es.js} +2 -2
  18. package/client/assets/EditorFeatureWrapper-_t_4D7Es.js.br +0 -0
  19. package/client/assets/EditorFeatureWrapper-_t_4D7Es.js.gz +0 -0
  20. package/client/assets/{EditorFeatureWrapper-DwXUAV4k.js.map → EditorFeatureWrapper-_t_4D7Es.js.map} +1 -1
  21. package/client/assets/{EditorUtils-DuKjlUkF.js → EditorUtils-C3QoonjM.js} +2 -2
  22. package/client/assets/EditorUtils-C3QoonjM.js.br +0 -0
  23. package/client/assets/EditorUtils-C3QoonjM.js.gz +0 -0
  24. package/client/assets/{EditorUtils-DuKjlUkF.js.map → EditorUtils-C3QoonjM.js.map} +1 -1
  25. package/client/assets/{Empty-CJbZxh45.js → Empty-DJMjfXnt.js} +2 -2
  26. package/client/assets/Empty-DJMjfXnt.js.br +2 -0
  27. package/client/assets/Empty-DJMjfXnt.js.gz +0 -0
  28. package/client/assets/{Empty-CJbZxh45.js.map → Empty-DJMjfXnt.js.map} +1 -1
  29. package/client/assets/{EmptyPage-Bc358YpE.js → EmptyPage-BlXZqoIr.js} +2 -2
  30. package/client/assets/EmptyPage-BlXZqoIr.js.br +0 -0
  31. package/client/assets/EmptyPage-BlXZqoIr.js.gz +0 -0
  32. package/client/assets/{EmptyPage-Bc358YpE.js.map → EmptyPage-BlXZqoIr.js.map} +1 -1
  33. package/client/assets/{FollowButton-C6Fvaqh0.js → FollowButton-Dy5n1J2c.js} +2 -2
  34. package/client/assets/FollowButton-Dy5n1J2c.js.br +0 -0
  35. package/client/assets/FollowButton-Dy5n1J2c.js.gz +0 -0
  36. package/client/assets/{FollowButton-C6Fvaqh0.js.map → FollowButton-Dy5n1J2c.js.map} +1 -1
  37. package/client/assets/{MessageControlExport-GmOrvUik.js → MessageControlExport-CWQX8mH0.js} +3 -3
  38. package/client/assets/MessageControlExport-CWQX8mH0.js.br +0 -0
  39. package/client/assets/MessageControlExport-CWQX8mH0.js.gz +0 -0
  40. package/client/assets/{MessageControlExport-GmOrvUik.js.map → MessageControlExport-CWQX8mH0.js.map} +1 -1
  41. package/client/assets/{MilestoneEditor-BA0PVIQh.js → MilestoneEditor-CxWZdQ1B.js} +2 -2
  42. package/client/assets/MilestoneEditor-CxWZdQ1B.js.br +0 -0
  43. package/client/assets/MilestoneEditor-CxWZdQ1B.js.gz +0 -0
  44. package/client/assets/{MilestoneEditor-BA0PVIQh.js.map → MilestoneEditor-CxWZdQ1B.js.map} +1 -1
  45. package/client/assets/{Modal-BKx0PDGT.js → Modal-ePA-Go14.js} +2 -2
  46. package/client/assets/Modal-ePA-Go14.js.br +0 -0
  47. package/client/assets/Modal-ePA-Go14.js.gz +0 -0
  48. package/client/assets/{Modal-BKx0PDGT.js.map → Modal-ePA-Go14.js.map} +1 -1
  49. package/client/assets/{MultiPartProgressBar-BXdLxJpy.js → MultiPartProgressBar-GQaCHX4z.js} +2 -2
  50. package/client/assets/MultiPartProgressBar-GQaCHX4z.js.br +0 -0
  51. package/client/assets/MultiPartProgressBar-GQaCHX4z.js.gz +0 -0
  52. package/client/assets/{MultiPartProgressBar-BXdLxJpy.js.map → MultiPartProgressBar-GQaCHX4z.js.map} +1 -1
  53. package/client/assets/{OperatorExport-X7-qi2jv.js → OperatorExport-CRS08UXj.js} +2 -2
  54. package/client/assets/OperatorExport-CRS08UXj.js.br +0 -0
  55. package/client/assets/OperatorExport-CRS08UXj.js.gz +0 -0
  56. package/client/assets/{OperatorExport-X7-qi2jv.js.map → OperatorExport-CRS08UXj.js.map} +1 -1
  57. package/client/assets/{OverviewWrapper-BQb2xl_N.js → OverviewWrapper-BNRb3Ub_.js} +2 -2
  58. package/client/assets/OverviewWrapper-BNRb3Ub_.js.br +0 -0
  59. package/client/assets/OverviewWrapper-BNRb3Ub_.js.gz +0 -0
  60. package/client/assets/{OverviewWrapper-BQb2xl_N.js.map → OverviewWrapper-BNRb3Ub_.js.map} +1 -1
  61. package/client/assets/{PipHost-CvtlZIn7.js → PipHost-DNfEY6RN.js} +2 -2
  62. package/client/assets/PipHost-DNfEY6RN.js.br +0 -0
  63. package/client/assets/PipHost-DNfEY6RN.js.gz +0 -0
  64. package/client/assets/{PipHost-CvtlZIn7.js.map → PipHost-DNfEY6RN.js.map} +1 -1
  65. package/client/assets/{ProjectInfo-1tw48NHZ.js → ProjectInfo-KPf-pM8y.js} +2 -2
  66. package/client/assets/ProjectInfo-KPf-pM8y.js.br +0 -0
  67. package/client/assets/ProjectInfo-KPf-pM8y.js.gz +0 -0
  68. package/client/assets/{ProjectInfo-1tw48NHZ.js.map → ProjectInfo-KPf-pM8y.js.map} +1 -1
  69. package/client/assets/{ProtectRoute-BH-QvsU0.js → ProtectRoute-DW_vXgYI.js} +2 -2
  70. package/client/assets/ProtectRoute-DW_vXgYI.js.br +0 -0
  71. package/client/assets/ProtectRoute-DW_vXgYI.js.gz +0 -0
  72. package/client/assets/{ProtectRoute-BH-QvsU0.js.map → ProtectRoute-DW_vXgYI.js.map} +1 -1
  73. package/client/assets/{ProtectedCuesheet-CYBIcg1c.js → ProtectedCuesheet-CCVDLsK-.js} +2 -2
  74. package/client/assets/ProtectedCuesheet-CCVDLsK-.js.br +0 -0
  75. package/client/assets/ProtectedCuesheet-CCVDLsK-.js.gz +0 -0
  76. package/client/assets/{ProtectedCuesheet-CYBIcg1c.js.map → ProtectedCuesheet-CCVDLsK-.js.map} +1 -1
  77. package/client/assets/{ProtectedEditor-D_A75byA.js → ProtectedEditor-Ddu9vBS8.js} +3 -3
  78. package/client/assets/ProtectedEditor-Ddu9vBS8.js.br +0 -0
  79. package/client/assets/ProtectedEditor-Ddu9vBS8.js.gz +0 -0
  80. package/client/assets/ProtectedEditor-Ddu9vBS8.js.map +1 -0
  81. package/client/assets/{RundownEntry-bkqwx57t.js → RundownEntry-CpspmKD0.js} +2 -2
  82. package/client/assets/RundownEntry-CpspmKD0.js.br +0 -0
  83. package/client/assets/RundownEntry-CpspmKD0.js.gz +0 -0
  84. package/client/assets/{RundownEntry-bkqwx57t.js.map → RundownEntry-CpspmKD0.js.map} +1 -1
  85. package/client/assets/{RundownExport-EorsanA0.js → RundownExport-DhCryTUp.js} +3 -3
  86. package/client/assets/RundownExport-DhCryTUp.js.br +0 -0
  87. package/client/assets/RundownExport-DhCryTUp.js.gz +0 -0
  88. package/client/assets/{RundownExport-EorsanA0.js.map → RundownExport-DhCryTUp.js.map} +1 -1
  89. package/client/assets/{Select-BGGVCKqU.js → Select-ASOzxGFV.js} +2 -2
  90. package/client/assets/Select-ASOzxGFV.js.br +0 -0
  91. package/client/assets/Select-ASOzxGFV.js.gz +0 -0
  92. package/client/assets/{Select-BGGVCKqU.js.map → Select-ASOzxGFV.js.map} +1 -1
  93. package/client/assets/{Studio-BjNZ4l-W.js → Studio-D7evHV2Q.js} +2 -2
  94. package/client/assets/Studio-D7evHV2Q.js.br +0 -0
  95. package/client/assets/Studio-D7evHV2Q.js.gz +0 -0
  96. package/client/assets/{Studio-BjNZ4l-W.js.map → Studio-D7evHV2Q.js.map} +1 -1
  97. package/client/assets/{StyleEditor-CpciRLYh.js → StyleEditor-DYybY9tA.js} +2 -2
  98. package/client/assets/StyleEditor-DYybY9tA.js.br +0 -0
  99. package/client/assets/StyleEditor-DYybY9tA.js.gz +0 -0
  100. package/client/assets/{StyleEditor-CpciRLYh.js.map → StyleEditor-DYybY9tA.js.map} +1 -1
  101. package/client/assets/{SuperscriptPeriod-DsPdWN_s.js → SuperscriptPeriod-NmBzJhFK.js} +2 -2
  102. package/client/assets/SuperscriptPeriod-NmBzJhFK.js.br +0 -0
  103. package/client/assets/SuperscriptPeriod-NmBzJhFK.js.gz +0 -0
  104. package/client/assets/{SuperscriptPeriod-DsPdWN_s.js.map → SuperscriptPeriod-NmBzJhFK.js.map} +1 -1
  105. package/client/assets/{SuperscriptTime-CA6S2R55.js → SuperscriptTime-CA_8XRM6.js} +2 -2
  106. package/client/assets/SuperscriptTime-CA_8XRM6.js.br +0 -0
  107. package/client/assets/SuperscriptTime-CA_8XRM6.js.gz +0 -0
  108. package/client/assets/{SuperscriptTime-CA6S2R55.js.map → SuperscriptTime-CA_8XRM6.js.map} +1 -1
  109. package/client/assets/{SwatchPicker-Cm5Eicvv.js → SwatchPicker-C8eFQKBd.js} +2 -2
  110. package/client/assets/SwatchPicker-C8eFQKBd.js.br +0 -0
  111. package/client/assets/SwatchPicker-C8eFQKBd.js.gz +0 -0
  112. package/client/assets/{SwatchPicker-Cm5Eicvv.js.map → SwatchPicker-C8eFQKBd.js.map} +1 -1
  113. package/client/assets/{TimeElements-DbclWDbU.js → TimeElements-D3dl9gAM.js} +2 -2
  114. package/client/assets/TimeElements-D3dl9gAM.js.br +0 -0
  115. package/client/assets/TimeElements-D3dl9gAM.js.gz +0 -0
  116. package/client/assets/{TimeElements-DbclWDbU.js.map → TimeElements-D3dl9gAM.js.map} +1 -1
  117. package/client/assets/{TimeInput-C8DQoFXv.js → TimeInput-DR-NCEhH.js} +2 -2
  118. package/client/assets/TimeInput-DR-NCEhH.js.br +0 -0
  119. package/client/assets/TimeInput-DR-NCEhH.js.gz +0 -0
  120. package/client/assets/{TimeInput-C8DQoFXv.js.map → TimeInput-DR-NCEhH.js.map} +1 -1
  121. package/client/assets/{TimelinePage-Cgtl1qNp.js → TimelinePage-BfTV9IdT.js} +2 -2
  122. package/client/assets/TimelinePage-BfTV9IdT.js.br +0 -0
  123. package/client/assets/TimelinePage-BfTV9IdT.js.gz +0 -0
  124. package/client/assets/{TimelinePage-Cgtl1qNp.js.map → TimelinePage-BfTV9IdT.js.map} +1 -1
  125. package/client/assets/{Timer-BbixOGdj.js → Timer-DvqDm4yX.js} +2 -2
  126. package/client/assets/Timer-DvqDm4yX.js.br +0 -0
  127. package/client/assets/Timer-DvqDm4yX.js.gz +0 -0
  128. package/client/assets/{Timer-BbixOGdj.js.map → Timer-DvqDm4yX.js.map} +1 -1
  129. package/client/assets/{TimerControlExport-Dx3SSGNG.js → TimerControlExport-CQQ2KxqK.js} +2 -2
  130. package/client/assets/TimerControlExport-CQQ2KxqK.js.br +0 -0
  131. package/client/assets/TimerControlExport-CQQ2KxqK.js.gz +0 -0
  132. package/client/assets/{TimerControlExport-Dx3SSGNG.js.map → TimerControlExport-CQQ2KxqK.js.map} +1 -1
  133. package/client/assets/{TitleCard-Xdr7xwzU.js → TitleCard-AESdy7kI.js} +2 -2
  134. package/client/assets/TitleCard-AESdy7kI.js.br +0 -0
  135. package/client/assets/TitleCard-AESdy7kI.js.gz +0 -0
  136. package/client/assets/{TitleCard-Xdr7xwzU.js.map → TitleCard-AESdy7kI.js.map} +1 -1
  137. package/client/assets/{Tooltip-B5vsLcFu.js → Tooltip-BTK4bJkV.js} +2 -2
  138. package/client/assets/Tooltip-BTK4bJkV.js.br +0 -0
  139. package/client/assets/Tooltip-BTK4bJkV.js.gz +0 -0
  140. package/client/assets/{Tooltip-B5vsLcFu.js.map → Tooltip-BTK4bJkV.js.map} +1 -1
  141. package/client/assets/ViewLogo-BZVUUIZA.js +2 -0
  142. package/client/assets/ViewLogo-BZVUUIZA.js.br +0 -0
  143. package/client/assets/ViewLogo-BZVUUIZA.js.gz +0 -0
  144. package/client/assets/ViewLogo-BZVUUIZA.js.map +1 -0
  145. package/client/assets/{ViewParamsEditor-C2-TRP6e.js → ViewParamsEditor-CBnRitZ4.js} +2 -2
  146. package/client/assets/ViewParamsEditor-CBnRitZ4.js.br +0 -0
  147. package/client/assets/ViewParamsEditor-CBnRitZ4.js.gz +0 -0
  148. package/client/assets/{ViewParamsEditor-C2-TRP6e.js.map → ViewParamsEditor-CBnRitZ4.js.map} +1 -1
  149. package/client/assets/{dateConfig-D7xim1t4.js → dateConfig-Crm-Cu2y.js} +2 -2
  150. package/client/assets/dateConfig-Crm-Cu2y.js.br +0 -0
  151. package/client/assets/dateConfig-Crm-Cu2y.js.gz +0 -0
  152. package/client/assets/{dateConfig-D7xim1t4.js.map → dateConfig-Crm-Cu2y.js.map} +1 -1
  153. package/client/assets/{editorSettings-D2f7e1a6.js → editorSettings-CRJwIW7V.js} +2 -2
  154. package/client/assets/editorSettings-CRJwIW7V.js.br +0 -0
  155. package/client/assets/editorSettings-CRJwIW7V.js.gz +0 -0
  156. package/client/assets/{editorSettings-D2f7e1a6.js.map → editorSettings-CRJwIW7V.js.map} +1 -1
  157. package/client/assets/{getProgress-cLuBFPjh.js → getProgress-fD6vhbNF.js} +2 -2
  158. package/client/assets/getProgress-fD6vhbNF.js.br +0 -0
  159. package/client/assets/getProgress-fD6vhbNF.js.gz +0 -0
  160. package/client/assets/{getProgress-cLuBFPjh.js.map → getProgress-fD6vhbNF.js.map} +1 -1
  161. package/client/assets/{index-B81u4hxi.js → index-B1K7rED_.js} +3 -3
  162. package/client/assets/index-B1K7rED_.js.br +0 -0
  163. package/client/assets/index-B1K7rED_.js.gz +0 -0
  164. package/client/assets/index-B1K7rED_.js.map +1 -0
  165. package/client/assets/{index-D6S93MXv.css → index-BAvwULMi.css} +1 -1
  166. package/client/assets/index-BAvwULMi.css.br +0 -0
  167. package/client/assets/{index-D6S93MXv.css.gz → index-BAvwULMi.css.gz} +0 -0
  168. package/client/assets/{offset-R98EXhWK.js → offset-FplkvYRD.js} +2 -2
  169. package/client/assets/offset-FplkvYRD.js.br +0 -0
  170. package/client/assets/offset-FplkvYRD.js.gz +0 -0
  171. package/client/assets/{offset-R98EXhWK.js.map → offset-FplkvYRD.js.map} +1 -1
  172. package/client/assets/{parseUserTime-YeFR8t3F.js → parseUserTime-0pNWLcr0.js} +2 -2
  173. package/client/assets/parseUserTime-0pNWLcr0.js.br +0 -0
  174. package/client/assets/parseUserTime-0pNWLcr0.js.gz +0 -0
  175. package/client/assets/{parseUserTime-YeFR8t3F.js.map → parseUserTime-0pNWLcr0.js.map} +1 -1
  176. package/client/assets/{playbackstate-CPQdnF-k.js → playbackstate-1HCEpVh5.js} +2 -2
  177. package/client/assets/playbackstate-1HCEpVh5.js.br +0 -0
  178. package/client/assets/playbackstate-1HCEpVh5.js.gz +0 -0
  179. package/client/assets/{playbackstate-CPQdnF-k.js.map → playbackstate-1HCEpVh5.js.map} +1 -1
  180. package/client/assets/{presentation.utils-Cl-L3pHN.js → presentation.utils-CLt2UhON.js} +2 -2
  181. package/client/assets/presentation.utils-CLt2UhON.js.br +0 -0
  182. package/client/assets/presentation.utils-CLt2UhON.js.gz +0 -0
  183. package/client/assets/{presentation.utils-Cl-L3pHN.js.map → presentation.utils-CLt2UhON.js.map} +1 -1
  184. package/client/assets/{rundownUtils-CtVGQDQn.js → rundownUtils-D1oJpMdx.js} +2 -2
  185. package/client/assets/rundownUtils-D1oJpMdx.js.br +0 -0
  186. package/client/assets/rundownUtils-D1oJpMdx.js.gz +0 -0
  187. package/client/assets/{rundownUtils-CtVGQDQn.js.map → rundownUtils-D1oJpMdx.js.map} +1 -1
  188. package/client/assets/{timer.utils-rGyI9NYa.js → timer.utils-FiqT1yNa.js} +2 -2
  189. package/client/assets/timer.utils-FiqT1yNa.js.br +0 -0
  190. package/client/assets/timer.utils-FiqT1yNa.js.gz +0 -0
  191. package/client/assets/{timer.utils-rGyI9NYa.js.map → timer.utils-FiqT1yNa.js.map} +1 -1
  192. package/client/assets/{useCustomFields-k4piRt9n.js → useCustomFields-nW-_Zyfw.js} +2 -2
  193. package/client/assets/useCustomFields-nW-_Zyfw.js.br +0 -0
  194. package/client/assets/useCustomFields-nW-_Zyfw.js.gz +0 -0
  195. package/client/assets/{useCustomFields-k4piRt9n.js.map → useCustomFields-nW-_Zyfw.js.map} +1 -1
  196. package/client/assets/{useFollowComponent-B7vvPzG2.js → useFollowComponent-4cbKEsVz.js} +2 -2
  197. package/client/assets/useFollowComponent-4cbKEsVz.js.br +0 -0
  198. package/client/assets/useFollowComponent-4cbKEsVz.js.gz +0 -0
  199. package/client/assets/{useFollowComponent-B7vvPzG2.js.map → useFollowComponent-4cbKEsVz.js.map} +1 -1
  200. package/client/assets/{useProjectData-DdgKoYzk.js → useProjectData-DP-pr73E.js} +2 -2
  201. package/client/assets/useProjectData-DP-pr73E.js.br +0 -0
  202. package/client/assets/useProjectData-DP-pr73E.js.gz +0 -0
  203. package/client/assets/{useProjectData-DdgKoYzk.js.map → useProjectData-DP-pr73E.js.map} +1 -1
  204. package/client/assets/{useReport-DSuFnUb9.js → useReport-6XA_s2Vc.js} +2 -2
  205. package/client/assets/useReport-6XA_s2Vc.js.br +0 -0
  206. package/client/assets/useReport-6XA_s2Vc.js.gz +0 -0
  207. package/client/assets/{useReport-DSuFnUb9.js.map → useReport-6XA_s2Vc.js.map} +1 -1
  208. package/client/assets/{useRundown-Bn6ZPsz0.js → useRundown-BGhL8DEI.js} +2 -2
  209. package/client/assets/useRundown-BGhL8DEI.js.br +0 -0
  210. package/client/assets/useRundown-BGhL8DEI.js.gz +0 -0
  211. package/client/assets/{useRundown-Bn6ZPsz0.js.map → useRundown-BGhL8DEI.js.map} +1 -1
  212. package/client/assets/{useWindowTitle-Bpmo_HzW.js → useWindowTitle-ahZQIheF.js} +2 -2
  213. package/client/assets/useWindowTitle-ahZQIheF.js.br +0 -0
  214. package/client/assets/useWindowTitle-ahZQIheF.js.gz +0 -0
  215. package/client/assets/{useWindowTitle-Bpmo_HzW.js.map → useWindowTitle-ahZQIheF.js.map} +1 -1
  216. package/client/assets/{validateEvent-Do8yE_DJ.js → validateEvent-jVIMKhmx.js} +2 -2
  217. package/client/assets/validateEvent-jVIMKhmx.js.br +0 -0
  218. package/client/assets/validateEvent-jVIMKhmx.js.gz +0 -0
  219. package/client/assets/{validateEvent-Do8yE_DJ.js.map → validateEvent-jVIMKhmx.js.map} +1 -1
  220. package/client/assets/{vendor-q6fv0YT2.js → vendor-DmGkEtRj.js} +2 -2
  221. package/client/assets/vendor-DmGkEtRj.js.br +0 -0
  222. package/client/assets/vendor-DmGkEtRj.js.gz +0 -0
  223. package/client/assets/{vendor-q6fv0YT2.js.map → vendor-DmGkEtRj.js.map} +1 -1
  224. package/client/assets/{viewLoader.utils-b42scp-I.js → viewLoader.utils-Bniie8Op.js} +2 -2
  225. package/client/assets/viewLoader.utils-Bniie8Op.js.br +0 -0
  226. package/client/assets/viewLoader.utils-Bniie8Op.js.gz +0 -0
  227. package/client/assets/{viewLoader.utils-b42scp-I.js.map → viewLoader.utils-Bniie8Op.js.map} +1 -1
  228. package/client/assets/{viewUtils-B8Dr4GHH.js → viewUtils-VNLYoR28.js} +2 -2
  229. package/client/assets/viewUtils-VNLYoR28.js.br +0 -0
  230. package/client/assets/viewUtils-VNLYoR28.js.gz +0 -0
  231. package/client/assets/{viewUtils-B8Dr4GHH.js.map → viewUtils-VNLYoR28.js.map} +1 -1
  232. package/client/index.html +3 -3
  233. package/package.json +1 -1
  234. package/server/index.cjs +74 -74
  235. package/client/assets/Backstage-CDH53Q_N.js.br +0 -0
  236. package/client/assets/Backstage-CDH53Q_N.js.gz +0 -0
  237. package/client/assets/Countdown-B-MuMf1C.js.br +0 -0
  238. package/client/assets/Countdown-B-MuMf1C.js.gz +0 -0
  239. package/client/assets/CustomTranslationModal-DiQbmcgD.js.br +0 -0
  240. package/client/assets/CustomTranslationModal-DiQbmcgD.js.gz +0 -0
  241. package/client/assets/DelayIndicator-D--91EO3.js.br +0 -0
  242. package/client/assets/DelayIndicator-D--91EO3.js.gz +0 -0
  243. package/client/assets/EditorFeatureWrapper-DwXUAV4k.js.br +0 -0
  244. package/client/assets/EditorFeatureWrapper-DwXUAV4k.js.gz +0 -0
  245. package/client/assets/EditorUtils-DuKjlUkF.js.br +0 -0
  246. package/client/assets/EditorUtils-DuKjlUkF.js.gz +0 -0
  247. package/client/assets/Empty-CJbZxh45.js.br +0 -0
  248. package/client/assets/Empty-CJbZxh45.js.gz +0 -0
  249. package/client/assets/EmptyPage-Bc358YpE.js.br +0 -5
  250. package/client/assets/EmptyPage-Bc358YpE.js.gz +0 -0
  251. package/client/assets/FollowButton-C6Fvaqh0.js.br +0 -0
  252. package/client/assets/FollowButton-C6Fvaqh0.js.gz +0 -0
  253. package/client/assets/MessageControlExport-GmOrvUik.js.br +0 -0
  254. package/client/assets/MessageControlExport-GmOrvUik.js.gz +0 -0
  255. package/client/assets/MilestoneEditor-BA0PVIQh.js.br +0 -0
  256. package/client/assets/MilestoneEditor-BA0PVIQh.js.gz +0 -0
  257. package/client/assets/Modal-BKx0PDGT.js.br +0 -0
  258. package/client/assets/Modal-BKx0PDGT.js.gz +0 -0
  259. package/client/assets/MultiPartProgressBar-BXdLxJpy.js.br +0 -0
  260. package/client/assets/MultiPartProgressBar-BXdLxJpy.js.gz +0 -0
  261. package/client/assets/OperatorExport-X7-qi2jv.js.br +0 -0
  262. package/client/assets/OperatorExport-X7-qi2jv.js.gz +0 -0
  263. package/client/assets/OverviewWrapper-BQb2xl_N.js.br +0 -0
  264. package/client/assets/OverviewWrapper-BQb2xl_N.js.gz +0 -0
  265. package/client/assets/PipHost-CvtlZIn7.js.br +0 -0
  266. package/client/assets/PipHost-CvtlZIn7.js.gz +0 -0
  267. package/client/assets/ProjectInfo-1tw48NHZ.js.br +0 -0
  268. package/client/assets/ProjectInfo-1tw48NHZ.js.gz +0 -0
  269. package/client/assets/ProtectRoute-BH-QvsU0.js.br +0 -0
  270. package/client/assets/ProtectRoute-BH-QvsU0.js.gz +0 -0
  271. package/client/assets/ProtectedCuesheet-CYBIcg1c.js.br +0 -0
  272. package/client/assets/ProtectedCuesheet-CYBIcg1c.js.gz +0 -0
  273. package/client/assets/ProtectedEditor-D_A75byA.js.br +0 -0
  274. package/client/assets/ProtectedEditor-D_A75byA.js.gz +0 -0
  275. package/client/assets/ProtectedEditor-D_A75byA.js.map +0 -1
  276. package/client/assets/RundownEntry-bkqwx57t.js.br +0 -0
  277. package/client/assets/RundownEntry-bkqwx57t.js.gz +0 -0
  278. package/client/assets/RundownExport-EorsanA0.js.br +0 -0
  279. package/client/assets/RundownExport-EorsanA0.js.gz +0 -0
  280. package/client/assets/Select-BGGVCKqU.js.br +0 -0
  281. package/client/assets/Select-BGGVCKqU.js.gz +0 -0
  282. package/client/assets/Studio-BjNZ4l-W.js.br +0 -0
  283. package/client/assets/Studio-BjNZ4l-W.js.gz +0 -0
  284. package/client/assets/StyleEditor-CpciRLYh.js.br +0 -0
  285. package/client/assets/StyleEditor-CpciRLYh.js.gz +0 -0
  286. package/client/assets/SuperscriptPeriod-DsPdWN_s.js.br +0 -0
  287. package/client/assets/SuperscriptPeriod-DsPdWN_s.js.gz +0 -0
  288. package/client/assets/SuperscriptTime-CA6S2R55.js.br +0 -0
  289. package/client/assets/SuperscriptTime-CA6S2R55.js.gz +0 -0
  290. package/client/assets/SwatchPicker-Cm5Eicvv.js.br +0 -0
  291. package/client/assets/SwatchPicker-Cm5Eicvv.js.gz +0 -0
  292. package/client/assets/TimeElements-DbclWDbU.js.br +0 -0
  293. package/client/assets/TimeElements-DbclWDbU.js.gz +0 -0
  294. package/client/assets/TimeInput-C8DQoFXv.js.br +0 -0
  295. package/client/assets/TimeInput-C8DQoFXv.js.gz +0 -0
  296. package/client/assets/TimelinePage-Cgtl1qNp.js.br +0 -0
  297. package/client/assets/TimelinePage-Cgtl1qNp.js.gz +0 -0
  298. package/client/assets/Timer-BbixOGdj.js.br +0 -0
  299. package/client/assets/Timer-BbixOGdj.js.gz +0 -0
  300. package/client/assets/TimerControlExport-Dx3SSGNG.js.br +0 -0
  301. package/client/assets/TimerControlExport-Dx3SSGNG.js.gz +0 -0
  302. package/client/assets/TitleCard-Xdr7xwzU.js.br +0 -0
  303. package/client/assets/TitleCard-Xdr7xwzU.js.gz +0 -0
  304. package/client/assets/Tooltip-B5vsLcFu.js.br +0 -0
  305. package/client/assets/Tooltip-B5vsLcFu.js.gz +0 -0
  306. package/client/assets/ViewLogo-G7EosFIr.js +0 -2
  307. package/client/assets/ViewLogo-G7EosFIr.js.br +0 -0
  308. package/client/assets/ViewLogo-G7EosFIr.js.gz +0 -0
  309. package/client/assets/ViewLogo-G7EosFIr.js.map +0 -1
  310. package/client/assets/ViewParamsEditor-C2-TRP6e.js.br +0 -0
  311. package/client/assets/ViewParamsEditor-C2-TRP6e.js.gz +0 -0
  312. package/client/assets/dateConfig-D7xim1t4.js.br +0 -0
  313. package/client/assets/dateConfig-D7xim1t4.js.gz +0 -0
  314. package/client/assets/editorSettings-D2f7e1a6.js.br +0 -0
  315. package/client/assets/editorSettings-D2f7e1a6.js.gz +0 -0
  316. package/client/assets/getProgress-cLuBFPjh.js.br +0 -0
  317. package/client/assets/getProgress-cLuBFPjh.js.gz +0 -0
  318. package/client/assets/index-B81u4hxi.js.br +0 -0
  319. package/client/assets/index-B81u4hxi.js.gz +0 -0
  320. package/client/assets/index-B81u4hxi.js.map +0 -1
  321. package/client/assets/index-D6S93MXv.css.br +0 -0
  322. package/client/assets/offset-R98EXhWK.js.br +0 -0
  323. package/client/assets/offset-R98EXhWK.js.gz +0 -0
  324. package/client/assets/parseUserTime-YeFR8t3F.js.br +0 -0
  325. package/client/assets/parseUserTime-YeFR8t3F.js.gz +0 -0
  326. package/client/assets/playbackstate-CPQdnF-k.js.br +0 -0
  327. package/client/assets/playbackstate-CPQdnF-k.js.gz +0 -0
  328. package/client/assets/presentation.utils-Cl-L3pHN.js.br +0 -0
  329. package/client/assets/presentation.utils-Cl-L3pHN.js.gz +0 -0
  330. package/client/assets/rundownUtils-CtVGQDQn.js.br +0 -0
  331. package/client/assets/rundownUtils-CtVGQDQn.js.gz +0 -0
  332. package/client/assets/timer.utils-rGyI9NYa.js.br +0 -0
  333. package/client/assets/timer.utils-rGyI9NYa.js.gz +0 -0
  334. package/client/assets/useCustomFields-k4piRt9n.js.br +0 -0
  335. package/client/assets/useCustomFields-k4piRt9n.js.gz +0 -0
  336. package/client/assets/useFollowComponent-B7vvPzG2.js.br +0 -0
  337. package/client/assets/useFollowComponent-B7vvPzG2.js.gz +0 -0
  338. package/client/assets/useProjectData-DdgKoYzk.js.br +0 -0
  339. package/client/assets/useProjectData-DdgKoYzk.js.gz +0 -0
  340. package/client/assets/useReport-DSuFnUb9.js.br +0 -0
  341. package/client/assets/useReport-DSuFnUb9.js.gz +0 -0
  342. package/client/assets/useRundown-Bn6ZPsz0.js.br +0 -0
  343. package/client/assets/useRundown-Bn6ZPsz0.js.gz +0 -0
  344. package/client/assets/useWindowTitle-Bpmo_HzW.js.br +0 -0
  345. package/client/assets/useWindowTitle-Bpmo_HzW.js.gz +0 -0
  346. package/client/assets/validateEvent-Do8yE_DJ.js.br +0 -3
  347. package/client/assets/validateEvent-Do8yE_DJ.js.gz +0 -0
  348. package/client/assets/vendor-q6fv0YT2.js.br +0 -0
  349. package/client/assets/vendor-q6fv0YT2.js.gz +0 -0
  350. package/client/assets/viewLoader.utils-b42scp-I.js.br +0 -0
  351. package/client/assets/viewLoader.utils-b42scp-I.js.gz +0 -0
  352. package/client/assets/viewUtils-B8Dr4GHH.js.br +0 -0
  353. package/client/assets/viewUtils-B8Dr4GHH.js.gz +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"mappings":"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","names":["TimerType","CountDown","CountUp","Clock","None","OntimeView","Editor","Cuesheet","Operator","Timer","Backstage","Timeline","StudioClock","Countdown","ProjectInfo","MessageTag","Ping","Pong","ClientInit","ClientSet","ClientSetPath","ClientRename","ClientRedirect","ClientList","Dialog","Log","RuntimeData","Refetch","RefetchKey","All","CustomFields","ProjectData","Report","Rundown","UrlPresets","ViewSettings","Translation","Settings","LogLevel","Info","Warn","Error","Severe","LogOrigin","Client","Playback","Rx","Server","Tx","User","Roll","Play","Pause","Stop","Armed","OffsetMode","Absolute","Relative","SimplePlayback","Start","SimpleDirection","TimerPhase","Default","Warning","Danger","Overtime","Pending","runtimeStorePlaceholder","clock","timer","addedTime","current","duration","elapsed","expectedFinish","phase","playback","secondaryTimer","startedAt","message","text","visible","blink","blackout","secondarySource","secondary","rundown","selectedEventIndex","numEvents","plannedStart","plannedEnd","actualStart","actualGroupStart","currentDay","offset","absolute","relative","mode","expectedFlagStart","expectedGroupEnd","expectedRundownEnd","groupNow","eventNow","eventNext","eventFlag","auxtimer1","direction","auxtimer2","auxtimer3","ping","langEn","githubUrl","apiRepoLatest","websiteUrl","discordUrl","subredditUrl","documentationUrl","customFieldsDocsUrl","githubSponsorUrl","buyMeACoffeeUrl","appVersion","version","isDocker","import","isProduction","currentHostName","window","location","hostname","isLocalhost","isOntimeCloud","document","querySelector","hasAttribute","isTouchDevice","navigator","maxTouchPoints","supportsFullscreen","fullscreenEnabled","baseURI","resolveBaseURI","serverURL","resolveUrl","websocketUrl","protocol","path","url","URL","origin","isSecure","pathname","result","toString","endsWith","slice","base","getAttribute","sessionScope","resolveSessionScope","getIsNavigationLocked","URLSearchParams","search","get","tokenCookie","cookie","split","find","startsWith","scope","JSON","parse","APP_INFO","APP_SETTINGS","APP_VERSION","AUTOMATION","CUSTOM_FIELDS","PROJECT_DATA","PROJECT_LIST","PROJECT_RUNDOWNS","RUNDOWN","URL_PRESETS","VIEW_SETTINGS","REPORT","TRANSLATION","apiEntryUrl","userAssetsPath","cssOverridePath","customTranslationsPath","overrideStylesURL","projectLogoPath","customTranslationsURL","MILLIS_PER_SECOND","MILLIS_PER_MINUTE","MILLIS_PER_HOUR","dayInMs","millisToSeconds","millis","seconds","Math","ceil","floor","secondsToMinutes","secondsToHours","secondsInMillis","nanoid","customAlphabet","generateId","pad","val","String","padStart","millisToString","options","fallback","isNegative","totalSeconds","abs","minutes","hours","map","join","removeLeadingZero","removeTrailingZero","removeSeconds","formatFromMillis","format","undefined","date","Date","hour24Padded","getUTCHours","hour24","minutePadded","getUTCMinutes","minute","secondPadded","getUTCSeconds","second","milliseconds","getUTCMilliseconds","hour12","hour12Padded","amPm","applyReplacements","HH","H","hh","h","mm","m","ss","s","S","a","template","replacements","Object","keys","reduce","token","regex","RegExp","replace","isOnlyNumbers","isIPAddress","startsWithHttp","startsWithSlash","isAlphanumeric","isAlphanumericWithSpace","isASCII","isASCIIorEmpty","isNotEmpty","checkRegex","test","isColourHex","regexS","regexD","getErrorMessage","error","obfuscate","str","obfuscated","c","fromCharCode","charCodeAt","unobfuscate","getExpectedStart","event","state","timeStart","dayOffset","delay","totalGap","isLinkedToLoaded","relativeDayOffset","normalisedTimeStart","max","relativeStartOffset","scheduledStartTime","offsetStartTime","mixColours","colour1","colour2","p","w1","w2","red","round","green","blue","alpha","colourToHex","colour","cssOrHexToColour","hexToColour","maybeCssColour","toLocaleLowerCase","CssColours","hexColour","hex","length","alphaPart","parseInt","repeat","number","isNaN","isLightColour","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","goldenrod","gold","gray","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavenderblush","lavender","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","ontimeQueryClient","QueryClient","defaultOptions","queries","gcTime","networkMode","refetchOnWindowFocus","retry","retryDelay","attempt","mutations","navigatorConstants","label","FORMAT_12","FORMAT_24","deepCompare","b","isEqual","runtimeStore","createWithEqualityFn","useRuntimeStore","selector","useStoreWithEqualityFn","patchRuntimeProperty","key","value","getState","setState","patchRuntime","patch","createSelector","setClientRemote","setIdentify","payload","sendSocket","setRedirect","setClientName","useRundownEditor","selectedEventId","id","nextEventId","useTimerViewControl","useTimerMessageInput","useExternalMessageInput","useMessagePreview","showTimerMessage","Boolean","timerType","countToEnd","setMessage","timerText","timerVisible","secondaryMessage","timerBlink","timerBlackout","timerSecondarySource","usePlaybackControl","timerPhase","setPlayback","start","pause","roll","startNext","previous","next","stop","reload","addTime","amount","useAuxTimersTime","aux1","aux2","aux3","useAuxTimerTime","index","useAuxTimerControl","setAuxTimer","setDirection","setDuration","time","useSelectedEventId","useCurrentGroupId","currentGroupId","setEventPlayback","loadEvent","startEvent","useTimer","useClock","useNextFlag","expectedStart","useProgressData","timeWarning","timeDanger","useExpectedStartData","useIsOnline","isOnline","useOffsetMode","offsetMode","setOffsetMode","usePlayback","useStartTimesOverview","useRundownExpectedEnd","expectedEnd","useProgressOverview","useOffsetOverview","useGroupTimerOverView","groupExpectedEnd","useFlagTimerOverView","useTimerSocket","timerTypeNow","countToEndNow","auxTimer","useCountdownSocket","useBackstageSocket","useStudioClockSocket","useStudioTimersSocket","nowInMillis","now","getHours","getMinutes","getSeconds","getMilliseconds","getFormatFromParams","params","href","searchParams","getFormatFromSettings","settings","getQueryData","timeFormat","getDefaultFormat","currentSettings","format12","format24","resolveTimeFormat","fallback12","fallback24","formatFromParams","formatTime","resolver","display","formatDuration","hideSeconds","exactSeconds","min","useTimeUntilExpectedStart","getExpectedTimesFromExtendedEvent","timeToStart","logger","createStore","logs","useLogData","useStore","addLog","log","clearLogs","maybeAxiosError","axios","isAxiosError","statusText","response","data","stringify","unwrapError","logAxiosError","prepend","level","invalidateAllCaches","invalidateQueries","createBlob","fileContent","type","Blob","downloadBlob","blob","fileName","downloadUrl","createObjectURL","link","createElement","setAttribute","body","appendChild","click","revokeObjectURL","booleanFromLocalStorage","valueInStorage","localStorage","getItem","setItem","makeStageKey","clientNameKey","persistNameInStorage","newValue","useClientStore","create","set","name","setName","setId","redirect","clients","setClients","getClientName","setClientId","getClientId","setClientRedirect","useDialogStore","showDialog","clearDialog","setDialog","addDialog","websocket","reconnectTimeout","reconnectInterval","hasConnected","reconnectAttempts","connectSocket","WebSocket","preferredClientName","onopen","clearTimeout","setOnlineStatus","onclose","console","warn","setTimeout","readyState","CLOSED","onerror","onmessage","tag","getTime","clientId","clientName","target","dialog","revision","queryKey","OPEN","send","status","ErrorBoundary","React","Component","constructor","props","reportContent","errorInfo","getDerivedStateFromError","errorMessage","componentDidCatch","info","componentStack","appState","Sentry","setExtras","store","hasSocket","eventId","render","jsx","style","errorContainer","report","encodeURIComponent","process","ipcRenderer","children","IdentifyOverlay","identify","portalRoot","getElementById","createPortal","Overlay","timerRef","useRef","showOverlay","handleClose","useCallback","useEffect","jsxs","overlay","settingsPath","getSettings","postSettings","post","postShowWelcomeDialog","show","ontimePlaceholderSettings","serverPort","editorKey","operatorKey","language","useSettings","isFetching","isError","refetch","useQuery","queryFn","placeholderData","previousData","_previousQuery","select","unobfuscated","AppContext","createContext","editorAuth","operatorAuth","validate","storageKeys","editor","operator","AppContextProvider","setEditorAuth","useState","setOperatorAuth","previousEditor","sessionStorage","previousOperator","pin","permission","isValid","savedPin","correct","PresetContext","canUseWakeLock","useWakelock","keepAwake","useKeepAwakeOptions","wakeLockSentinelRef","removeLock","release","finally","acquireLock","sentinel","released","wakeLock","request","then","catch","controller","AbortController","addEventListener","visibilityState","signal","abort","keepAwakeKey","getOptionsFromParams","defaultValues","has","setSearchParams","useSearchParams","maybePreset","use","useMemo","toggleKeepAwake","delete","KeepAwake","assetsPath","getCSSContents","postCSSContents","css","restoreCSSContents","getUserTranslation","postUserTranslation","translation","queryRefetchIntervalSlow","sessionKeys","cuesheetMode","editorMode","AppMode","Run","Edit","useCustomTranslation","refetchInterval","langDe","langEs","langFr","langIt","langPt","translationsList","en","es","fr","it","de","pt","TranslationContext","userTranslation","getLocalizedString","TranslationProvider","translationData","lang","contextValue","useTranslation","useContext","useViewParamsEditorStore","isOpen","open","close","toggle","throttle","callback","wait","timeout","args","inactiveTime","useFadeOutOnInactivity","initialState","isUserActive","setIsUserActive","fadeOut","throttledShowMenu","setShowMenuTrue","removeEventListener","defaultUiBackground","getAccessibleColour","bgColour","backgroundColor","color","originalColour","backgroundColorMix","textColor","cx","classNames","filter","enDash","timerPlaceholder","timerPlaceholderMin","IconButton","forwardRef","className","variant","size","buttonProps","ref","baseIconButton","displayName","FloatingNavigation","toggleMenu","toggleSettings","isButtonShown","fadeable","buttonContainer","hidden","IoApps","IoSettingsOutline","ViewLockedIcon","isLockIconShown","lockIcon","IoLockClosedOutline","useIsSmallScreen","width","useViewportSize","useViewOptionsStore","mirror","LocalEventKeys","toggleMirror","Button","fluid","loading","baseButton","disabled","content","loadingOverlay","IoEllipseOutline","spinner","title","showCloseButton","showBackdrop","bodyElements","footerElements","onClose","BaseDialog.Root","BaseDialog.Portal","BaseDialog.Backdrop","backdrop","BaseDialog.Popup","IoClose","footer","Input","height","inputProps","input","RenameClientModal","currentName","handleRename","rename","canSubmit","Fragment","isElectron","require","useElectronEvent","sendToElectron","channel","useElectronListener","navigate","useNavigate","on","_event","removeAllListeners","openLink","handleLinks","externalServerUrl","externalBaseURI","preventDefault","destination","linkToOtherHost","host","isKeyEnter","isKeyEscape","preventEscape","stopPropagation","NavigationMenuItem","active","onClick","ClientLink","to","postAction","IoArrowUp","linkIcon","useIsSmallDevice","os","useOs","EditorNavigation","sessionPath","getInfo","generateUrl","ontimePlaceholderInfo","networkInterfaces","publicDir","useInfo","copyToClipboard","clipboard","writeText","safeCopyToClipboard","CopyTag","copyValue","copied","setCopied","timeoutRef","handleClick","copytag","action","copy","IoCheckmark","IoCopy","OtherAddresses","currentLocation","header","interfaces","nif","address","interfaceCopy","goIcon","memo","NavigationMenu","isSmallScreen","isRenameOpen","handlers","useDisclosure","fullscreen","useFullscreen","useLocation","Dialog.Root","Dialog.Portal","Dialog.Backdrop","Dialog.Popup","drawer","Dialog.Title","IoContract","IoExpand","IoSwapVertical","note","LuCoffee","separator","route","ViewNavigationMenu","isNavigationLocked","suppressSettings","isMenuOpen","menuHandler","showEditFormDrawer","useHotkeys","useClientPath","useShallow","urlPresetsPath","getUrlPresets","postUrlPreset","putUrlPreset","alias","put","deleteUrlPreset","useUrlPresets","skip","enabled","useViewUrlPresets","view","viewPresets","preset","useUpdateUrlPreset","queryClient","useQueryClient","addFn","useMutation","mutationFn","onSuccess","newPresets","setQueryData","updateFn","deleteFn","addPreset","mutateAsync","updatePreset","deletePreset","isMutating","isPending","isMutationError","getRouteFromPreset","urlPresets","isPresetPath","currentPath","substring","currentURL","getCurrentPath","isLocked","includes","newPath","generatePathFromPreset","arePathsEquivalent","segments","locked","resolvePath","currentUrl","newUrl","generateUrlPresetOptions","userUrl","sanitisedUrl","toLowerCase","isPresettableView","values","Header","SubHeader","subheader","Title","Section","as","Element","section","Indent","indent","Paragraph","paragraph","Card","card","Table","table","TableEmpty","empty","IoAdd","ListGroup","listGroup","ListItem","listItem","Field","description","fieldTitle","Description","fieldDescription","Highlight","highlight","fieldError","Divider","divider","Loader","isLoading","loader","InlineElements","relation","align","inlineElements","logData","showClient","setShowClient","showServer","setShowServer","showRx","setShowRx","showTx","setShowTx","showPlayback","setShowPlayback","showUser","setShowUser","matchers","push","filteredData","some","entry","match","disableOthers","toEnable","Panel.InlineElements","buttonBar","e","apart","logEntry","msg","ellipsis","SvgEmpty","React.createElement","NotFound","notFound","EmptyImage","scriptTagId","useRuntimeStylesheet","pathToFile","shouldRender","setShouldRender","handleNoStylesheet","fetchStylesheetData","injectStylesheet","remove","fetch","ok","styleContent","styleSheet","innerHTML","head","append","viewSettingsPath","getViewSettings","postViewSettings","viewsSettingsPlaceholder","dangerColor","normalColor","overrideStyles","warningColor","useViewSettings","staleTime","onMutate","cancelQueries","ViewLoader","ONTIME_VERSION","sentryRecommendedIgnore","sentryDsn","initializeSentry","dsn","integrations","useNavigationType","createRoutesFromChildren","matchRoutes","tracesSampleRate","ignoreErrors","denyUrls","beforeSend","exception","Routes","lazy","__vitePreload","EditorFeatureWrapper","RundownPanel","n","TimerControl","MessageControl","SentryRouter","AppRouter","Suspense","Route","Navigate","PresetView","RedirectPreset","PresetViewMap","useParams","showNav","App","QueryClientProvider","Tooltip.Provider","BrowserRouter","ReactQueryDevtools","container","root","createRoot","StrictMode"],"ignoreList":[],"sources":["../../../../packages/types/src/definitions/TimerType.type.ts","../../../../packages/types/src/definitions/core/UrlPreset.type.ts","../../../../packages/types/src/api/websocket/data.type.ts","../../../../packages/types/src/api/websocket/refetch.type.ts","../../../../packages/types/src/definitions/runtime/Logger.type.ts","../../../../packages/types/src/definitions/runtime/Playback.type.ts","../../../../packages/types/src/definitions/runtime/Offset.type.ts","../../../../packages/types/src/definitions/runtime/AuxTimer.type.ts","../../../../packages/types/src/definitions/runtime/TimerState.type.ts","../../../../packages/types/src/definitions/runtime/RuntimeStore.ts","../../../../packages/types/src/translations/index.ts","../../src/externals.ts","../../src/common/api/constants.ts","../../../../packages/utils/src/date-utils/conversionUtils.ts","../../../../packages/utils/src/generate-id/generateId.ts","../../../../packages/utils/src/date-utils/timeFormatting.ts","../../../../packages/utils/src/regex-utils/checkRegex.ts","../../../../packages/utils/src/regex-utils/isColourHex.ts","../../../../packages/utils/src/generic/generic.ts","../../../../packages/utils/src/date-utils/getExpectedStart.ts","../../../../packages/utils/src/colour/colour.utils.ts","../../src/common/queryClient.ts","../../src/viewerConfig.ts","../../src/common/stores/runtime.ts","../../src/common/hooks/useSocket.ts","../../src/common/utils/time.ts","../../src/common/stores/logger.ts","../../src/common/api/utils.ts","../../src/common/utils/localStorage.ts","../../src/common/stores/clientStore.ts","../../src/common/stores/dialogStore.ts","../../src/common/utils/socket.ts","../../src/common/components/error-boundary/ErrorBoundary.jsx","../../src/common/components/identify-overlay/IdentifyOverlay.tsx","../../src/common/api/settings.ts","../../src/common/models/OntimeSettings.ts","../../src/common/hooks-query/useSettings.ts","../../src/common/context/AppContext.tsx","../../src/common/context/PresetContext.tsx","../../src/features/keep-awake/useWakeLock.ts","../../src/features/keep-awake/KeepAwake.tsx","../../src/common/api/assets.ts","../../src/ontimeConfig.ts","../../src/common/hooks-query/useCustomTranslation.ts","../../src/translation/languages/de.ts","../../src/translation/languages/es.ts","../../src/translation/languages/fr.ts","../../src/translation/languages/it.ts","../../src/translation/languages/pt.ts","../../src/translation/TranslationProvider.tsx","../../src/common/components/view-params-editor/viewParamsEditor.store.ts","../../src/common/utils/throttle.ts","../../src/common/hooks/useFadeOutOnInactivity.tsx","../../src/common/utils/styleUtils.ts","../../src/common/components/buttons/IconButton.tsx","../../src/common/components/navigation-menu/floating-navigation/FloatingNavigation.tsx","../../src/common/components/navigation-menu/view-locked-icon/ViewLockedIcon.tsx","../../src/common/hooks/useIsSmallScreen.ts","../../src/common/stores/viewOptions.ts","../../src/common/components/buttons/Button.tsx","../../src/common/components/dialog/Dialog.tsx","../../src/common/components/input/input/Input.tsx","../../src/common/components/client-modal/RenameClientModal.tsx","../../src/common/hooks/useElectronEvent.ts","../../src/common/utils/linkUtils.ts","../../src/common/utils/keyEvent.ts","../../src/common/components/navigation-menu/navigation-menu-item/NavigationMenuItem.tsx","../../src/common/components/navigation-menu/client-link/ClientLink.tsx","../../src/common/hooks/useIsSmallDevice.ts","../../src/common/components/navigation-menu/editor-navigation/EditorNavigation.tsx","../../src/common/api/session.ts","../../src/common/models/Info.ts","../../src/common/hooks-query/useInfo.ts","../../src/common/utils/copyToClipboard.ts","../../src/common/components/copy-tag/CopyTag.tsx","../../src/common/components/navigation-menu/other-addresses/OtherAddresses.tsx","../../src/common/components/navigation-menu/NavigationMenu.tsx","../../src/common/components/navigation-menu/ViewNavigationMenu.tsx","../../src/common/hooks/useClientPath.ts","../../src/common/api/urlPresets.ts","../../src/common/hooks-query/useUrlPresets.ts","../../src/common/utils/urlPresets.ts","../../src/features/app-settings/panel-utils/PanelUtils.tsx","../../src/features/log/Log.tsx","../../src/views/common/loader/Loader.tsx","../../src/assets/images/empty.svg?react","../../src/views/common/not-found/NotFound.tsx","../../src/common/hooks/useRuntimeStylesheet.ts","../../src/common/api/viewSettings.ts","../../src/common/models/ViewSettings.type.ts","../../src/common/hooks-query/useViewSettings.ts","../../src/views/ViewLoader.tsx","../../src/ONTIME_VERSION.js","../../src/sentry.config.ts","../../src/AppRouter.tsx","../../src/App.tsx","../../src/index.tsx"],"sourcesContent":["export enum TimerType {\n CountDown = 'count-down',\n CountUp = 'count-up',\n Clock = 'clock',\n None = 'none',\n}\n","/**\n * Describes all views in Ontime\n */\nexport enum OntimeView {\n Editor = 'editor',\n Cuesheet = 'cuesheet',\n Operator = 'op',\n Timer = 'timer',\n Backstage = 'backstage',\n Timeline = 'timeline',\n StudioClock = 'studio',\n Countdown = 'countdown',\n ProjectInfo = 'info',\n}\n\nexport type OntimeViewPresettable = Exclude<OntimeView, OntimeView.Editor>;\n\ntype BaseURLPreset = {\n target: OntimeViewPresettable;\n enabled: boolean;\n alias: string;\n search: string;\n options?: Record<string, string>;\n};\n\ntype CuesheetUrlPreset = {\n target: OntimeView.Cuesheet;\n enabled: boolean;\n alias: string;\n search: string;\n options: {\n read: string;\n write: string;\n };\n};\n\nexport type URLPreset = BaseURLPreset | CuesheetUrlPreset;\n","import type { Client } from '../../definitions/Clients.type.js';\nimport type { Log } from '../../definitions/runtime/Logger.type.js';\nimport type { RuntimeStore } from '../../definitions/runtime/RuntimeStore.type.js';\nimport type { MaybeNumber } from '../../utils/utils.type.js';\nimport type { RefetchKey } from './refetch.type.js';\n\nexport enum MessageTag {\n Ping = 'ping',\n Pong = 'pong',\n ClientInit = 'client-init',\n ClientSet = 'client-set',\n ClientSetPath = 'client-set-path',\n ClientRename = 'client-rename',\n ClientRedirect = 'client-redirect',\n ClientList = 'client-list',\n Dialog = 'dialog',\n Log = 'log',\n RuntimeData = 'runtime-data',\n Refetch = 'refetch',\n}\n\n// CLIENT TO SERVER\ntype PingPacket = { tag: MessageTag.Ping; payload: Date };\ntype SetClientPacket = { tag: MessageTag.ClientSetPath; payload: string };\ntype SetClientPathPacket = { tag: MessageTag.ClientSet; payload: Partial<Client> };\n\n// SERVER TO CLIENT\ntype PongPacket = { tag: MessageTag.Pong; payload: Date };\ntype InitClientPacket = { tag: MessageTag.ClientInit; payload: { clientId: string; clientName: string } };\ntype RenameClientPacket = { tag: MessageTag.ClientRename; payload: { target: string; name: string } };\ntype RedirectClientPacket = { tag: MessageTag.ClientRedirect; payload: { target: string; path: string } };\ntype DialogPacket = { tag: MessageTag.Dialog; payload: { dialog: string } };\ntype ListClientPacket = {\n tag: MessageTag.ClientList;\n payload: Record<string, Client>;\n};\ntype RuntimePacket = { tag: MessageTag.RuntimeData; payload: Partial<RuntimeStore> };\n\ntype RefetchPacket = {\n tag: MessageTag.Refetch;\n payload: {\n target: RefetchKey;\n revision: MaybeNumber;\n };\n};\n\n// SHARED\ntype LogPacket = { tag: MessageTag.Log; payload: Log };\n\nexport type WsPacketToServer = PingPacket | SetClientPacket | SetClientPathPacket | LogPacket;\nexport type WsPacketToClient =\n | PongPacket\n | InitClientPacket\n | RenameClientPacket\n | RedirectClientPacket\n | DialogPacket\n | LogPacket\n | ListClientPacket\n | RuntimePacket\n | RefetchPacket;\n","export enum RefetchKey {\n All = 'all',\n CustomFields = 'custom-fields',\n ProjectData = 'project-data',\n Report = 'report',\n Rundown = 'rundown',\n UrlPresets = 'url-presets',\n ViewSettings = 'view-settings',\n Translation = 'translation',\n Settings = 'settings',\n}\n","export enum LogLevel {\n Info = 'INFO',\n Warn = 'WARN',\n Error = 'ERROR',\n Severe = 'SEVERE',\n}\n\nexport type Log = {\n id: string;\n origin: string;\n time: string;\n level: LogLevel;\n text: string;\n};\n\nexport type LogMessage = {\n type: 'ontime-log';\n payload: Log;\n};\n\nexport enum LogOrigin {\n Client = 'CLIENT',\n Playback = 'PLAYBACK',\n Rx = 'RX',\n Server = 'SERVER',\n Tx = 'TX',\n User = 'USER',\n}\n","export enum Playback {\n Roll = 'roll',\n Play = 'play',\n Pause = 'pause',\n Stop = 'stop',\n Armed = 'armed',\n}\n","import type { MaybeNumber } from '../../utils/utils.type.js';\n\nexport enum OffsetMode {\n Absolute = 'absolute',\n Relative = 'relative',\n}\n\n/**\n * Offset represents our current position in relation to the planned time\n * a positive value means that we have added extra time to the expected end\n * aka behind schedule\n */\nexport type Offset = {\n /** Current absolute offset: accounts for planned times */\n absolute: number;\n /** Current relative offset: only counts for generated offset since start */\n relative: number;\n /** Currently selected offset mode */\n mode: OffsetMode;\n /** Timestamp of the expected start of the next flag */\n expectedGroupEnd: MaybeNumber;\n /** Timestamp of the expected end of the current group */\n expectedRundownEnd: MaybeNumber;\n /** Timestamp of the expected end of the loaded rundown */\n expectedFlagStart: MaybeNumber;\n};\n","export enum SimplePlayback {\n Start = 'start',\n Pause = 'pause',\n Stop = 'stop',\n}\n\nexport enum SimpleDirection {\n CountUp = 'count-up',\n CountDown = 'count-down',\n}\n\nexport type SimpleTimerState = {\n duration: number;\n current: number;\n playback: SimplePlayback;\n direction: SimpleDirection;\n};\n","import type { MaybeNumber } from '../../utils/utils.type.js';\nimport type { Playback } from './Playback.type.js';\n\nexport enum TimerPhase {\n None = 'none',\n Default = 'default',\n Warning = 'warning',\n Danger = 'danger',\n Overtime = 'overtime',\n /** used for waiting to roll */\n Pending = 'pending',\n}\n\n/**\n * Gathers the current running timer state\n */\nexport type TimerState = {\n /** Additional time added to the running timer, can be negative */\n addedTime: number;\n /** Current running timer countdown */\n current: MaybeNumber;\n /** Total duration of the running event */\n duration: MaybeNumber;\n /** Time elapsed since the timer started */\n elapsed: MaybeNumber;\n /** Timestamp of the expected finish time */\n expectedFinish: MaybeNumber;\n /** Current phase of the running event */\n phase: TimerPhase;\n /** Timer's playback state */\n playback: Playback;\n /** Secondary timer, used to count to an event start in roll mode */\n secondaryTimer: MaybeNumber;\n /** Timestamp when the timer started */\n startedAt: MaybeNumber;\n};\n","import { SimpleDirection, SimplePlayback } from './AuxTimer.type.js';\nimport { OffsetMode } from './Offset.type.js';\nimport { Playback } from './Playback.type.js';\nimport type { RuntimeStore } from './RuntimeStore.type.js';\nimport { TimerPhase } from './TimerState.type.js';\n\nexport const runtimeStorePlaceholder: Readonly<RuntimeStore> = {\n clock: 0,\n timer: {\n addedTime: 0,\n current: null, // changes on every update\n duration: null, // only changes if event changes\n elapsed: null, // changes on every update\n expectedFinish: null, // change can only be initiated by user, can roll over midnight\n phase: TimerPhase.None, // can change on update or user action\n playback: Playback.Stop, // change initiated by user\n secondaryTimer: null, // change on every update\n startedAt: null, // change can only be initiated by user\n },\n message: {\n timer: {\n text: '',\n visible: false,\n blink: false,\n blackout: false,\n secondarySource: null,\n },\n secondary: '',\n },\n rundown: {\n selectedEventIndex: null, // changes if rundown changes or we load a new event\n numEvents: 0, // change initiated by user\n plannedStart: 0, // only changes if event changes\n plannedEnd: 0, // only changes if event changes, overflows over dayInMs\n actualStart: null, // set once we start the timer\n actualGroupStart: null, // maybe set once we start the timer\n currentDay: null,\n },\n offset: {\n absolute: 0, // changes at runtime\n relative: 0, // changes at runtime\n mode: OffsetMode.Absolute,\n expectedFlagStart: null,\n expectedGroupEnd: null,\n expectedRundownEnd: null,\n },\n groupNow: null,\n eventNow: null,\n eventNext: null,\n eventFlag: null,\n auxtimer1: {\n current: 0,\n direction: SimpleDirection.CountUp,\n duration: 0,\n playback: SimplePlayback.Stop,\n },\n auxtimer2: {\n current: 0,\n direction: SimpleDirection.CountUp,\n duration: 0,\n playback: SimplePlayback.Stop,\n },\n auxtimer3: {\n current: 0,\n direction: SimpleDirection.CountUp,\n duration: 0,\n playback: SimplePlayback.Stop,\n },\n ping: 1,\n};\n","export const langEn = {\n 'common.expected_finish': 'Expected Finish',\n 'common.minutes': 'min',\n 'common.seconds': 'sec',\n 'common.now': 'Now',\n 'common.next': 'Next',\n 'common.scheduled_start': 'Scheduled start',\n 'common.scheduled_end': 'Scheduled end',\n 'common.expected_start': 'Expected start',\n 'common.expected_end': 'Expected end',\n 'common.stage_timer': 'Stage Timer',\n 'common.started_at': 'Started At',\n 'common.time_now': 'Time now',\n 'common.no_data': 'No data',\n 'countdown.ended': 'Event ended at',\n 'countdown.running': 'Event running',\n 'countdown.loaded': 'Event loaded',\n 'countdown.select_event': 'Select an event to follow',\n 'countdown.to_start': 'Time to start',\n 'countdown.waiting': 'Waiting for event start',\n 'countdown.overtime': 'in overtime',\n 'timeline.live': 'live',\n 'timeline.done': 'done',\n 'timeline.due': 'due',\n 'timeline.followedby': 'Followed by',\n 'project.title': 'Title',\n 'project.description': 'Description',\n 'project.info': 'Project Info',\n 'project.url': 'Project URL',\n};\n\nexport type TranslationObject = Record<keyof typeof langEn, string>;\n","/**\n * This file contains a list of constants that may need to be resolved at runtime\n */\n\nimport { version } from '../../../package.json';\n\nexport const githubUrl = 'https://www.github.com/cpvalente/ontime';\nexport const apiRepoLatest = 'https://api.github.com/repos/cpvalente/ontime/releases/latest';\nexport const websiteUrl = 'https://www.getontime.no';\nexport const discordUrl = 'https://discord.com/invite/eje3CSUEXm';\nexport const subredditUrl = 'https://www.reddit.com/r/ontimeapp/';\n\nexport const documentationUrl = 'https://docs.getontime.no';\nexport const customFieldsDocsUrl = 'https://docs.getontime.no/features/custom-fields/';\n\nexport const githubSponsorUrl = 'https://github.com/sponsors/cpvalente';\nexport const buyMeACoffeeUrl = 'https://buymeacoffee.com/cpvalente';\n\n// resolve environment\nexport const appVersion = version;\nexport const isDocker = import.meta.env.IS_DOCKER; // this env is made available by the vite.config.js define function\nexport const isProduction = import.meta.env.PROD;\nexport const isDev = import.meta.env.DEV;\nexport const currentHostName = window.location.hostname;\nexport const isLocalhost = currentHostName === 'localhost' || currentHostName === '127.0.0.1';\nexport const isOntimeCloud = document.querySelector('base')?.hasAttribute('data-is-cloud')\n\nexport const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\nexport const supportsFullscreen = document.fullscreenEnabled;\n\n// resolve entrypoint URLs\n\n/**\n * Resolve base\n * @example '' for electron\n * @example '/client-hash' for cloud\n */\nexport const baseURI = resolveBaseURI();\nexport const serverURL = resolveUrl('http', '');\nexport const websocketUrl = resolveUrl('ws', 'ws');\n\nfunction resolveUrl(protocol: 'http' | 'ws', path: string) {\n const url = new URL(window.location.origin);\n\n // generate ws url\n if (protocol === 'ws') {\n // ensure we remain in a secure context\n const isSecure = window.location.protocol === 'https:';\n url.protocol = isSecure ? 'wss' : 'ws';\n }\n\n // make path name relative to the base URI\n url.pathname = baseURI ? `${baseURI}/${path}` : path;\n\n // in development mode, we use the React port for UI, but need the requests to target the server\n // this is done with a proxy in the vite config to avoid CORS issues in the dev environment\n\n const result = url.toString();\n\n // prevent trailing slash\n return result.endsWith('/') ? result.slice(0, -1) : result;\n}\n\n/**\n * Resolves a base URI for a client that is not at the root segment\n * ie: https://cloud.getontime.com/client-hash/timer\n * This is necessary for ontime cloud and should otherwise not affect the client\n */\nfunction resolveBaseURI(): string {\n // in ontime cloud, the base tag is set by the server\n const baseHref = document.querySelector('base')?.getAttribute('href');\n const base = baseHref ?? '';\n\n // prevent a trailing slash from either an empty base or a base with a trailing slash\n if (base.endsWith('/')) {\n return base.slice(0, -1);\n }\n\n return base;\n}\n\n/**\n * Resolves a session scope for the session\n */\nexport const sessionScope = resolveSessionScope();\nexport const getIsNavigationLocked = () => new URLSearchParams(window.location.search).get('n') === '1';\n\n/**\n * The session scope is read from the cookie and will only exist if the app is password protected\n */\nfunction resolveSessionScope() {\n const tokenCookie = document.cookie.split('; ').find((cookie) => cookie.startsWith('token='));\n\n if (tokenCookie) {\n try {\n const { scope } = JSON.parse(tokenCookie.split('=')[1]);\n return scope;\n } catch {\n return 'rw';\n }\n }\n return 'rw';\n}\n","import { serverURL } from '../../externals';\n\n// keys in tanstack store\nexport const APP_INFO = ['appinfo'];\nexport const APP_SETTINGS = ['appSettings'];\nexport const APP_VERSION = ['appVersion'];\nexport const AUTOMATION = ['automation'];\nexport const CUSTOM_FIELDS = ['customFields'];\nexport const PROJECT_DATA = ['project'];\nexport const PROJECT_LIST = ['projectList'];\nexport const PROJECT_RUNDOWNS = ['projectRundowns'];\nexport const RUNDOWN = ['rundown'];\nexport const RUNTIME = ['runtimeStore'];\nexport const URL_PRESETS = ['urlpresets'];\nexport const VIEW_SETTINGS = ['viewSettings'];\nexport const CLIENT_LIST = ['clientList'];\nexport const REPORT = ['report'];\nexport const TRANSLATION = ['translation'];\n\n// API URLs\nexport const apiEntryUrl = `${serverURL}/data`;\n\nconst userAssetsPath = 'user';\nconst cssOverridePath = 'styles/override.css';\nconst customTranslationsPath = 'translations/translations.json';\n\nexport const overrideStylesURL = `${serverURL}/${userAssetsPath}/${cssOverridePath}`;\nexport const projectLogoPath = `${serverURL}/${userAssetsPath}/logo`;\nexport const customTranslationsURL = `${serverURL}/${userAssetsPath}/${customTranslationsPath}`;\n","import type { MaybeNumber } from 'ontime-types';\nimport { TimerType } from 'ontime-types';\n\nexport const MILLIS_PER_SECOND = 1000;\nexport const MILLIS_PER_MINUTE = 1000 * 60;\nexport const MILLIS_PER_HOUR = 1000 * 60 * 60;\n\nexport const dayInMs = 86400000;\nexport const maxDuration = dayInMs - MILLIS_PER_SECOND;\n\n/**\n * Converts value in milliseconds to seconds\n * @param millis\n * @returns\n */\nexport function millisToSeconds(\n millis: MaybeNumber,\n direction: TimerType.CountDown | TimerType.CountUp = TimerType.CountDown,\n) {\n if (millis === null) return 0;\n\n let seconds = 0;\n if (direction === TimerType.CountDown) {\n seconds = Math.ceil(millis / MILLIS_PER_SECOND);\n }\n\n if (direction === TimerType.CountUp) {\n seconds = Math.floor(millis / MILLIS_PER_SECOND);\n }\n\n // this is there to avoid result giving -0\n return seconds === 0 ? 0 : seconds;\n}\n\n/**\n * Converts value in seconds to minutes\n * @param seconds\n * @returns\n */\nexport function secondsToMinutes(seconds: number): number {\n return Math.floor(seconds / 60);\n}\n\n/**\n * Converts value in seconds to hours\n * @param seconds\n * @returns\n */\nexport function secondsToHours(seconds: number): number {\n return Math.floor(seconds / 3600);\n}\n\n/**\n * @description Returns amount of seconds in a date given in milliseconds. For studio clock second indicator\n * @param {MaybeNumber} millis time to format\n * @returns amount of elapsed seconds\n */\nexport function secondsInMillis(millis: MaybeNumber): number {\n if (!millis) {\n return 0;\n }\n return Math.floor((millis % MILLIS_PER_MINUTE) / MILLIS_PER_SECOND);\n}\n","import { customAlphabet } from 'nanoid';\n\nconst nanoid = customAlphabet('1234567890abcdef', 6);\n\n/**\n * Generates a random id from the defined alphabet\n */\nexport const generateId = (): string => nanoid();\n","import type { MaybeNumber, TimerType } from 'ontime-types';\n\nimport { millisToSeconds, secondsToHours, secondsToMinutes } from './conversionUtils.js';\n\nexport function pad(val: number): string {\n return String(val).padStart(2, '0');\n}\n\ntype FormatOptions = {\n fallback?: string;\n direction?: TimerType.CountDown | TimerType.CountUp;\n};\n\n/**\n * Converts a value in milliseconds to its time tag\n * @param millis time to convert\n * @param options optional overloads for format\n * @returns formatted time such as 12:00:00\n */\nexport function millisToString(millis?: MaybeNumber, options?: FormatOptions): string {\n if (millis == null) {\n return options?.fallback ?? '...';\n }\n\n const isNegative = millis < 0;\n\n const totalSeconds = Math.abs(millisToSeconds(millis, options?.direction));\n const seconds = totalSeconds % 60;\n const minutes = secondsToMinutes(totalSeconds) % 60;\n const hours = secondsToHours(totalSeconds);\n\n return `${isNegative ? '-' : ''}${[hours, minutes, seconds].map(pad).join(':')}`;\n}\n\n/**\n * Receives a string such as 00:10:10 and removes the hours field if it is 00\n * @param timer\n */\nexport function removeLeadingZero(timer: string): string {\n if (timer.startsWith('00:0')) {\n return timer.slice(4);\n }\n if (timer.startsWith('00:')) {\n return timer.slice(3);\n }\n if (timer.startsWith('-00:0')) {\n return `-${timer.slice(5)}`;\n }\n if (timer.startsWith('-00:')) {\n return `-${timer.slice(4)}`;\n }\n return timer;\n}\n\n/**\n * Receives a string such as 00:10:10 and removes the seconds field if it is 00\n * @param timer\n */\nexport function removeTrailingZero(timer: string): string {\n if (timer.endsWith(':00')) {\n return timer.slice(0, -3);\n }\n return timer;\n}\n\n/**\n * Receives a string such as 00:10:10 and removes the seconds field\n * @param timer\n */\nexport function removeSeconds(timer: string): string {\n return timer.slice(0, -3);\n}\n\n/**\n * Formats a given date into a custom string format based on UTC time.\n *\n * @param millis - The number of milliseconds.\n * @param format - A string specifying the desired output format.\n * For example, 'ss' will format the millis as '07' seconds.\n *\n * @returns The formatted date as a string according to the provided `format` string.\n * If input `millis` is smaller than zero, it returns undefined.\n *\n */\nexport function formatFromMillis(millis: number, format: string): string | undefined {\n if (millis < 0) {\n return undefined;\n }\n\n const date: Date = new Date(millis);\n\n const hour24Padded = date.getUTCHours().toString().padStart(2, '0');\n const hour24 = date.getUTCHours().toString();\n const minutePadded = date.getUTCMinutes().toString().padStart(2, '0');\n const minute = date.getUTCMinutes().toString();\n const secondPadded = date.getUTCSeconds().toString().padStart(2, '0');\n const second = date.getUTCSeconds().toString();\n const milliseconds = date.getUTCMilliseconds().toString().padStart(3, '0');\n const hour12 = (date.getUTCHours() % 12 || 12).toString();\n const hour12Padded = hour12.padStart(2, '0');\n const amPm = date.getUTCHours() >= 12 ? 'PM' : 'AM';\n\n const replacements: Record<string, string> = {\n HH: hour24Padded,\n H: hour24,\n hh: hour12Padded,\n h: hour12,\n mm: minutePadded,\n m: minute,\n ss: secondPadded,\n s: second,\n S: milliseconds,\n a: amPm,\n };\n\n return applyReplacements(format, replacements);\n}\n\n/**\n * Applies replacements to a template string based on a dictionary of tokens and their corresponding values.\n *\n * @param {string} template - The format template string containing tokens to be replaced.\n * @param {Record<string, string>} replacements - A record of tokens and their corresponding values.\n * @returns {string} The formatted string with all tokens replaced by their values.\n */\nfunction applyReplacements(template: string, replacements: Record<string, string>): string {\n return Object.keys(replacements).reduce((result, token) => {\n const regex = new RegExp(`\\\\b${token}\\\\b`, 'g');\n return result.replace(regex, replacements[token]);\n }, template);\n}\n","export const regex = {\n isOnlyNumbers: /^\\d+$/,\n isIPAddress: /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$/,\n startsWithHttp: /^https?:\\/\\//,\n startsWithSlash: /^\\//,\n isAlphanumeric: /^[a-z0-9]+$/i,\n isAlphanumericWithSpace: /^[a-z0-9_ ]+$/i,\n isASCII: /^[ -~]+$/, // https://catonmat.net/my-favorite-regex\n isASCIIorEmpty: /^$|^[ -~]+$/, // https://catonmat.net/my-favorite-regex\n isNotEmpty: /\\S/,\n};\n\nexport const checkRegex = {\n isOnlyNumbers: (text: string): boolean => regex.isOnlyNumbers.test(text),\n isIPAddress: (text: string): boolean => regex.isIPAddress.test(text),\n startsWithHttp: (text: string): boolean => regex.startsWithHttp.test(text),\n startsWithSlash: (text: string): boolean => regex.startsWithSlash.test(text),\n isAlphanumeric: (text: string): boolean => regex.isAlphanumeric.test(text),\n isAlphanumericWithSpace: (text: string): boolean => regex.isAlphanumericWithSpace.test(text),\n isASCII: (text: string): boolean => regex.isASCII.test(text),\n isASCIIorEmpty: (text: string): boolean => regex.isASCIIorEmpty.test(text),\n isNotEmpty: (text: string): boolean => regex.isNotEmpty.test(text),\n};\n","/**\n * @description Validates a colour hex string\n * @param {string} text - colour hex string \"#FFF\" | \"#FFFF\" | \"#FFFFFF\" | \"#FFFFFFFF\"\n * @returns {boolean} string represents time\n */\nexport const isColourHex = (text: string): boolean => {\n const regexS = /^#((?:[a-f\\d]{1}){3,4})$/i;\n const regexD = /^#((?:[a-f\\d]{2}){3,4})$/i;\n return regexS.test(text) || regexD.test(text);\n};\n","export function getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\n/**\n * Obfuscate a string\n * Uses a variation of ROT13 that handles numeric values\n * @param str\n * @returns\n */\nexport function obfuscate(str: string): string {\n const obfuscated = str.replace(/[a-zA-Z0-9]/g, (c) => {\n if (/[a-zA-Z]/.test(c)) {\n // @ts-expect-error -- we use some javascript magic here\n return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);\n } else {\n // @ts-expect-error -- we use some javascript magic here\n\n return String.fromCharCode((c <= '4' ? 57 : 48) >= (c = c.charCodeAt(0) + 5) ? c : c - 10);\n }\n });\n if (str.startsWith('_')) {\n return obfuscated.replace('_', '');\n }\n return `_${obfuscated}`;\n}\n\n/**\n * Unobfoscate a string\n * Uses a variation of ROT13 that handles numeric values\n * @param str\n * @returns\n */\nexport function unobfuscate(str: string): string {\n if (str.startsWith('_')) {\n return obfuscate(str);\n }\n return str;\n}\n","import type { MaybeNumber, OntimeEvent } from 'ontime-types';\nimport { OffsetMode } from 'ontime-types';\n\nimport { dayInMs } from './conversionUtils.js';\n\n/**\n * @param event the event that we are counting to\n * @param currentDay the day offset of the currently running event\n * @param totalGap accumulated gap from the current event\n * @param isLinkedToLoaded is this event part of a chain linking back to the current loaded event\n * @param clock\n * @param offset\n * @returns\n */\nexport function getExpectedStart(\n event: Pick<OntimeEvent, 'timeStart' | 'dayOffset' | 'delay'>,\n state: {\n currentDay: number; // the current day from the rundown\n totalGap: number;\n isLinkedToLoaded: boolean;\n offset: number;\n mode: OffsetMode;\n actualStart: MaybeNumber;\n plannedStart: MaybeNumber;\n },\n): number {\n const { timeStart, dayOffset, delay } = event;\n const { currentDay, totalGap, isLinkedToLoaded, offset, mode, actualStart, plannedStart } = state;\n\n //How many days from the currently running event to this one\n const relativeDayOffset = dayOffset - currentDay;\n\n const delayedStart = Math.max(0, timeStart + delay);\n\n //The normalised start time of this event relative to the currently running event\n const normalisedTimeStart = delayedStart + relativeDayOffset * dayInMs;\n\n let relativeStartOffset = 0;\n\n if (mode === OffsetMode.Relative) {\n relativeStartOffset = (actualStart ?? 0) + currentDay * dayInMs - (plannedStart ?? 0);\n }\n\n const scheduledStartTime = normalisedTimeStart + relativeStartOffset;\n\n const offsetStartTime = scheduledStartTime + offset;\n\n if (isLinkedToLoaded) {\n //if we are directly linked back to the loaded event we just follow the offset\n return offsetStartTime;\n }\n\n const gapsCanCompensateForOffset = totalGap > offset;\n if (gapsCanCompensateForOffset) {\n // if we are ahead of schedule or the gap can compensate for the amount we are behind then expect to start at the scheduled time\n return scheduledStartTime;\n }\n\n // otherwise consume as much of the offset as possible with the gap\n const offsetStartTimeBufferedByGaps = offsetStartTime - totalGap;\n return offsetStartTimeBufferedByGaps;\n}\n","import type { RGBColour } from 'ontime-types';\n\nimport { isColourHex } from '../regex-utils/isColourHex.js';\n\n// naive colour mix\nexport function mixColours(colour1: RGBColour, colour2: RGBColour, p: number = 0.5) {\n const w1 = p;\n const w2 = 1 - w1;\n\n return {\n red: Math.round(colour1.red * w1 + colour2.red * w2),\n green: Math.round(colour1.green * w1 + colour2.green * w2),\n blue: Math.round(colour1.blue * w1 + colour2.blue * w2),\n alpha: 1,\n };\n}\n\nexport function colourToHex(colour: RGBColour): string {\n const alpha = Math.round(colour.alpha * 255)\n .toString(16)\n .padStart(2, '0');\n const red = colour.red.toString(16).padStart(2, '0');\n const green = colour.green.toString(16).padStart(2, '0');\n const blue = colour.blue.toString(16).padStart(2, '0');\n return '#' + red + green + blue + alpha;\n}\n\nexport function cssOrHexToColour(colour: string): RGBColour | null {\n if (colour.startsWith('#')) return hexToColour(colour);\n const maybeCssColour = colour.toLocaleLowerCase();\n if (maybeCssColour in CssColours) {\n return hexToColour(CssColours[maybeCssColour]);\n }\n return null;\n}\n\nexport function hexToColour(hexColour: string): RGBColour | null {\n if (!isColourHex(hexColour)) return null;\n let hex = hexColour.toLocaleLowerCase();\n hex = hex.replace(/^#/, '');\n\n let alpha = 1;\n\n // full length hex #FFFFFFFF\n if (hex.length === 8) {\n const alphaPart = hex.slice(6, 8);\n alpha = parseInt(alphaPart, 16) / 255;\n hex = hex.slice(0, 6);\n }\n\n // compressed hex with alpha #FFFF\n if (hex.length === 4) {\n const alphaPart = hex.slice(3, 4).repeat(2);\n alpha = parseInt(alphaPart, 16) / 255;\n hex = hex.slice(0, 3);\n }\n\n // compressed hex without alpha or after the alpha channel has been removed\n // here all the values duplicated to create a 6 length hex value\n if (hex.length === 3) {\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n\n const number = parseInt(hex, 16);\n const red = number >> 16;\n const green = (number >> 8) & 255;\n const blue = number & 255;\n\n if (isNaN(red) || isNaN(green) || isNaN(blue) || isNaN(alpha)) return null;\n\n return { red, green, blue, alpha };\n}\n\n/**\n * Calculates if black or white is the best contras\n *\n * @returns true if the colour is light -> the best contrast is black\n *\n * is done with YIQ calculation\n * @link https://24ways.org/2010/calculating-color-contrast\n */\nexport function isLightColour(colour: RGBColour): boolean {\n const yiq = (colour.red * 299 + colour.green * 587 + colour.blue * 114) / 1000;\n return yiq >= 128;\n}\n\n//https://developer.mozilla.org/en-US/docs/Web/CSS/named-color\nexport const CssColours: Record<string, string> = {\n aliceblue: '#f0f8ff',\n antiquewhite: '#faebd7',\n aqua: '#00ffff',\n aquamarine: '#7fffd4',\n azure: '#f0ffff',\n beige: '#f5f5dc',\n bisque: '#ffe4c4',\n black: '#000000',\n blanchedalmond: '#ffebcd',\n blue: '#0000ff',\n blueviolet: '#8a2be2',\n brown: '#a52a2a',\n burlywood: '#deb887',\n cadetblue: '#5f9ea0',\n chartreuse: '#7fff00',\n chocolate: '#d2691e',\n coral: '#ff7f50',\n cornflowerblue: '#6495ed',\n cornsilk: '#fff8dc',\n crimson: '#dc143c',\n cyan: '#00ffff',\n darkblue: '#00008b',\n darkcyan: '#008b8b',\n darkgoldenrod: '#b8860b',\n darkgray: '#a9a9a9',\n darkgreen: '#006400',\n darkgrey: '#a9a9a9',\n darkkhaki: '#bdb76b',\n darkmagenta: '#8b008b',\n darkolivegreen: '#556b2f',\n darkorange: '#ff8c00',\n darkorchid: '#9932cc',\n darkred: '#8b0000',\n darksalmon: '#e9967a',\n darkseagreen: '#8fbc8f',\n darkslateblue: '#483d8b',\n darkslategray: '#2f4f4f',\n darkslategrey: '#2f4f4f',\n darkturquoise: '#00ced1',\n darkviolet: '#9400d3',\n deeppink: '#ff1493',\n deepskyblue: '#00bfff',\n dimgray: '#696969',\n dimgrey: '#696969',\n dodgerblue: '#1e90ff',\n firebrick: '#b22222',\n floralwhite: '#fffaf0',\n forestgreen: '#228b22',\n fuchsia: '#ff00ff',\n gainsboro: '#dcdcdc',\n ghostwhite: '#f8f8ff',\n goldenrod: '#daa520',\n gold: '#ffd700',\n gray: '#808080',\n green: '#008000',\n greenyellow: '#adff2f',\n grey: '#808080',\n honeydew: '#f0fff0',\n hotpink: '#ff69b4',\n indianred: '#cd5c5c',\n indigo: '#4b0082',\n ivory: '#fffff0',\n khaki: '#f0e68c',\n lavenderblush: '#fff0f5',\n lavender: '#e6e6fa',\n lawngreen: '#7cfc00',\n lemonchiffon: '#fffacd',\n lightblue: '#add8e6',\n lightcoral: '#f08080',\n lightcyan: '#e0ffff',\n lightgoldenrodyellow: '#fafad2',\n lightgray: '#d3d3d3',\n lightgreen: '#90ee90',\n lightgrey: '#d3d3d3',\n lightpink: '#ffb6c1',\n lightsalmon: '#ffa07a',\n lightseagreen: '#20b2aa',\n lightskyblue: '#87cefa',\n lightslategray: '#778899',\n lightslategrey: '#778899',\n lightsteelblue: '#b0c4de',\n lightyellow: '#ffffe0',\n lime: '#00ff00',\n limegreen: '#32cd32',\n linen: '#faf0e6',\n magenta: '#ff00ff',\n maroon: '#800000',\n mediumaquamarine: '#66cdaa',\n mediumblue: '#0000cd',\n mediumorchid: '#ba55d3',\n mediumpurple: '#9370db',\n mediumseagreen: '#3cb371',\n mediumslateblue: '#7b68ee',\n mediumspringgreen: '#00fa9a',\n mediumturquoise: '#48d1cc',\n mediumvioletred: '#c71585',\n midnightblue: '#191970',\n mintcream: '#f5fffa',\n mistyrose: '#ffe4e1',\n moccasin: '#ffe4b5',\n navajowhite: '#ffdead',\n navy: '#000080',\n oldlace: '#fdf5e6',\n olive: '#808000',\n olivedrab: '#6b8e23',\n orange: '#ffa500',\n orangered: '#ff4500',\n orchid: '#da70d6',\n palegoldenrod: '#eee8aa',\n palegreen: '#98fb98',\n paleturquoise: '#afeeee',\n palevioletred: '#db7093',\n papayawhip: '#ffefd5',\n peachpuff: '#ffdab9',\n peru: '#cd853f',\n pink: '#ffc0cb',\n plum: '#dda0dd',\n powderblue: '#b0e0e6',\n purple: '#800080',\n rebeccapurple: '#663399',\n red: '#ff0000',\n rosybrown: '#bc8f8f',\n royalblue: '#4169e1',\n saddlebrown: '#8b4513',\n salmon: '#fa8072',\n sandybrown: '#f4a460',\n seagreen: '#2e8b57',\n seashell: '#fff5ee',\n sienna: '#a0522d',\n silver: '#c0c0c0',\n skyblue: '#87ceeb',\n slateblue: '#6a5acd',\n slategray: '#708090',\n slategrey: '#708090',\n snow: '#fffafa',\n springgreen: '#00ff7f',\n steelblue: '#4682b4',\n tan: '#d2b48c',\n teal: '#008080',\n thistle: '#d8bfd8',\n tomato: '#ff6347',\n turquoise: '#40e0d0',\n violet: '#ee82ee',\n wheat: '#f5deb3',\n white: '#ffffff',\n whitesmoke: '#f5f5f5',\n yellow: '#ffff00',\n yellowgreen: '#9acd3',\n} as const;\n","import { QueryClient } from '@tanstack/react-query';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport { isOntimeCloud } from '../externals';\n\nexport const ontimeQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n gcTime: 10 * MILLIS_PER_MINUTE,\n // staleTime: MILLIS_PER_HOUR, //TODO: when all routes have implemented refetch signal from server, we can the assume that the data is not stale until we get the signal\n networkMode: 'always',\n refetchOnWindowFocus: false,\n retry: 5,\n retryDelay: (attempt) => attempt * 2500,\n },\n mutations: {\n /**\n * React Query detects whether the client is online\n * However, web access is not required for the clients when deployed locally\n * - use 'always' for clients that may be online\n * - use 'online' for clients that are connected to the cloud\n */\n networkMode: isOntimeCloud ? 'online' : 'always',\n },\n },\n});\n","export const navigatorConstants = [\n { url: 'timer', label: 'Timer' },\n { url: 'backstage', label: 'Backstage' },\n { url: 'timeline', label: 'Timeline' },\n { url: 'studio', label: 'Studio Clock' },\n { url: 'countdown', label: 'Countdown' },\n { url: 'info', label: 'Project Info' },\n];\n\n// default time format to use for users in 12 hour clocks\nexport const FORMAT_12 = 'h:mm:ss a';\n// default time format to use for users in 24 hour clocks\nexport const FORMAT_24 = 'HH:mm:ss';\n","import isEqual from 'react-fast-compare';\nimport { RuntimeStore, runtimeStorePlaceholder } from 'ontime-types';\nimport { createWithEqualityFn, useStoreWithEqualityFn } from 'zustand/traditional';\n\nconst deepCompare = <T>(a: T, b: T) => isEqual(a, b);\n\nexport const runtimeStore = createWithEqualityFn<RuntimeStore>(\n () => ({\n ...runtimeStorePlaceholder,\n }),\n deepCompare,\n);\n\nexport const useRuntimeStore = <T>(selector: (state: RuntimeStore) => T) =>\n useStoreWithEqualityFn(runtimeStore, selector, deepCompare);\n\n/**\n * Allows patching a property of the runtime store\n */\nexport function patchRuntimeProperty<K extends keyof RuntimeStore>(key: K, value: RuntimeStore[K]) {\n const state = runtimeStore.getState();\n state[key] = value;\n runtimeStore.setState({ ...state });\n}\n\n/**\n * Allows patching the entire runtime store\n */\nexport function patchRuntime(patch: Partial<RuntimeStore>) {\n const state = runtimeStore.getState();\n runtimeStore.setState({ ...state, ...patch });\n}\n","import { OffsetMode, RuntimeStore, SimpleDirection, SimplePlayback, TimerMessage, TimerType } from 'ontime-types';\n\nimport { useRuntimeStore } from '../stores/runtime';\nimport { sendSocket } from '../utils/socket';\n\nconst createSelector =\n <T>(selector: (state: RuntimeStore) => T) =>\n () =>\n useRuntimeStore(selector);\n\nexport const setClientRemote = {\n setIdentify: (payload: { target: string; identify: boolean }) => sendSocket('client', payload),\n setRedirect: (payload: { target: string; redirect: string }) => {\n sendSocket('client', payload);\n },\n setClientName: (payload: { target: string; rename: string }) => sendSocket('client', payload),\n};\n\nexport const useRundownEditor = createSelector((state: RuntimeStore) => ({\n playback: state.timer.playback,\n selectedEventId: state.eventNow?.id ?? null,\n nextEventId: state.eventNext?.id ?? null,\n}));\n\nexport const useTimerViewControl = createSelector((state: RuntimeStore) => ({\n blackout: state.message.timer.blackout,\n blink: state.message.timer.blink,\n secondarySource: state.message.timer.secondarySource,\n}));\n\nexport const useTimerMessageInput = createSelector((state: RuntimeStore) => ({\n text: state.message.timer.text,\n visible: state.message.timer.visible,\n}));\n\nexport const useExternalMessageInput = createSelector((state: RuntimeStore) => ({\n text: state.message.secondary,\n visible: state.message.timer.secondarySource === 'secondary',\n}));\n\nexport const useMessagePreview = createSelector((state: RuntimeStore) => ({\n blink: state.message.timer.blink,\n blackout: state.message.timer.blackout,\n phase: state.timer.phase,\n secondarySource: state.message.timer.secondarySource,\n showTimerMessage: state.message.timer.visible && Boolean(state.message.timer.text),\n timerType: state.eventNow?.timerType ?? null,\n countToEnd: state.eventNow?.countToEnd ?? false,\n}));\n\nexport const setMessage = {\n timerText: (payload: string) => sendSocket('message', { timer: { text: payload } }),\n timerVisible: (payload: boolean) => sendSocket('message', { timer: { visible: payload } }),\n secondaryMessage: (payload: string) => sendSocket('message', { secondary: payload }),\n timerBlink: (payload: boolean) => sendSocket('message', { timer: { blink: payload } }),\n timerBlackout: (payload: boolean) => sendSocket('message', { timer: { blackout: payload } }),\n timerSecondarySource: (payload: TimerMessage['secondarySource']) =>\n sendSocket('message', { timer: { secondarySource: payload } }),\n};\n\nexport const usePlaybackControl = createSelector((state: RuntimeStore) => ({\n playback: state.timer.playback,\n selectedEventIndex: state.rundown.selectedEventIndex,\n numEvents: state.rundown.numEvents,\n timerPhase: state.timer.phase,\n}));\n\nexport const setPlayback = {\n start: () => sendSocket('start', undefined),\n pause: () => sendSocket('pause', undefined),\n roll: () => sendSocket('roll', undefined),\n startNext: () => sendSocket('start', 'next'),\n previous: () => {\n sendSocket('load', 'previous');\n },\n next: () => {\n sendSocket('load', 'next');\n },\n stop: () => {\n sendSocket('stop', undefined);\n },\n reload: () => {\n sendSocket('reload', undefined);\n },\n addTime: (amount: number) => {\n sendSocket('addtime', amount);\n },\n};\n\nexport const useAuxTimersTime = createSelector((state: RuntimeStore) => {\n return {\n aux1: state.auxtimer1.current,\n aux2: state.auxtimer2.current,\n aux3: state.auxtimer3.current,\n };\n});\n\nexport const useAuxTimerTime = (index: number) =>\n createSelector((state: RuntimeStore) => {\n if (index === 1) return state.auxtimer1.current;\n if (index === 2) return state.auxtimer2.current;\n return state.auxtimer3.current;\n })();\n\nexport const useAuxTimerControl = (index: number) =>\n createSelector((state: RuntimeStore) => {\n if (index === 1)\n return {\n playback: state.auxtimer1.playback,\n direction: state.auxtimer1.direction,\n };\n if (index === 2)\n return {\n playback: state.auxtimer2.playback,\n direction: state.auxtimer2.direction,\n };\n return {\n playback: state.auxtimer3.playback,\n direction: state.auxtimer3.direction,\n };\n })();\n\nexport const setAuxTimer = {\n start: (index: number) => sendSocket('auxtimer', { [index]: SimplePlayback.Start }),\n pause: (index: number) => sendSocket('auxtimer', { [index]: SimplePlayback.Pause }),\n stop: (index: number) => sendSocket('auxtimer', { [index]: SimplePlayback.Stop }),\n setDirection: (index: number, direction: SimpleDirection) => sendSocket('auxtimer', { [index]: { direction } }),\n setDuration: (index: number, time: number) => sendSocket('auxtimer', { [index]: { duration: time } }),\n};\n\nexport const useSelectedEventId = createSelector((state: RuntimeStore) => ({\n selectedEventId: state.eventNow?.id ?? null,\n}));\n\nexport const useCurrentGroupId = createSelector((state: RuntimeStore) => ({\n currentGroupId: state.groupNow?.id ?? null,\n}));\n\nexport const setEventPlayback = {\n loadEvent: (id: string) => sendSocket('load', { id }),\n startEvent: (id: string) => sendSocket('start', { id }),\n start: () => sendSocket('start', undefined),\n pause: () => sendSocket('pause', undefined),\n};\n\nexport const useTimer = createSelector((state: RuntimeStore) => ({\n ...state.timer,\n}));\n\nexport const useClock = createSelector((state: RuntimeStore) => ({\n clock: state.clock,\n}));\n\nexport const useNextFlag = createSelector((state: RuntimeStore) => ({\n id: state.eventFlag?.id ?? null,\n expectedStart: state.offset.expectedFlagStart,\n}));\n\n/** Used by the progress bar components */\nexport const useProgressData = createSelector((state: RuntimeStore) => ({\n current: state.timer.current,\n duration: state.timer.duration,\n timeWarning: state.eventNow?.timeWarning ?? null,\n timeDanger: state.eventNow?.timeDanger ?? null,\n}));\n\nexport const useExpectedStartData = createSelector((state: RuntimeStore) => ({\n offset: state.offset.mode === OffsetMode.Absolute ? state.offset.absolute : state.offset.relative,\n mode: state.offset.mode,\n currentDay: state.rundown.currentDay ?? 0,\n actualStart: state.rundown.actualStart,\n plannedStart: state.rundown.plannedStart,\n clock: state.clock,\n}));\n\nexport const usePing = createSelector((state: RuntimeStore) => ({\n ping: state.ping,\n}));\n\n/** convert ping into a derived value which changes less often */\nexport const useIsOnline = createSelector((state: RuntimeStore) => ({\n isOnline: state.ping > 0,\n}));\n\nexport const useOffsetMode = createSelector((state: RuntimeStore) => ({\n offsetMode: state.offset.mode,\n}));\n\nexport const setOffsetMode = (payload: OffsetMode) => sendSocket('offsetmode', payload);\n\nexport const usePlayback = () => {\n const featureSelector = (state: RuntimeStore) => ({\n playback: state.timer.playback,\n });\n\n return useRuntimeStore(featureSelector);\n};\n\n/* ======================= Overview data subscriptions ======================= */\n\nexport const useStartTimesOverview = createSelector((state: RuntimeStore) => ({\n plannedStart: state.rundown.plannedStart,\n actualStart: state.rundown.actualStart,\n plannedEnd: state.rundown.plannedEnd,\n}));\n\nexport const useRundownExpectedEnd = createSelector((state: RuntimeStore) => ({\n expectedEnd: state.offset.expectedRundownEnd,\n}));\n\nexport const useProgressOverview = createSelector((state: RuntimeStore) => ({\n numEvents: state.rundown.numEvents,\n selectedEventIndex: state.rundown.selectedEventIndex,\n}));\n\nexport const useOffsetOverview = createSelector((state: RuntimeStore) => ({\n offset: state.offset.mode === OffsetMode.Absolute ? state.offset.absolute : state.offset.relative,\n playback: state.timer.playback,\n}));\n\nexport const useGroupTimerOverView = createSelector((state: RuntimeStore) => ({\n clock: state.clock,\n mode: state.offset.mode,\n groupExpectedEnd: state.offset.expectedGroupEnd,\n // we can force these numbers to 0 fo this use case to avoid null checks\n actualGroupStart: state.rundown.actualGroupStart ?? 0,\n currentDay: state.eventNow?.dayOffset ?? 0,\n playback: state.timer.playback,\n}));\n\nexport const useFlagTimerOverView = createSelector((state: RuntimeStore) => ({\n clock: state.clock,\n mode: state.offset.mode,\n // we can force these numbers to 0 fo this use case to avoid null checks\n actualStart: state.rundown.actualStart ?? 0,\n plannedStart: state.rundown.plannedStart ?? 0,\n currentDay: state.eventNow?.dayOffset ?? 0,\n playback: state.timer.playback,\n}));\n\n/* ======================= View specific subscriptions ======================= */\n\nexport const useTimerSocket = createSelector((state: RuntimeStore) => ({\n eventNext: state.eventNext,\n eventNow: state.eventNow,\n message: state.message,\n time: state.timer,\n clock: state.clock,\n timerTypeNow: state.eventNow?.timerType ?? TimerType.CountDown,\n countToEndNow: state.eventNow?.countToEnd ?? false,\n auxTimer: {\n aux1: state.auxtimer1.current,\n aux2: state.auxtimer2.current,\n aux3: state.auxtimer3.current,\n },\n}));\n\nexport const useCountdownSocket = createSelector((state: RuntimeStore) => ({\n playback: state.timer.playback,\n current: state.timer.current,\n clock: state.clock,\n}));\n\nexport const useBackstageSocket = createSelector((state: RuntimeStore) => ({\n eventNext: state.eventNext,\n eventNow: state.eventNow,\n rundown: state.rundown,\n selectedEventId: state.eventNow?.id ?? null,\n time: state.timer,\n}));\n\nexport const useStudioClockSocket = createSelector((state: RuntimeStore) => ({\n clock: state.clock,\n playback: state.timer.playback,\n}));\n\nexport const useStudioTimersSocket = createSelector((state: RuntimeStore) => ({\n eventNext: state.eventNext,\n eventNow: state.eventNow,\n message: state.message,\n time: state.timer,\n offset: state.offset.mode === OffsetMode.Absolute ? state.offset.absolute : state.offset.relative,\n rundown: state.rundown,\n expectedRundownEnd: state.offset.expectedRundownEnd,\n}));\n","import { MaybeNumber, OntimeEvent, Settings, TimeFormat } from 'ontime-types';\nimport {\n formatFromMillis,\n getExpectedStart,\n MILLIS_PER_HOUR,\n MILLIS_PER_MINUTE,\n MILLIS_PER_SECOND,\n} from 'ontime-utils';\n\nimport { FORMAT_12, FORMAT_24 } from '../../viewerConfig';\nimport { APP_SETTINGS } from '../api/constants';\nimport { useExpectedStartData } from '../hooks/useSocket';\nimport { ontimeQueryClient } from '../queryClient';\n\nimport { ExtendedEntry } from './rundownMetadata';\n\n/**\n * Returns current time in milliseconds from midnight\n * @returns {number}\n */\nexport function nowInMillis(): number {\n const now = new Date();\n\n // extract milliseconds since midnight\n let elapsed = now.getHours() * MILLIS_PER_HOUR;\n elapsed += now.getMinutes() * MILLIS_PER_MINUTE;\n elapsed += now.getSeconds() * MILLIS_PER_SECOND;\n elapsed += now.getMilliseconds();\n\n return elapsed;\n}\n\n/**\n * @description Resolves format from url and store\n * @return {string|null} A format string like \"hh:mm:ss a\" or null\n */\nfunction getFormatFromParams() {\n const params = new URL(document.location.href).searchParams;\n return params.get('timeformat');\n}\n\n/**\n * Gets the format options from the applicaton settings\n * @returns a string equivalent to the format, ie: hh:mm:ss a or HH:mm:ss\n */\nfunction getFormatFromSettings(): TimeFormat {\n const settings: Settings | undefined = ontimeQueryClient.getQueryData(APP_SETTINGS);\n return settings?.timeFormat ?? '24';\n}\n\nexport function getDefaultFormat(\n currentSettings?: TimeFormat,\n format12: string = FORMAT_12,\n format24: string = FORMAT_24,\n): string {\n if (currentSettings === '12') {\n return format12;\n }\n return format24;\n}\n\nfunction resolveTimeFormat(fallback12: string, fallback24: string): string {\n // if the user has an option, we use that\n const formatFromParams = getFormatFromParams();\n if (formatFromParams) {\n return formatFromParams;\n }\n\n // otherwise we use the view defined, with respect to the 12-24 hour settings\n const formatFromSettings = getFormatFromSettings();\n if (formatFromSettings === '12') {\n return fallback12;\n }\n\n return fallback24;\n}\n\ntype FormatOptions = {\n format12: string;\n format24: string;\n};\n\n/**\n * @description viewer specific utility function to format a date in 12 or 24 hour format\n * @param {MaybeNumber} milliseconds\n * @param {object} [options]\n * @param {string} [options.format.format12] format string if 12 hour time\n * @param {string} [options.format.format24] format string if 24 hour time\n * @param {Function} resolver DI for testing\n * @return {string}\n */\nexport const formatTime = (\n milliseconds: MaybeNumber,\n options?: FormatOptions,\n resolver = resolveTimeFormat,\n): string => {\n if (milliseconds === null) {\n return '...';\n }\n\n const timeFormat = resolver(options?.format12 ?? FORMAT_12, options?.format24 ?? FORMAT_24);\n const display = formatFromMillis(Math.abs(milliseconds), timeFormat);\n\n const isNegative = milliseconds < 0;\n return `${isNegative ? '-' : ''}${display}`;\n};\n\n/**\n * Handles case for formatting a duration time\n * eg: \"1h 0m 0s\" or \"0h 30m\"\n */\nexport function formatDuration(duration: number, hideSeconds = true): string {\n // durations should never be negative, we handle it here to flag if there is an issue in future\n if (duration <= 0) {\n return '0m';\n }\n\n const hours = Math.floor(duration / MILLIS_PER_HOUR);\n const minutes = Math.floor((duration % MILLIS_PER_HOUR) / MILLIS_PER_MINUTE);\n\n let result = '';\n if (hours > 0) {\n result += `${hours}h`;\n }\n if (minutes > 0) {\n result += `${minutes}m`;\n }\n\n if (!hideSeconds) {\n const remainingMs = duration % MILLIS_PER_MINUTE;\n const exactSeconds = remainingMs / MILLIS_PER_SECOND;\n // cap at 59 to avoid showing 60s\n const seconds = Math.min(59, Math.ceil(exactSeconds));\n\n if (seconds > 0) {\n result += `${seconds}s`;\n }\n }\n\n return result;\n}\n\n/**\n * @param totalGap accumulated gap from the current event\n * @param isLinkedToLoaded is this event part of a chain linking back to the current loaded event\n * @returns\n */\nexport function useTimeUntilExpectedStart(\n // typed like this to make it very clear what the data is\n event: Pick<OntimeEvent, 'timeStart' | 'dayOffset' | 'delay'> | null,\n state: {\n totalGap: number;\n isLinkedToLoaded: boolean;\n },\n): number {\n const { offset, currentDay, mode, actualStart, plannedStart, clock } = useExpectedStartData();\n if (event === null) return 0;\n\n const expectedStart = getExpectedStart(\n { ...event },\n { ...state, currentDay, offset, mode, actualStart, plannedStart },\n );\n return expectedStart - clock;\n}\n\nexport function getExpectedTimesFromExtendedEvent(\n event: Pick<\n ExtendedEntry<OntimeEvent>,\n 'timeStart' | 'dayOffset' | 'delay' | 'totalGap' | 'isLinkedToLoaded' | 'countToEnd' | 'duration'\n > | null,\n state: ReturnType<typeof useExpectedStartData>,\n) {\n if (event === null) return { expectedStart: 0, timeToStart: 0, expectedEnd: 0, plannedEnd: 0 };\n\n const expectedStart = getExpectedStart(\n { timeStart: event.timeStart, delay: event.delay, dayOffset: event.dayOffset },\n {\n totalGap: event.totalGap,\n isLinkedToLoaded: event.isLinkedToLoaded,\n ...state,\n },\n );\n\n const plannedEnd = event.timeStart + event.duration + event.delay;\n\n return {\n expectedStart,\n timeToStart: expectedStart - state.clock,\n expectedEnd: event.countToEnd\n ? Math.max(expectedStart + event.duration, plannedEnd)\n : expectedStart + event.duration,\n plannedEnd,\n };\n}\n","import { useCallback } from 'react';\nimport { Log, LogLevel, LogOrigin, MessageTag } from 'ontime-types';\nimport { generateId, millisToString } from 'ontime-utils';\nimport { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\nimport { sendSocket } from '../utils/socket';\nimport { nowInMillis } from '../utils/time';\n\ntype LogStore = {\n logs: Log[];\n};\n\nconst logger = createStore<LogStore>(() => ({\n logs: [],\n}));\n\nexport const useLogData = () => useStore(logger);\n\nexport const addLog = (log: Log) =>\n logger.setState((state) => ({\n logs: [log, ...state.logs],\n }));\n\nexport const clearLogs = () => logger.setState({ logs: [] });\n\nexport function useEmitLog() {\n /**\n * Utility function sends message over socket\n * @param text\n * @param level\n * @private\n */\n const _emit = useCallback((text: string, level: LogLevel) => {\n const log = {\n id: generateId(),\n origin: LogOrigin.Client,\n time: millisToString(nowInMillis()),\n level,\n text,\n };\n\n sendSocket(MessageTag.Log, log);\n }, []);\n\n /**\n * Sends a message with level INFO\n * @param text\n */\n const emitInfo = useCallback(\n (text: string) => {\n _emit(text, LogLevel.Info);\n },\n [_emit],\n );\n\n /**\n * Sends a message with level WARN\n * @param text\n */\n const emitWarning = useCallback(\n (text: string) => {\n _emit(text, LogLevel.Warn);\n },\n [_emit],\n );\n\n /**\n * Sends a message with level ERROR\n * @param text\n */\n const emitError = useCallback(\n (text: string) => {\n _emit(text, LogLevel.Error);\n },\n [_emit],\n );\n\n return {\n emitInfo,\n emitWarning,\n emitError,\n };\n}\n","import axios, { AxiosError } from 'axios';\nimport { LogLevel } from 'ontime-types';\nimport { generateId, millisToString } from 'ontime-utils';\n\nimport { ontimeQueryClient } from '../queryClient';\nimport { addLog } from '../stores/logger';\nimport { nowInMillis } from '../utils/time';\n\n/**\n * Utility unwrap a potential axios error\n * @param error\n * @returns\n */\nexport function maybeAxiosError(error: unknown) {\n if (axios.isAxiosError(error)) {\n const statusText = (error as AxiosError).response?.statusText ?? '';\n let data = (error as AxiosError).response?.data ?? '';\n if (typeof data === 'object') {\n if ('message' in data) {\n data = JSON.stringify(data.message);\n } else {\n data = JSON.stringify(data);\n }\n }\n return `${statusText}: ${data}`;\n } else if (error instanceof Error) {\n return error.message;\n } else {\n if (typeof error !== 'string') {\n return JSON.stringify(error);\n }\n return error;\n }\n}\n\n/**\n * Utility unwrap a an instance of Error\n */\nexport function unwrapError(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n } else {\n if (typeof error !== 'string') {\n return JSON.stringify(error);\n }\n return error;\n }\n}\n\n/**\n * Utility unwraps a potential axios error and sends to logger\n * @param prepend\n * @param error\n */\nexport function logAxiosError(prepend: string, error: unknown) {\n const message = `${prepend}: ${maybeAxiosError(error)}`;\n\n addLog({\n id: generateId(),\n origin: 'SERVER',\n time: millisToString(nowInMillis()),\n level: LogLevel.Error,\n text: message,\n });\n}\n\n/**\n * Utility function invalidates react-query caches\n */\nexport async function invalidateAllCaches() {\n await ontimeQueryClient.invalidateQueries();\n}\n\n/**\n * Creates blob from content\n * @param fileContent\n * @param type\n * @returns\n */\nexport function createBlob(fileContent: string, type: string): Blob {\n return new Blob([fileContent], { type });\n}\n\n/**\n * downloads a blob\n * @param downloadUrl\n * @param fileName\n */\nexport function downloadBlob(blob: Blob, fileName: string) {\n const downloadUrl = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.setAttribute('href', downloadUrl);\n link.setAttribute('download', fileName);\n document.body.appendChild(link);\n link.click();\n\n // Clean up the URL.createObjectURL to release resources\n URL.revokeObjectURL(downloadUrl);\n}\n","import { baseURI } from '../../externals';\n\nexport function booleanFromLocalStorage(key: string, fallback: boolean): boolean {\n const valueInStorage = localStorage.getItem(key);\n if (valueInStorage) {\n return valueInStorage === 'true';\n } else {\n localStorage.setItem(key, String(fallback));\n return fallback;\n }\n}\n\nexport function makeStageKey(key: string) {\n if (baseURI) return `${baseURI}-${key}`;\n return key;\n}\n","import { ClientList } from 'ontime-types';\nimport { create } from 'zustand';\n\nimport { makeStageKey } from '../utils/localStorage';\n\ninterface ClientStore {\n name?: string;\n setName: (newValue: string) => void;\n\n id: string;\n setId: (newValue: string) => void;\n\n redirect: string;\n setRedirect: (newValue: string) => void;\n\n clients: ClientList;\n setClients: (clients: ClientList) => void;\n}\n\nconst clientNameKey = makeStageKey('client-name');\n\nfunction persistNameInStorage(newValue: string) {\n localStorage.setItem(clientNameKey, newValue);\n}\n\nexport const useClientStore = create<ClientStore>((set) => ({\n name: localStorage.getItem(clientNameKey) ?? undefined,\n setName: (name: string) =>\n set(() => {\n persistNameInStorage(name);\n return { name };\n }),\n\n id: '',\n setId: (id) => set({ id }),\n\n redirect: '',\n setRedirect: (redirect: string) => set({ redirect }),\n\n clients: {},\n setClients: (clients: ClientList) => set({ clients }),\n}));\n\n/**\n * Allows getting client name (outside react)\n */\nexport function getClientName(): string | undefined {\n return useClientStore.getState().name;\n}\n\n/**\n * Allows updating current client name (outside react)\n */\nexport function setClientName(name: string): void {\n useClientStore.getState().setName(name);\n}\n\n/**\n * Allows updating current client name (outside react)\n */\nexport function setClientId(id: string): void {\n useClientStore.getState().setId(id);\n}\n\n/**\n * Allows getting client name (outside react)\n */\nexport function getClientId(): string | undefined {\n return useClientStore.getState().id;\n}\n\n/**\n * Allows updating redirect (outside react)\n */\nexport function setClientRedirect(path: string): void {\n useClientStore.getState().setRedirect(path);\n}\n\n/**\n * Allows setting clients (outside react)\n */\nexport function setClients(clients: ClientList): void {\n return useClientStore.getState().setClients(clients);\n}\n","import { MaybeString } from 'ontime-types';\nimport { create } from 'zustand';\n\ninterface DialogStore {\n showDialog: MaybeString;\n setDialog: (name: string) => void;\n clearDialog: () => void;\n}\n\n/**\n * Used to allow the server to show a dialog in the client\n */\nexport const useDialogStore = create<DialogStore>((set) => ({\n showDialog: null,\n clearDialog: () => set({ showDialog: null }),\n setDialog: (name) => set({ showDialog: name }),\n}));\n\n/**\n * Allows setting a dialog to show (outside react)\n */\nexport function addDialog(name: string): void {\n useDialogStore.getState().setDialog(name);\n}\n","import {\n ApiActionTag,\n Log,\n MessageTag,\n RefetchKey,\n Rundown,\n RuntimeStore,\n WsPacketToClient,\n WsPacketToServer,\n} from 'ontime-types';\n\nimport { isProduction, websocketUrl } from '../../externals';\nimport {\n APP_SETTINGS,\n CLIENT_LIST,\n CUSTOM_FIELDS,\n PROJECT_DATA,\n REPORT,\n RUNDOWN,\n RUNTIME,\n TRANSLATION,\n URL_PRESETS,\n VIEW_SETTINGS,\n} from '../api/constants';\nimport { invalidateAllCaches } from '../api/utils';\nimport { ontimeQueryClient } from '../queryClient';\nimport {\n getClientId,\n getClientName,\n setClientId,\n setClientName,\n setClientRedirect,\n setClients,\n} from '../stores/clientStore';\nimport { addDialog } from '../stores/dialogStore';\nimport { addLog } from '../stores/logger';\nimport { patchRuntime, patchRuntimeProperty } from '../stores/runtime';\n\nlet websocket: WebSocket | null = null;\nlet reconnectTimeout: NodeJS.Timeout | null = null;\nconst reconnectInterval = 1000;\n\nexport let hasConnected = false;\nexport let reconnectAttempts = 0;\n\nexport const connectSocket = () => {\n websocket = new WebSocket(websocketUrl);\n\n const preferredClientName = getClientName();\n\n websocket.onopen = () => {\n clearTimeout(reconnectTimeout as NodeJS.Timeout);\n hasConnected = true;\n reconnectAttempts = 0;\n\n sendSocket(MessageTag.ClientSet, {\n type: 'ontime',\n origin: window.location.origin,\n path: window.location.pathname + window.location.search,\n name: preferredClientName,\n });\n invalidateAllCaches(); // assume all data to be stale after a reconnect\n setOnlineStatus(true);\n };\n\n websocket.onclose = () => {\n console.warn('WebSocket disconnected');\n\n // we decide to allows reconnect\n reconnectTimeout = setTimeout(() => {\n if (reconnectAttempts > 2) {\n setOnlineStatus(false);\n }\n console.warn('WebSocket: attempting reconnect');\n if (websocket && websocket.readyState === WebSocket.CLOSED) {\n reconnectAttempts += 1;\n connectSocket();\n }\n }, reconnectInterval);\n };\n\n websocket.onerror = (error) => {\n console.error('WebSocket error:', error);\n };\n\n websocket.onmessage = async (event) => {\n try {\n const data = JSON.parse(event.data) as WsPacketToClient;\n\n const { tag, payload } = data;\n\n if (!tag) {\n return;\n }\n\n switch (tag) {\n case MessageTag.Pong: {\n const offset = (new Date().getTime() - new Date(payload).getTime()) * 0.5;\n patchRuntimeProperty('ping', offset);\n updateDevTools({ ping: offset });\n break;\n }\n case MessageTag.ClientInit: {\n setClientId(payload.clientId);\n if (!preferredClientName) {\n setClientName(payload.clientName);\n }\n break;\n }\n\n case MessageTag.ClientRename: {\n const id = getClientId();\n if (payload.target === id) {\n setClientName(payload.name);\n }\n break;\n }\n\n case MessageTag.ClientRedirect: {\n const id = getClientId();\n if (payload.target === id) {\n setClientRedirect(payload.path);\n }\n break;\n }\n\n case MessageTag.ClientList: {\n setClients(payload);\n if (!isProduction) {\n ontimeQueryClient.setQueryData(CLIENT_LIST, payload);\n }\n break;\n }\n\n case MessageTag.Dialog: {\n if (payload.dialog === 'welcome') {\n addDialog('welcome');\n }\n break;\n }\n\n case MessageTag.Log: {\n addLog(payload as Log);\n break;\n }\n case MessageTag.RuntimeData: {\n patchRuntime(payload);\n updateDevTools(payload);\n break;\n }\n case MessageTag.Refetch: {\n // the refetch message signals that the rundown has changed in the server side\n const { target, revision } = payload;\n switch (target) {\n case RefetchKey.All:\n invalidateAllCaches();\n break;\n case RefetchKey.CustomFields:\n ontimeQueryClient.invalidateQueries({ queryKey: CUSTOM_FIELDS });\n break;\n case RefetchKey.ProjectData:\n ontimeQueryClient.invalidateQueries({ queryKey: PROJECT_DATA });\n break;\n case RefetchKey.Report:\n ontimeQueryClient.invalidateQueries({ queryKey: REPORT });\n break;\n case RefetchKey.Rundown:\n if (revision === (ontimeQueryClient.getQueryData(RUNDOWN) as Rundown).revision) break;\n ontimeQueryClient.invalidateQueries({ queryKey: RUNDOWN });\n ontimeQueryClient.invalidateQueries({ queryKey: CUSTOM_FIELDS });\n break;\n case RefetchKey.UrlPresets:\n ontimeQueryClient.invalidateQueries({ queryKey: URL_PRESETS });\n break;\n case RefetchKey.ViewSettings:\n ontimeQueryClient.invalidateQueries({ queryKey: VIEW_SETTINGS });\n break;\n case RefetchKey.Translation:\n ontimeQueryClient.invalidateQueries({ queryKey: TRANSLATION });\n break;\n case RefetchKey.Settings:\n ontimeQueryClient.invalidateQueries({ queryKey: APP_SETTINGS });\n break;\n default: {\n target satisfies never;\n break;\n }\n }\n break;\n }\n default: {\n tag satisfies never;\n break;\n }\n }\n } catch (_) {\n // ignore unhandled\n }\n };\n};\n\nexport function sendSocket<T extends MessageTag | ApiActionTag>(\n tag: T,\n payload: T extends MessageTag ? Pick<WsPacketToServer & { tag: T }, 'payload'>['payload'] : unknown,\n): void {\n if (websocket && websocket.readyState === WebSocket.OPEN) {\n websocket.send(JSON.stringify({ tag, payload }));\n }\n}\n\nfunction updateDevTools(newData: Partial<RuntimeStore>) {\n if (!isProduction) {\n ontimeQueryClient.setQueryData(RUNTIME, (oldData: RuntimeStore) => ({\n ...oldData,\n ...newData,\n }));\n }\n}\n\n/**\n * Allows setting the status of the client\n * We leverage the ping as an indication of the client's online status\n * @example ping < 0 - client is offline\n * @example ping > 0 -> client is online\n */\nfunction setOnlineStatus(status: boolean) {\n const derivedPing = status ? 1 : -1;\n patchRuntimeProperty('ping', derivedPing);\n updateDevTools({ ping: derivedPing });\n}\n","/* eslint-disable react/destructuring-assignment */\nimport React from 'react';\n// skipcq: JS-C1003 - sentry does not expose itself as an ES Module.\nimport * as Sentry from '@sentry/react';\n\nimport { hasConnected, reconnectAttempts } from '../../../common/utils/socket';\nimport { runtimeStore } from '../../stores/runtime';\n\nimport style from './ErrorBoundary.module.scss';\n\nclass ErrorBoundary extends React.Component {\n reportContent = '';\n\n constructor(props) {\n super(props);\n this.state = { error: null, errorInfo: null };\n }\n\n static getDerivedStateFromError(error) {\n // Update state so next render shows fallback UI.\n return { errorMessage: error.toString() };\n }\n\n componentDidCatch(error, info) {\n this.setState({\n error,\n errorInfo: info,\n });\n this.reportContent = `${error} ${info.componentStack}`;\n\n const appState = runtimeStore.getState();\n if (appState.ping < 0) {\n return;\n }\n\n Sentry.withScope((scope) => {\n scope.setExtras({\n error,\n store: appState,\n hasSocket: { hasConnected, reconnectAttempts },\n });\n const eventId = Sentry.captureException(error);\n this.setState({ eventId, info });\n });\n }\n\n render() {\n if (this.state.errorMessage) {\n return (\n <div className={style.errorContainer} data-testid='error-container'>\n <div>\n <p className={style.error}>: /</p>\n <p>Something went wrong.</p>\n <a\n className={style.report}\n href={`mailto:mail@getontime.no?subject=Error%20Report&body=${encodeURIComponent(this.reportContent)}`}\n >\n Report error\n </a>\n <div\n role='button'\n className={style.report}\n onClick={() => {\n if (window?.process?.type === 'renderer') {\n window.ipcRenderer.send('reload');\n } else {\n window.location.reload();\n }\n }}\n >\n Reload interface\n </div>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n\nexport default ErrorBoundary;\n","import { useCallback, useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport { setClientRemote } from '../../hooks/useSocket';\nimport { useClientStore } from '../../stores/clientStore';\n\nimport style from './IdentifyOverlay.module.scss';\n\nexport default function IdentifyOverlay() {\n const clients = useClientStore((store) => store.clients);\n const id = useClientStore((store) => store.id);\n const showOverlay = clients[id]?.identify;\n\n if (!showOverlay) {\n return null;\n }\n\n const portalRoot = document.getElementById('identify-portal');\n\n if (!portalRoot) {\n return null;\n }\n return createPortal(<Overlay />, portalRoot);\n}\n\nfunction Overlay() {\n const clients = useClientStore((store) => store.clients);\n const id = useClientStore((store) => store.id);\n const name = useClientStore((store) => store.name);\n\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n\n const { setIdentify } = setClientRemote;\n const showOverlay = clients[id]?.identify;\n\n const handleClose = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n\n setIdentify({ target: id, identify: false });\n }, [id, setIdentify]);\n\n // start a timer that will close the overlay after some time\n useEffect(() => {\n if (showOverlay) {\n timerRef.current = setTimeout(handleClose, MILLIS_PER_MINUTE);\n }\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, [showOverlay, id, setIdentify, handleClose]);\n\n return (\n <div className={style.overlay} data-testid='identify-overlay' onClick={handleClose}>\n <div className={style.name}>{name}</div>\n <div className={style.message}>Click to close</div>\n </div>\n );\n}\n","import axios, { AxiosResponse } from 'axios';\nimport { Settings } from 'ontime-types';\n\nimport { apiEntryUrl } from './constants';\n\nconst settingsPath = `${apiEntryUrl}/settings`;\n\n/**\n * HTTP request to retrieve application settings\n */\nexport async function getSettings(): Promise<Settings> {\n const res = await axios.get(settingsPath);\n return res.data;\n}\n\n/**\n * HTTP request to mutate application settings\n */\nexport async function postSettings(data: Settings): Promise<AxiosResponse<Settings>> {\n return axios.post(settingsPath, data);\n}\n\n/**\n * Allows setting the welcome modal dialog state from the clients\n */\nexport async function postShowWelcomeDialog(show: boolean) {\n axios.post(`${settingsPath}/welcomedialog`, { show });\n}\n","import { Settings } from 'ontime-types';\n\nexport const ontimePlaceholderSettings: Settings = {\n version: '4.0.0',\n serverPort: 4001,\n editorKey: null,\n operatorKey: null,\n timeFormat: '24',\n language: 'en',\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { unobfuscate } from 'ontime-utils';\n\nimport { APP_SETTINGS } from '../api/constants';\nimport { getSettings } from '../api/settings';\nimport { ontimePlaceholderSettings } from '../models/OntimeSettings';\n\nexport default function useSettings() {\n const { data, status, isFetching, isError, refetch } = useQuery({\n queryKey: APP_SETTINGS,\n queryFn: getSettings,\n placeholderData: (previousData, _previousQuery) => previousData,\n select: (data) => {\n const unobfuscated = { ...data };\n if (data.editorKey) {\n unobfuscated.editorKey = unobfuscate(data.editorKey);\n }\n if (data.operatorKey) {\n unobfuscated.operatorKey = unobfuscate(data.operatorKey);\n }\n return unobfuscated;\n },\n });\n\n return { data: data ?? ontimePlaceholderSettings, status, isFetching, isError, refetch };\n}\n","import { createContext, PropsWithChildren, useCallback, useEffect, useState } from 'react';\n\nimport useSettings from '../hooks-query/useSettings';\n\ninterface AppContextType {\n editorAuth: boolean;\n operatorAuth: boolean;\n validate: (pin: string, permission: 'editor' | 'operator') => boolean;\n}\n\nexport const AppContext = createContext<AppContextType>({\n editorAuth: false,\n operatorAuth: false,\n validate: () => false,\n});\n\nconst storageKeys = {\n editor: 'ontime-editor-entry',\n operator: 'ontime-operator-entry',\n};\n\nexport const AppContextProvider = ({ children }: PropsWithChildren) => {\n const { status, data } = useSettings();\n const [editorAuth, setEditorAuth] = useState(true);\n const [operatorAuth, setOperatorAuth] = useState(true);\n\n useEffect(() => {\n if (status === 'pending') return;\n const previousEditor = sessionStorage.getItem(storageKeys.editor);\n\n if (previousEditor && previousEditor === data.editorKey) {\n setEditorAuth(true);\n } else {\n setEditorAuth(data.editorKey == null || data.editorKey === '');\n }\n\n const previousOperator = sessionStorage.getItem(storageKeys.operator);\n if (previousOperator && previousOperator === data.operatorKey) {\n setOperatorAuth(true);\n } else {\n setOperatorAuth(data.operatorKey == null || data.operatorKey === '');\n }\n }, [data, status]);\n\n /**\n * Validates a pincode\n * @return boolean - whether the pin is valid\n */\n const validate = useCallback(\n (pin: string, permission: 'editor' | 'operator'): boolean => {\n function isValid(pin: string, savedPin?: string | null): boolean {\n return savedPin == null || savedPin === '' || pin === savedPin;\n }\n\n if (permission === 'editor') {\n const correct = isValid(pin, data.editorKey);\n if (correct) {\n sessionStorage.setItem(storageKeys.editor, pin);\n }\n setEditorAuth(correct);\n return correct;\n } else if (permission === 'operator') {\n const correct = isValid(pin, data.operatorKey);\n if (correct) {\n sessionStorage.setItem(storageKeys.operator, pin);\n }\n setOperatorAuth(correct);\n return correct;\n }\n return false;\n },\n [data],\n );\n\n return <AppContext.Provider value={{ editorAuth, operatorAuth, validate }}>{children}</AppContext.Provider>;\n};\n","import { createContext } from 'react';\nimport { URLPreset } from 'ontime-types';\n\nexport const PresetContext = createContext<URLPreset | undefined>(undefined);\n","import { use, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useSearchParams } from 'react-router';\n\nimport { PresetContext } from '../../common/context/PresetContext';\n\n// wakelock is only available in secure contexts\n// however, that is covered by the navigator check\nexport const canUseWakeLock = typeof window !== 'undefined' && 'wakeLock' in navigator;\n\n/** @url https://developer.mozilla.org/en-US/docs/Web/API/WakeLock */\nexport function useWakelock() {\n const { keepAwake } = useKeepAwakeOptions();\n const wakeLockSentinelRef = useRef<WakeLockSentinel | null>(null);\n\n useEffect(() => {\n const removeLock = () => {\n if (wakeLockSentinelRef.current) {\n wakeLockSentinelRef.current.release().finally(() => {\n wakeLockSentinelRef.current = null;\n });\n }\n };\n\n const acquireLock = () => {\n const sentinel = wakeLockSentinelRef.current;\n if (!sentinel || sentinel.released) {\n wakeLockSentinelRef.current = null;\n\n if (!canUseWakeLock) {\n return;\n }\n\n navigator.wakeLock\n .request('screen')\n .then((sentinel) => {\n wakeLockSentinelRef.current = sentinel;\n })\n .catch(console.error);\n }\n };\n\n const controller = new AbortController();\n if (keepAwake) {\n acquireLock();\n document.addEventListener(\n 'visibilitychange',\n () => {\n if (wakeLockSentinelRef.current !== null && document.visibilityState === 'visible') {\n acquireLock();\n }\n },\n { signal: controller.signal },\n );\n } else {\n removeLock();\n }\n\n return () => {\n controller.abort();\n removeLock();\n };\n }, [keepAwake]);\n}\n\nconst keepAwakeKey = 'keep-awake';\n\nfunction getOptionsFromParams(searchParams: URLSearchParams, defaultValues?: URLSearchParams) {\n // Helper to get value from either source, prioritizing defaultValues\n return defaultValues?.has(keepAwakeKey) || searchParams.has(keepAwakeKey);\n}\n\n/**\n * Hook exposes the keep awake options\n */\nexport function useKeepAwakeOptions() {\n const [searchParams, setSearchParams] = useSearchParams();\n const maybePreset = use(PresetContext);\n\n const keepAwake = useMemo(() => {\n const defaultValues = maybePreset ? new URLSearchParams(maybePreset.search) : undefined;\n return getOptionsFromParams(searchParams, defaultValues);\n }, [maybePreset, searchParams]);\n\n const toggleKeepAwake = useCallback(() => {\n setSearchParams((searchParams) => {\n if (keepAwake) {\n searchParams.delete(keepAwakeKey);\n } else {\n searchParams.set(keepAwakeKey, '1');\n }\n return searchParams;\n });\n }, [keepAwake, setSearchParams]);\n\n return { keepAwake, toggleKeepAwake };\n}\n","import { useWakelock } from './useWakeLock';\n\n/**\n * Composes the wakelock hook to contain re-renders\n */\nexport default function KeepAwake() {\n useWakelock();\n\n return null;\n}\n","import axios from 'axios';\nimport { TranslationObject } from 'ontime-types';\n\nimport { ontimeQueryClient } from '../../common/queryClient';\n\nimport { apiEntryUrl, customTranslationsURL, TRANSLATION } from './constants';\n\nconst assetsPath = `${apiEntryUrl}/assets`;\n\n/**\n * HTTP request to get css contents\n */\nexport async function getCSSContents(): Promise<string> {\n const res = await axios.get(`${assetsPath}/css`);\n return res.data;\n}\n\n/**\n * HTTP request to post css contents\n */\nexport async function postCSSContents(css: string): Promise<void> {\n await axios.post(`${assetsPath}/css`, {\n css,\n });\n}\n\n/**\n * HTTP request to restore default css\n */\nexport async function restoreCSSContents(): Promise<string> {\n const res = await axios.post(`${assetsPath}/css/restore`);\n return res.data;\n}\n\n/**\n * HTTP request to get user translation\n */\nexport async function getUserTranslation(): Promise<TranslationObject> {\n const res = await axios.get(customTranslationsURL);\n return res.data;\n}\n\n/**\n * HTTP request to post user translation\n */\nexport async function postUserTranslation(translation: TranslationObject): Promise<void> {\n await axios.post(`${assetsPath}/translations`, {\n translation,\n });\n await ontimeQueryClient.invalidateQueries({ queryKey: TRANSLATION });\n}\n","export const tooltipDelaySlow = 1000;\nexport const tooltipDelayMid = 500;\nexport const tooltipDelayFast = 300;\n\nexport const queryRefetchInterval = 60000; // 60 seconds\nexport const queryRefetchIntervalSlow = 120000; // 120 seconds\n\nexport const sessionKeys = {\n cuesheetMode: 'cuesheet-mode',\n editorMode: 'editor-mode',\n};\n\nexport enum AppMode {\n Run = 'run',\n Edit = 'edit',\n}\n","import { useQuery } from '@tanstack/react-query';\nimport { langEn } from 'ontime-types';\n\nimport { getUserTranslation } from '../../common/api/assets';\nimport { TRANSLATION } from '../../common/api/constants';\nimport { queryRefetchIntervalSlow } from '../../ontimeConfig';\n\nexport function useCustomTranslation() {\n const { data, status, refetch } = useQuery({\n queryKey: TRANSLATION,\n queryFn: getUserTranslation,\n placeholderData: (previousData, _previousQuery) => previousData,\n refetchInterval: queryRefetchIntervalSlow,\n });\n return { data: data ?? langEn, status, refetch };\n}\n","import { TranslationObject } from 'ontime-types';\n\nexport const langDe: TranslationObject = {\n 'common.expected_finish': 'Erwartetes Ende',\n 'common.minutes': 'min',\n 'common.seconds': 'sek',\n 'common.now': 'Jetzt',\n 'common.next': 'Nächste',\n 'common.scheduled_start': 'Geplanter beginn',\n 'common.scheduled_end': 'Geplantes ende',\n 'common.expected_start': 'Erwartetes beginn',\n 'common.expected_end': 'Erwartetes ende',\n 'common.stage_timer': 'Bühnen-Timer',\n 'common.started_at': 'Gestartet am',\n 'common.time_now': 'Aktuelle Zeit',\n 'common.no_data': 'Keine Daten',\n 'countdown.ended': 'Veranstaltung endete um',\n 'countdown.running': 'Veranstaltung läuft',\n 'countdown.loaded': 'Veranstaltung geladen',\n 'countdown.select_event': 'Wählen Sie eine Veranstaltung aus, um sie zu verfolgen',\n 'countdown.to_start': 'Zeit bis zum Start',\n 'countdown.waiting': 'Warten auf den Veranstaltungsbeginn',\n 'countdown.overtime': 'überfällig',\n 'timeline.live': 'live',\n 'timeline.done': 'Beendet',\n 'timeline.due': 'fällig',\n 'timeline.followedby': 'Gefolgt von',\n 'project.title': 'Titel',\n 'project.description': 'Beschreibung',\n 'project.info': 'Projektinfo',\n 'project.url': 'Projekt-URL',\n};\n","import { TranslationObject } from 'ontime-types';\n\nexport const langEs: TranslationObject = {\n 'common.expected_finish': 'Finalización esperada',\n 'common.minutes': 'min',\n 'common.seconds': 'sec',\n 'common.now': 'Ahora',\n 'common.next': 'Siguiente',\n 'common.scheduled_start': 'Inicio programado',\n 'common.scheduled_end': 'Fin programado',\n 'common.expected_start': 'Inicio previsto',\n 'common.expected_end': 'Fin previsto',\n 'common.stage_timer': 'Temporizador de presentador',\n 'common.started_at': 'Iniciado en',\n 'common.time_now': 'Ahora',\n 'common.no_data': 'Sin datos',\n 'countdown.ended': 'Evento finalizado a las',\n 'countdown.running': 'Evento en curso',\n 'countdown.loaded': 'Evento está cargado', //TODO: check translation\n 'countdown.select_event': 'Seleccionar un evento para seguir',\n 'countdown.to_start': 'Tiempo para comenzar',\n 'countdown.waiting': 'Esperando el inicio del evento',\n 'countdown.overtime': 'en tiempo extra',\n 'timeline.live': 'live',\n 'timeline.done': 'Terminado',\n 'timeline.due': 'pendiente',\n 'timeline.followedby': 'Seguido por',\n 'project.title': 'Título',\n 'project.description': 'Descripción',\n 'project.info': 'Información del proyecto',\n 'project.url': 'URL del proyecto',\n};\n","import { TranslationObject } from 'ontime-types';\n\nexport const langFr: TranslationObject = {\n 'common.expected_finish': 'Fin estimée à',\n 'common.minutes': 'min',\n 'common.seconds': 'sec',\n 'common.now': 'Maintenant',\n 'common.next': 'A suivre',\n 'common.scheduled_start': 'Début prévu',\n 'common.scheduled_end': 'Fin prévue',\n 'common.expected_start': 'Début projeté',\n 'common.expected_end': 'Fin projetée',\n 'common.stage_timer': 'Minuteur de scène',\n 'common.started_at': 'Commencé à',\n 'common.time_now': 'Heure',\n 'common.no_data': 'Aucune donnée',\n 'countdown.ended': 'Évènement terminé à',\n 'countdown.running': 'Évènement en cours',\n 'countdown.loaded': 'Évènement chargé',\n 'countdown.select_event': 'Sélectionnez un évènement à suivre',\n 'countdown.to_start': 'Évènement commence dans',\n 'countdown.waiting': 'En attente du début de l’évènement',\n 'countdown.overtime': 'en dépassement',\n 'timeline.live': 'live',\n 'timeline.done': 'Terminé',\n 'timeline.due': 'dû',\n 'timeline.followedby': 'Suivi de',\n 'project.title': 'Titre',\n 'project.description': 'Description',\n 'project.info': 'Informations du projet',\n 'project.url': 'URL du projet',\n};\n","import { TranslationObject } from 'ontime-types';\n\nexport const langIt: TranslationObject = {\n 'common.expected_finish': 'Fine Prevista',\n 'common.minutes': 'min',\n 'common.seconds': 'sec',\n 'common.now': 'Adesso',\n 'common.next': 'Prossimo',\n 'common.scheduled_start': 'Inizio programmato',\n 'common.scheduled_end': 'Fine programmata',\n 'common.expected_start': 'Inizio previsto',\n 'common.expected_end': 'Fine prevista',\n 'common.stage_timer': 'Orologio Palco',\n 'common.started_at': 'Iniziato Alle',\n 'common.time_now': 'Ora attuale',\n 'common.no_data': 'Nessun dato disponibile',\n 'countdown.ended': 'Evento finito alle',\n 'countdown.running': 'Evento in corso',\n 'countdown.loaded': 'Evento caricato', //TODO: check translation\n 'countdown.select_event': 'Seleziona un evento da seguire',\n 'countdown.to_start': 'Tempo alla partenza',\n 'countdown.waiting': \"In attesa dell'inizio dell'evento\",\n 'countdown.overtime': 'in ritardo',\n 'timeline.live': 'live',\n 'timeline.done': 'Terminato',\n 'timeline.due': 'previsto',\n 'timeline.followedby': 'Seguito da',\n 'project.title': 'Titolo',\n 'project.description': 'Descrizione',\n 'project.info': 'Informazioni sul progetto',\n 'project.url': 'URL del progetto',\n};\n","import { TranslationObject } from 'ontime-types';\n\nexport const langPt: TranslationObject = {\n 'common.expected_finish': 'Término esperado',\n 'common.minutes': 'min',\n 'common.seconds': 'sec',\n 'common.now': 'Agora',\n 'common.next': 'Próximo',\n 'common.scheduled_start': 'Início programado',\n 'common.scheduled_end': 'Fim programado',\n 'common.expected_start': 'Início previsto',\n 'common.expected_end': 'Fim previsto',\n 'common.stage_timer': 'Temporizador do presentador',\n 'common.started_at': 'Iniciado em',\n 'common.time_now': 'Hora atual',\n 'common.no_data': 'Sem dados',\n 'countdown.ended': 'Evento encerrado às',\n 'countdown.running': 'Evento em andamento',\n 'countdown.loaded': 'Evento carregado', //TODO: check translation\n 'countdown.select_event': 'Selecione um evento para acompanhar',\n 'countdown.to_start': 'Tempo para iniciar',\n 'countdown.waiting': 'Aguardando o início do evento',\n 'countdown.overtime': 'em tempo extra',\n 'timeline.live': 'live',\n 'timeline.done': 'Concluído',\n 'timeline.due': 'Pendente',\n 'timeline.followedby': 'Seguido por',\n 'project.title': 'Título',\n 'project.description': 'Descrição',\n 'project.info': 'Informações do projeto',\n 'project.url': 'URL do projeto',\n};\n","import { createContext, PropsWithChildren, useCallback, useContext } from 'react';\nimport { langEn, TranslationObject } from 'ontime-types';\n\nimport { postUserTranslation } from '../common/api/assets';\nimport { useCustomTranslation } from '../common/hooks-query/useCustomTranslation';\nimport useSettings from '../common/hooks-query/useSettings';\n\nimport { langDe } from './languages/de';\nimport { langEs } from './languages/es';\nimport { langFr } from './languages/fr';\nimport { langIt } from './languages/it';\nimport { langPt } from './languages/pt';\n\nconst translationsList = {\n en: langEn,\n es: langEs,\n fr: langFr,\n it: langIt,\n de: langDe,\n pt: langPt,\n};\n\nexport type TranslationKey = keyof typeof langEn;\n\ninterface TranslationContextValue {\n userTranslation: TranslationObject;\n getLocalizedString: (key: TranslationKey, lang?: string) => string;\n postUserTranslation: (translation: TranslationObject) => Promise<void>;\n}\n\nconst TranslationContext = createContext<TranslationContextValue>({\n userTranslation: langEn,\n getLocalizedString: () => '',\n postUserTranslation: async () => {},\n});\n\nexport const TranslationProvider = ({ children }: PropsWithChildren) => {\n const { data } = useSettings();\n const { data: translationData } = useCustomTranslation();\n\n const getLocalizedString = useCallback(\n (key: TranslationKey, lang = data?.language || 'en'): string => {\n if (lang in translationsList) {\n if (key in translationsList[lang as keyof typeof translationsList]) {\n return translationsList[lang as keyof typeof translationsList][key];\n }\n } else if (lang === 'custom') {\n return translationData[key];\n }\n return langEn[key];\n },\n [data?.language, translationData],\n );\n\n const contextValue = {\n userTranslation: translationData,\n getLocalizedString,\n postUserTranslation,\n };\n\n return <TranslationContext.Provider value={contextValue}>{children}</TranslationContext.Provider>;\n};\n\nexport const useTranslation = () => {\n const { userTranslation, getLocalizedString, postUserTranslation } = useContext(TranslationContext);\n return { userTranslation, getLocalizedString, postUserTranslation };\n};\n","import { create } from 'zustand';\n\ninterface ViewParamsEditorStore {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n}\n\nexport const useViewParamsEditorStore = create<ViewParamsEditorStore>((set) => ({\n isOpen: false,\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((state) => ({ isOpen: !state.isOpen })),\n}));\n","export function throttle<T extends any[]>(callback: (...args: T) => void, wait: number) {\n let timeout: NodeJS.Timeout | null;\n return (...args: T) => {\n if (timeout) {\n return;\n }\n timeout = setTimeout(() => {\n timeout = null;\n callback(...args);\n }, wait);\n };\n}\n","import { useEffect, useState } from 'react';\n\nimport { throttle } from '../utils/throttle';\n\nconst inactiveTime = 3000; // 3 seconds\n\n/**\n * Provides whether there has been mouse movement in the page in the last <inactiveTime>\n */\nexport const useFadeOutOnInactivity = (initialState = false) => {\n const [isUserActive, setIsUserActive] = useState(initialState);\n\n // show on mouse move\n useEffect(() => {\n let fadeOut: NodeJS.Timeout | null = null;\n const setShowMenuTrue = () => {\n setIsUserActive(true);\n if (fadeOut) {\n clearTimeout(fadeOut);\n }\n fadeOut = setTimeout(() => setIsUserActive(false), inactiveTime);\n };\n\n const throttledShowMenu = throttle(setShowMenuTrue, 1000);\n\n // we call the function on mount, to make sure the menu is hidden\n throttledShowMenu();\n\n document.addEventListener('mousemove', throttledShowMenu);\n document.addEventListener('keydown', throttledShowMenu);\n\n return () => {\n document.removeEventListener('mousemove', throttledShowMenu);\n document.removeEventListener('keydown', throttledShowMenu);\n if (fadeOut) {\n clearTimeout(fadeOut);\n }\n };\n }, []);\n\n return isUserActive;\n};\n","import { RGBColour } from 'ontime-types';\nimport { colourToHex, cssOrHexToColour, isLightColour, mixColours } from 'ontime-utils';\n\ntype ColourCombination = {\n backgroundColor: string;\n color: string;\n};\n\nconst defaultUiBackground: RGBColour = { red: 26, green: 26, blue: 26, alpha: 1 };\n/**\n * @description Selects text colour to maintain accessible contrast\n * @param bgColour\n * @return {{backgroundColor, color: string}}\n */\nexport const getAccessibleColour = (bgColour?: string): ColourCombination => {\n if (!bgColour) return { backgroundColor: '#1a1a1a', color: '#fffffa' };\n\n const originalColour = cssOrHexToColour(bgColour);\n if (!originalColour) return { backgroundColor: '#1a1a1a', color: '#fffffa' };\n\n const backgroundColorMix = mixColours(defaultUiBackground, originalColour, 1 - originalColour.alpha);\n const textColor = isLightColour(backgroundColorMix) ? 'black' : '#fffffa';\n\n return { backgroundColor: colourToHex(backgroundColorMix), color: textColor };\n};\n\n/**\n * @description Creates a list of classnames from array of css module conditions\n * @param classNames - css modules objects\n */\nexport const cx = (classNames: any[]) => classNames.filter(Boolean).join(' ');\n\nexport const enDash = '–';\n\nexport const timerPlaceholder = '––:––:––';\nexport const timerPlaceholderMin = '––:––';\n\n/**\n * Adds opacity to a given colour if possible\n */\nexport function alpha(colour: string, amount: number): string {\n const originalColour = cssOrHexToColour(colour);\n if (!originalColour) return colour;\n originalColour.alpha = amount;\n return colourToHex(originalColour);\n}\n","import { ButtonHTMLAttributes, forwardRef } from 'react';\n\nimport { cx } from '../../utils/styleUtils';\n\nimport style from './IconButton.module.scss';\n\ninterface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?:\n | 'primary'\n | 'subtle'\n | 'subtle-white'\n | 'destructive'\n | 'subtle-destructive'\n | 'ghosted'\n | 'ghosted-white'\n | 'ghosted-destructive';\n size?: 'small' | 'medium' | 'large' | 'xlarge';\n}\n\nconst IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ className, children, variant = 'subtle', size = 'medium', ...buttonProps }, ref) => {\n return (\n <button\n ref={ref}\n className={cx([style.baseIconButton, style[variant], style[size], className])}\n type='button'\n {...buttonProps}\n >\n {children}\n </button>\n );\n },\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\n","import { IoApps, IoSettingsOutline } from 'react-icons/io5';\n\nimport { useFadeOutOnInactivity } from '../../../hooks/useFadeOutOnInactivity';\nimport { cx } from '../../../utils/styleUtils';\nimport IconButton from '../../buttons/IconButton';\n\nimport style from './FloatingNavigation.module.scss';\n\ninterface FloatingNavigationProps {\n toggleMenu?: () => void;\n toggleSettings?: () => void;\n}\n\nexport default function FloatingNavigation({ toggleMenu, toggleSettings }: FloatingNavigationProps) {\n const isButtonShown = useFadeOutOnInactivity(true);\n\n return (\n <div\n id='fadeable-navigation'\n className={cx([style.fadeable, style.buttonContainer, !isButtonShown && style.hidden])}\n >\n {toggleMenu && (\n <IconButton\n variant='subtle-white'\n size='xlarge'\n onClick={toggleMenu}\n aria-label='toggle menu'\n data-testid='navigation__toggle-menu'\n >\n <IoApps />\n </IconButton>\n )}\n {toggleSettings && (\n <IconButton\n variant='subtle-white'\n size='xlarge'\n onClick={toggleSettings}\n aria-label='toggle settings'\n data-testid='navigation__toggle-settings'\n >\n <IoSettingsOutline />\n </IconButton>\n )}\n </div>\n );\n}\n","import { IoLockClosedOutline } from 'react-icons/io5';\n\nimport { useFadeOutOnInactivity } from '../../../hooks/useFadeOutOnInactivity';\nimport { cx } from '../../../utils/styleUtils';\n\nimport style from './ViewLockedIcon.module.scss';\n\nexport default function ViewLockedIcon() {\n const isLockIconShown = useFadeOutOnInactivity();\n\n return (\n <div className={cx([style.fadeable, style.lockIcon, !isLockIconShown && style.hidden])}>\n <IoLockClosedOutline />\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport { useViewportSize } from '@mantine/hooks';\n\nexport function useIsSmallScreen(): boolean {\n const { width } = useViewportSize();\n\n return useMemo(() => width < 1300, [width]);\n}\n","import { create } from 'zustand';\n\nimport { booleanFromLocalStorage } from '../utils/localStorage';\n\nenum LocalEventKeys {\n Mirror = 'view-mirror',\n}\n\ntype ViewOptionsStore = {\n mirror: boolean;\n toggleMirror: (newValue?: boolean) => void;\n};\n\nexport const useViewOptionsStore = create<ViewOptionsStore>()((set) => ({\n mirror: booleanFromLocalStorage(LocalEventKeys.Mirror, false),\n toggleMirror: (newValue?: boolean) =>\n set((state) => {\n const val = typeof newValue === 'undefined' ? !state.mirror : newValue;\n localStorage.setItem(LocalEventKeys.Mirror, String(val));\n return { mirror: val };\n }),\n}));\n","import { ButtonHTMLAttributes, forwardRef } from 'react';\nimport { IoEllipseOutline } from 'react-icons/io5';\n\nimport { cx } from '../../utils/styleUtils';\n\nimport style from './Button.module.scss';\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?:\n | 'primary'\n | 'subtle'\n | 'subtle-white'\n | 'destructive'\n | 'subtle-destructive'\n | 'ghosted'\n | 'ghosted-white'\n | 'ghosted-destructive';\n size?: 'small' | 'medium' | 'large' | 'xlarge';\n fluid?: boolean;\n loading?: boolean;\n}\n\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, children, variant = 'subtle', size = 'medium', fluid, loading, ...buttonProps }, ref) => {\n return (\n <button\n ref={ref}\n className={cx([\n style.baseButton,\n style[variant],\n style[size],\n fluid && style.fluid,\n loading && style.loading,\n className,\n ])}\n type='button'\n disabled={loading || buttonProps.disabled}\n {...buttonProps}\n >\n <span className={style.content}>{children}</span>\n {loading && (\n <div className={style.loadingOverlay}>\n <IoEllipseOutline className={style.spinner} />\n </div>\n )}\n </button>\n );\n },\n);\n\nButton.displayName = 'Button';\n\nexport default Button;\n","import type { ReactNode } from 'react';\nimport { IoClose } from 'react-icons/io5';\nimport { Dialog as BaseDialog } from '@base-ui/react/dialog';\n\nimport IconButton from '../buttons/IconButton';\n\nimport style from './Dialog.module.scss';\n\ninterface DialogProps {\n isOpen: boolean;\n title: string;\n showCloseButton?: boolean;\n showBackdrop?: boolean;\n bodyElements: ReactNode;\n footerElements?: ReactNode;\n onClose: () => void;\n}\n\nexport default function Dialog({\n isOpen,\n title,\n showCloseButton,\n showBackdrop,\n bodyElements,\n footerElements,\n onClose,\n}: DialogProps) {\n return (\n <BaseDialog.Root\n open={isOpen}\n onOpenChange={(isOpen) => {\n if (!isOpen) onClose();\n }}\n >\n <BaseDialog.Portal>\n {showBackdrop && <BaseDialog.Backdrop className={style.backdrop} />}\n <BaseDialog.Popup className={style.dialog}>\n <div className={style.title}>\n {title}\n {showCloseButton && (\n <IconButton variant='subtle-white' onClick={onClose}>\n <IoClose />\n </IconButton>\n )}\n </div>\n <div className={style.body}>{bodyElements}</div>\n <div className={style.footer}>{footerElements}</div>\n </BaseDialog.Popup>\n </BaseDialog.Portal>\n </BaseDialog.Root>\n );\n}\n","import { forwardRef, InputHTMLAttributes } from 'react';\n\nimport { cx } from '../../../utils/styleUtils';\n\nimport style from './Input.module.scss';\n\nexport interface InputProps extends InputHTMLAttributes<HTMLInputElement> {\n variant?: 'subtle' | 'ghosted';\n height?: 'medium' | 'large';\n fluid?: boolean;\n}\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { className, variant = 'subtle', height = 'medium', fluid, ...inputProps },\n ref,\n) {\n return (\n <input\n ref={ref}\n type='text'\n autoCorrect='off'\n autoComplete='off'\n spellCheck='false'\n className={cx([style.input, style[variant], style[height], fluid && style.fluid, className])}\n {...inputProps}\n />\n );\n});\n\nexport default Input;\n","import { useState } from 'react';\n\nimport Button from '../../../common/components/buttons/Button';\nimport { setClientRemote } from '../../hooks/useSocket';\nimport Dialog from '../dialog/Dialog';\nimport Input from '../input/input/Input';\n\ninterface RenameClientModalProps {\n id: string;\n name?: string;\n isOpen: boolean;\n onClose: () => void;\n}\n\nexport function RenameClientModal({ id, name: currentName = '', isOpen, onClose }: RenameClientModalProps) {\n const [name, setName] = useState(currentName);\n\n const { setClientName } = setClientRemote;\n\n const handleRename = () => {\n if (name !== currentName && name !== '') {\n setClientName({ target: id, rename: name });\n }\n onClose();\n };\n\n const canSubmit = name !== currentName && name !== '';\n\n return (\n <Dialog\n isOpen={isOpen}\n title={`Rename Client: ${currentName}`}\n showCloseButton\n onClose={onClose}\n bodyElements={\n <Input height='large' placeholder='New name' value={name} onChange={(event) => setName(event.target.value)} />\n }\n footerElements={\n <>\n <Button variant='subtle' size='large' onClick={onClose}>\n Cancel\n </Button>\n <Button variant='primary' size='large' onClick={handleRename} disabled={!canSubmit}>\n Submit\n </Button>\n </>\n }\n />\n );\n}\n","import { useCallback, useEffect } from 'react';\nimport { useNavigate } from 'react-router';\n\nimport { addDialog } from '../stores/dialogStore';\n\nconst isElectron = window.process?.type === 'renderer';\nconst ipcRenderer = isElectron ? window.require('electron').ipcRenderer : null;\n\nexport function useElectronEvent() {\n const sendToElectron = useCallback((channel: string, args?: string | Record<string, unknown>) => {\n if (isElectron && ipcRenderer) {\n ipcRenderer.send(channel, args);\n }\n }, []);\n\n return { isElectron, sendToElectron };\n}\n\nexport function useElectronListener() {\n const navigate = useNavigate();\n const { isElectron } = useElectronEvent();\n\n // listen to requests to change the editor location\n useEffect(() => {\n if (isElectron) {\n ipcRenderer.on('request-editor-location', (_event: unknown, location: string) => {\n navigate(location, { relative: 'route' });\n });\n\n ipcRenderer.on('dialog', (_event: unknown, dialog: string) => {\n if (dialog === 'welcome') {\n addDialog('welcome');\n }\n });\n }\n\n // Clean the listener after the component is dismounted\n return () => {\n ipcRenderer?.removeAllListeners();\n };\n }, [isElectron, navigate]);\n}\n","import type { MouseEvent } from 'react';\n\nimport { baseURI, serverURL } from '../../externals';\n\n/**\n * Open an external URLs: specifically for a electron / browser case\n * If electron: ask main process to call a new browser window\n * If browser: open in new tab\n */\nexport function openLink(url: string) {\n if (window.process?.type === 'renderer') {\n window.ipcRenderer.send('send-to-link', url);\n } else {\n window.open(url);\n }\n}\n\n/**\n * Handles opening external links\n * serverUrl and baseURI are used for testing\n */\nexport function handleLinks(\n location: string,\n event?: MouseEvent,\n externalServerUrl: string = serverURL,\n externalBaseURI: string = baseURI,\n) {\n // we handle the link manually\n event?.preventDefault();\n\n const destination = new URL(externalServerUrl);\n destination.pathname = externalBaseURI ? `${externalBaseURI}/${location}` : location;\n openLink(destination.toString());\n}\n\nexport function linkToOtherHost(\n host: string,\n path?: string,\n externalServerUrl: string = serverURL,\n externalBaseURI: string = baseURI,\n) {\n const destination = new URL(externalServerUrl);\n destination.hostname = host;\n if (path) {\n destination.pathname = externalBaseURI ? `${externalBaseURI}/${path}` : path;\n }\n return destination.toString();\n}\n","import { KeyboardEvent } from 'react';\n\nexport function isKeyEnter<T>(event: KeyboardEvent<T>): boolean {\n return event.key === 'Enter';\n}\n\nexport function isKeyEscape<T>(event: KeyboardEvent<T>): boolean {\n return event.key === 'Escape';\n}\n\nexport function preventEscape<T>(event: KeyboardEvent<T>, callback?: () => void): void {\n if (isKeyEscape(event)) {\n event.preventDefault();\n event.stopPropagation();\n callback?.();\n }\n}\n","import { PropsWithChildren } from 'react';\n\nimport { isKeyEnter } from '../../../utils/keyEvent';\nimport { cx } from '../../../utils/styleUtils';\n\nimport style from './NavigationMenuItem.module.scss';\n\ninterface NavigationMenuItemProps {\n active?: boolean;\n className?: string;\n onClick: () => void;\n}\n\nexport default function NavigationMenuItem({\n active,\n className,\n children,\n onClick,\n}: PropsWithChildren<NavigationMenuItemProps>) {\n return (\n <div\n className={cx([style.link, active && style.current, className])}\n tabIndex={0}\n role='button'\n onClick={onClick}\n onKeyDown={(event) => {\n isKeyEnter(event) && onClick();\n }}\n >\n {children}\n </div>\n );\n}\n","import { PropsWithChildren } from 'react';\nimport { IoArrowUp } from 'react-icons/io5';\nimport { useNavigate } from 'react-router';\n\nimport { useElectronEvent } from '../../../hooks/useElectronEvent';\nimport { handleLinks } from '../../../utils/linkUtils';\nimport NavigationMenuItem from '../navigation-menu-item/NavigationMenuItem';\n\nimport style from './ClientLink.module.scss';\n\ninterface ClientLinkProps {\n current: boolean;\n to: string;\n postAction?: () => void;\n}\n\nexport default function ClientLink({ current, to, postAction, children }: PropsWithChildren<ClientLinkProps>) {\n const { isElectron } = useElectronEvent();\n const navigate = useNavigate();\n\n if (isElectron) {\n return (\n <NavigationMenuItem\n active={current}\n onClick={() => {\n handleLinks(to);\n postAction?.();\n }}\n >\n {children}\n <IoArrowUp className={style.linkIcon} />\n </NavigationMenuItem>\n );\n }\n\n return (\n <NavigationMenuItem\n active={current}\n onClick={() => {\n navigate(`/${to}`);\n postAction?.();\n }}\n >\n {children}\n </NavigationMenuItem>\n );\n}\n","import { useMemo } from 'react';\nimport { useOs, useViewportSize } from '@mantine/hooks';\n\nexport function useIsSmallDevice(): boolean {\n const { width } = useViewportSize();\n const os = useOs();\n\n return useMemo(() => (os === 'ios' || os === 'android') && width < 1300, [width, os]);\n}\n","import { IoLockClosedOutline } from 'react-icons/io5';\nimport { useNavigate } from 'react-router';\n\nimport { useIsSmallDevice } from '../../../hooks/useIsSmallDevice';\nimport NavigationMenuItem from '../navigation-menu-item/NavigationMenuItem';\n\nexport default function EditorNavigation() {\n const navigate = useNavigate();\n const isSmallDevice = useIsSmallDevice();\n\n if (!isSmallDevice) {\n return (\n <NavigationMenuItem active={location.pathname === '/editor'} onClick={() => navigate('/editor')}>\n <IoLockClosedOutline />\n Editor\n </NavigationMenuItem>\n );\n }\n\n return (\n <>\n <NavigationMenuItem active={location.pathname === '/timercontrol'} onClick={() => navigate('/timercontrol')}>\n <IoLockClosedOutline />\n Timer Controls\n </NavigationMenuItem>\n\n <NavigationMenuItem active={location.pathname === '/messagecontrol'} onClick={() => navigate('/messagecontrol')}>\n <IoLockClosedOutline />\n Message Controls\n </NavigationMenuItem>\n\n <NavigationMenuItem active={location.pathname === '/rundown'} onClick={() => navigate('/rundown')}>\n <IoLockClosedOutline />\n Rundown\n </NavigationMenuItem>\n </>\n );\n}\n","import axios from 'axios';\nimport { GetInfo, LinkOptions } from 'ontime-types';\n\nimport { apiEntryUrl } from './constants';\n\nconst sessionPath = `${apiEntryUrl}/session`;\n\n/**\n * HTTP request to retrieve application info\n */\nexport async function getInfo(): Promise<GetInfo> {\n const res = await axios.get(`${sessionPath}/info`);\n return res.data;\n}\n\n/**\n * HTTP request to get a pre-authenticated URL\n */\nexport async function generateUrl(options: LinkOptions & { baseUrl: string; path: string }): Promise<string> {\n const res = await axios.post(`${sessionPath}/url`, options);\n return res.data.url;\n}\n","import { GetInfo } from 'ontime-types';\n\nexport const ontimePlaceholderInfo: GetInfo = {\n networkInterfaces: [],\n version: '4.0.0',\n serverPort: 4001,\n publicDir: '',\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { GetInfo } from 'ontime-types';\n\nimport { queryRefetchIntervalSlow } from '../../ontimeConfig';\nimport { APP_INFO } from '../api/constants';\nimport { getInfo } from '../api/session';\nimport { ontimePlaceholderInfo } from '../models/Info';\n\nexport default function useInfo() {\n const { data, status, isError, refetch, isFetching } = useQuery<GetInfo>({\n queryKey: APP_INFO,\n queryFn: getInfo,\n placeholderData: (previousData, _previousQuery) => previousData,\n retry: 5,\n retryDelay: (attempt) => attempt * 2500,\n refetchInterval: queryRefetchIntervalSlow,\n networkMode: 'always',\n });\n\n return { data: data ?? ontimePlaceholderInfo, status, isError, refetch, isFetching };\n}\n","/**\n * copy text to clipboard\n * @throws if not supported or permission denied\n */\nexport async function copyToClipboard(text: string) {\n await navigator.clipboard?.writeText(text);\n}\n\n/**\n * Copy to clipboard but safely ignore errors\n */\nexport async function safeCopyToClipboard(text: string): Promise<void> {\n try {\n await copyToClipboard(text);\n } catch {\n // Silently ignore errors\n }\n}\n","import { PropsWithChildren, useRef, useState } from 'react';\nimport { IoCheckmark, IoCopy } from 'react-icons/io5';\n\nimport { copyToClipboard } from '../../utils/copyToClipboard';\nimport { cx } from '../../utils/styleUtils';\nimport Button from '../buttons/Button';\nimport IconButton from '../buttons/IconButton';\n\nimport style from './CopyTag.module.scss';\n\ninterface CopyTagProps {\n copyValue: string;\n disabled?: boolean;\n onClick?: () => void;\n size?: 'small' | 'medium' | 'large';\n}\n\nexport default function CopyTag({\n copyValue,\n disabled,\n size = 'medium',\n children,\n onClick,\n}: PropsWithChildren<CopyTagProps>) {\n const [copied, setCopied] = useState(false);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n const handleClick = async () => {\n try {\n await copyToClipboard(copyValue);\n setCopied(true);\n\n // reset copied state\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => setCopied(false), 2000);\n } catch {\n // ignore errors\n }\n };\n\n return (\n <div className={style.copytag}>\n {onClick !== undefined ? (\n <Button className={style.action} size={size} onClick={onClick} disabled={disabled}>\n {children}\n </Button>\n ) : (\n <div className={cx([style.label, style[size]])}>{children}</div>\n )}\n <IconButton className={style.copy} variant='primary' size={size} onClick={handleClick} disabled={disabled}>\n {copied ? <IoCheckmark /> : <IoCopy />}\n </IconButton>\n </div>\n );\n}\n","import { IoArrowUp } from 'react-icons/io5';\n\nimport useInfo from '../../../hooks-query/useInfo';\nimport { linkToOtherHost, openLink } from '../../../utils/linkUtils';\nimport CopyTag from '../../copy-tag/CopyTag';\n\nimport style from './OtherAddresses.module.scss';\n\ninterface OtherAddressesProps {\n currentLocation: string;\n}\n\nexport default function OtherAddresses({ currentLocation }: OtherAddressesProps) {\n const { data } = useInfo();\n\n // there is no point showing this if we only have one interface\n if (data.networkInterfaces.length < 2) {\n return null;\n }\n\n return (\n <>\n <div className={style.header}>Accessible on external networks</div>\n <div className={style.interfaces}>\n {data?.networkInterfaces?.map((nif) => {\n if (nif.name === 'localhost') {\n return null;\n }\n\n const address = linkToOtherHost(nif.address, currentLocation);\n\n return (\n <CopyTag key={nif.name} copyValue={address} onClick={() => openLink(address)} size='small'>\n <span className={style.interfaceCopy}>\n {nif.address} <IoArrowUp className={style.goIcon} />\n </span>\n </CopyTag>\n );\n })}\n </div>\n </>\n );\n}\n","import { memo } from 'react';\nimport { IoClose, IoContract, IoExpand, IoLockClosedOutline, IoSwapVertical } from 'react-icons/io5';\nimport { LuCoffee } from 'react-icons/lu';\nimport { useLocation } from 'react-router';\nimport { Dialog } from '@base-ui/react/dialog';\nimport { useDisclosure, useFullscreen } from '@mantine/hooks';\n\nimport { isLocalhost, supportsFullscreen } from '../../../externals';\nimport { canUseWakeLock, useKeepAwakeOptions } from '../../../features/keep-awake/useWakeLock';\nimport { navigatorConstants } from '../../../viewerConfig';\nimport { useIsSmallScreen } from '../../hooks/useIsSmallScreen';\nimport { useClientStore } from '../../stores/clientStore';\nimport { useViewOptionsStore } from '../../stores/viewOptions';\nimport IconButton from '../buttons/IconButton';\nimport { RenameClientModal } from '../client-modal/RenameClientModal';\n\nimport ClientLink from './client-link/ClientLink';\nimport EditorNavigation from './editor-navigation/EditorNavigation';\nimport NavigationMenuItem from './navigation-menu-item/NavigationMenuItem';\nimport OtherAddresses from './other-addresses/OtherAddresses';\n\nimport style from './NavigationMenu.module.scss';\n\ninterface NavigationMenuProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\nexport default memo(NavigationMenu);\nfunction NavigationMenu({ isOpen, onClose }: NavigationMenuProps) {\n const id = useClientStore((store) => store.id);\n const name = useClientStore((store) => store.name);\n const isSmallScreen = useIsSmallScreen();\n\n const [isRenameOpen, handlers] = useDisclosure(false);\n const { fullscreen, toggle } = useFullscreen();\n const { mirror, toggleMirror } = useViewOptionsStore();\n const { keepAwake, toggleKeepAwake } = useKeepAwakeOptions();\n const location = useLocation();\n\n return (\n <Dialog.Root\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n }\n }}\n >\n <Dialog.Portal>\n <Dialog.Backdrop className={style.backdrop} />\n <RenameClientModal id={id} name={name} isOpen={isRenameOpen} onClose={handlers.close} />\n <Dialog.Popup className={style.drawer}>\n <div className={style.header}>\n <Dialog.Title>Ontime</Dialog.Title>\n <IconButton variant='subtle-white' size='large' onClick={onClose}>\n <IoClose />\n </IconButton>\n </div>\n <div className={style.body}>\n {supportsFullscreen && (\n <NavigationMenuItem active={fullscreen} onClick={toggle}>\n Toggle Fullscreen\n {fullscreen ? <IoContract /> : <IoExpand />}\n </NavigationMenuItem>\n )}\n <NavigationMenuItem active={mirror} onClick={() => toggleMirror()}>\n Flip Screen\n <IoSwapVertical />\n {mirror && <span className={style.note}>Active</span>}\n </NavigationMenuItem>\n {canUseWakeLock && (\n <NavigationMenuItem active={keepAwake} onClick={toggleKeepAwake}>\n Keep Awake\n <LuCoffee />\n {keepAwake && <span className={style.note}>Active</span>}\n </NavigationMenuItem>\n )}\n <NavigationMenuItem onClick={handlers.open}>Rename Client</NavigationMenuItem>\n\n <hr className={style.separator} />\n\n <EditorNavigation />\n <ClientLink\n to='cuesheet'\n current={location.pathname === '/cuesheet'}\n postAction={isSmallScreen ? onClose : undefined}\n >\n <IoLockClosedOutline />\n Cuesheet\n </ClientLink>\n <ClientLink to='op' current={location.pathname === '/op'} postAction={isSmallScreen ? onClose : undefined}>\n <IoLockClosedOutline />\n Operator\n </ClientLink>\n\n <hr className={style.separator} />\n\n {navigatorConstants.map((route) => (\n <ClientLink\n key={route.url}\n to={route.url}\n current={location.pathname === `/${route.url}`}\n postAction={isSmallScreen ? onClose : undefined}\n >\n {route.label}\n </ClientLink>\n ))}\n </div>\n\n {isLocalhost && (\n <div>\n <OtherAddresses currentLocation={location.pathname} />\n </div>\n )}\n </Dialog.Popup>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import { memo } from 'react';\nimport { useDisclosure, useHotkeys } from '@mantine/hooks';\n\nimport { useViewParamsEditorStore } from '../view-params-editor/viewParamsEditor.store';\n\nimport FloatingNavigation from './floating-navigation/FloatingNavigation';\nimport ViewLockedIcon from './view-locked-icon/ViewLockedIcon';\nimport NavigationMenu from './NavigationMenu';\n\ninterface ViewNavigationMenuProps {\n /** prevent navigation */\n isNavigationLocked?: boolean;\n /** prevent showing settings */\n suppressSettings?: boolean;\n}\n\nexport default memo(ViewNavigationMenu);\nfunction ViewNavigationMenu({ isNavigationLocked, suppressSettings }: ViewNavigationMenuProps) {\n const [isMenuOpen, menuHandler] = useDisclosure();\n const { open: showEditFormDrawer } = useViewParamsEditorStore();\n\n useHotkeys([\n [\n 'Space',\n () => {\n if (isNavigationLocked) return;\n menuHandler.toggle();\n },\n { preventDefault: true },\n ],\n [\n 'mod + ,',\n () => {\n if (suppressSettings) return;\n showEditFormDrawer();\n },\n { preventDefault: true },\n ],\n ]);\n\n if (isNavigationLocked && suppressSettings) {\n return <ViewLockedIcon />;\n }\n\n return (\n <>\n <FloatingNavigation\n toggleMenu={isNavigationLocked ? undefined : menuHandler.toggle}\n toggleSettings={suppressSettings ? undefined : showEditFormDrawer}\n />\n {!isNavigationLocked && <NavigationMenu isOpen={isMenuOpen} onClose={menuHandler.close} />}\n </>\n );\n}\n","import { useEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\nimport { MessageTag } from 'ontime-types';\nimport { useShallow } from 'zustand/shallow';\n\nimport { useClientStore } from '../stores/clientStore';\nimport { sendSocket } from '../utils/socket';\n\nimport { useIsOnline } from './useSocket';\n\nexport const useClientPath = () => {\n const navigate = useNavigate();\n const { pathname, search } = useLocation();\n const { redirect, setRedirect } = useClientStore(\n useShallow((store) => ({\n redirect: store.redirect,\n setRedirect: store.setRedirect,\n })),\n );\n const isOnline = useIsOnline();\n\n // notify of client path changes\n useEffect(() => {\n if (!isOnline) return;\n\n sendSocket(MessageTag.ClientSetPath, pathname + search);\n }, [pathname, search, isOnline]);\n\n // navigate to new path when received from server\n useEffect(() => {\n if (redirect === '') {\n return;\n }\n\n // clear redirect\n setRedirect('');\n\n // navigate if there is a path change\n if (redirect !== pathname + search) {\n navigate(redirect, { replace: true });\n }\n }, [navigate, pathname, redirect, search, setRedirect]);\n};\n","import axios from 'axios';\nimport { URLPreset } from 'ontime-types';\n\nimport { apiEntryUrl } from './constants';\n\nconst urlPresetsPath = `${apiEntryUrl}/url-presets`;\n\n/**\n * HTTP request to retrieve all presets\n */\nexport async function getUrlPresets(): Promise<URLPreset[]> {\n const res = await axios.get(urlPresetsPath);\n return res.data;\n}\n\n/**\n * HTTP request to add a preset\n */\nexport async function postUrlPreset(data: URLPreset): Promise<URLPreset[]> {\n return (await axios.post(urlPresetsPath, data)).data;\n}\n\n/**\n * HTTP request to edit a preset\n */\nexport async function putUrlPreset(alias: string, data: URLPreset): Promise<URLPreset[]> {\n return (await axios.put(`${urlPresetsPath}/${alias}`, data)).data;\n}\n\n/**\n * HTTP request to delete a preset\n */\nexport async function deleteUrlPreset(alias: string): Promise<URLPreset[]> {\n return (await axios.delete(`${urlPresetsPath}/${alias}`)).data;\n}\n","import { useMemo } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { OntimeView, URLPreset } from 'ontime-types';\n\nimport { queryRefetchIntervalSlow } from '../../ontimeConfig';\nimport { URL_PRESETS } from '../api/constants';\nimport { deleteUrlPreset, getUrlPresets, postUrlPreset, putUrlPreset } from '../api/urlPresets';\n\ninterface FetchProps {\n skip?: boolean;\n}\n\nexport default function useUrlPresets({ skip = false }: FetchProps = {}) {\n const { data, status, isError, refetch } = useQuery({\n queryKey: URL_PRESETS,\n queryFn: getUrlPresets,\n placeholderData: (previousData, _previousQuery) => previousData,\n refetchInterval: queryRefetchIntervalSlow,\n enabled: !skip,\n });\n\n return { data: data ?? [], status, isError, refetch };\n}\n\nexport function useViewUrlPresets(view: OntimeView) {\n const { data } = useUrlPresets();\n\n const viewPresets = useMemo(() => data.filter((preset) => preset.target === view), [data, view]);\n\n return { viewPresets };\n}\n\nexport function useUpdateUrlPreset() {\n const queryClient = useQueryClient();\n\n const addFn = useMutation({\n mutationFn: postUrlPreset,\n onSuccess: (newPresets) => {\n queryClient.setQueryData(URL_PRESETS, newPresets);\n },\n });\n\n const updateFn = useMutation({\n mutationFn: ({ alias, data }: { alias: string; data: URLPreset }) => putUrlPreset(alias, data),\n onSuccess: (newPresets) => {\n queryClient.setQueryData(URL_PRESETS, newPresets);\n },\n });\n\n const deleteFn = useMutation({\n mutationFn: deleteUrlPreset,\n onSuccess: (newPresets) => {\n queryClient.setQueryData(URL_PRESETS, newPresets);\n },\n });\n\n return {\n addPreset: addFn.mutateAsync,\n updatePreset: (alias: string, data: URLPreset) => updateFn.mutateAsync({ alias, data }),\n deletePreset: deleteFn.mutateAsync,\n isMutating: addFn.isPending || updateFn.isPending || deleteFn.isPending,\n isMutationError: addFn.isError || updateFn.isError || deleteFn.isError,\n };\n}\n","import { Path, resolvePath } from 'react-router';\nimport { OntimeView, OntimeViewPresettable, URLPreset } from 'ontime-types';\nimport { checkRegex } from 'ontime-utils';\n\n/**\n * Validates a preset against defined parameters\n * Used in the context of form validation\n */\nexport function validateUrlPresetPath(preset: string): { message: string; isValid: boolean } {\n if (preset === '' || preset == null) {\n return { isValid: false, message: 'Path cannot be empty' };\n }\n\n if (preset.includes('http') || preset.includes('https') || preset.includes('www')) {\n return { isValid: false, message: 'Path should not include http, https, www' };\n }\n\n if (preset.includes('127.0.0.1') || preset.includes('localhost') || preset.includes('0.0.0.0')) {\n return { isValid: false, message: 'Path should not include hostname' };\n }\n\n if (preset.includes('editor')) {\n // no editor\n return { isValid: false, message: 'No path to editor page allowed' };\n }\n\n return { isValid: true, message: 'ok' };\n}\n\n/**\n * Checks whether the current location corresponds to a preset and returns the new path if necessary\n */\nexport function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): string | null {\n // if we're already on a preset path, no need to redirect\n if (isPresetPath(location)) {\n return null;\n }\n\n // NOTE: verify that this resolves correctly in cloud\n const currentPath = `${location.pathname}${location.search}`.substring(1);\n const currentURL = getCurrentPath(location);\n const token = new URLSearchParams(location.search).get('token');\n const isLocked = location.search.includes('n=1');\n\n for (const preset of urlPresets) {\n if (!preset.enabled) continue;\n /**\n * If the page is a known alias it would be like\n * /preset/{alias} <- locked to a preset\n * or\n * /{target}?alias={alias} <- unwrapped preset options\n *\n * we need to compare the saved preset to the current path to see if we need to redirect\n */\n if (preset.alias === currentURL || preset.target === currentURL) {\n const newPath = generatePathFromPreset(preset.target, preset.search, preset.alias, isLocked, token);\n /**\n * if the current path is equivalent to the new path, we return null\n * this means we will not redirect\n */\n return arePathsEquivalent(currentPath, newPath) ? null : newPath;\n }\n }\n\n return null;\n}\n\n/**\n * Resolves the current path accounting for the base URI\n * Returns the alias if it's a preset path, or the last segment otherwise\n */\nexport function getCurrentPath(location: Path): string {\n // 1. get path without query parameters\n const pathWithoutQuery = location.pathname.split('?')[0];\n // 2. split path into segments and filter out empty segments\n const segments = pathWithoutQuery.split('/').filter(Boolean);\n\n // If this is a preset path, return the alias (last segment)\n if (segments[0] === 'preset' && segments.length > 1) {\n return segments[1];\n }\n\n // Otherwise return the last segment (view name)\n return segments[segments.length - 1] || '';\n}\n\n/**\n * Handles generating a path and search parameters from a preset\n * This is done when we want to keep the current navigation and unwrap the search params\n */\nexport function generatePathFromPreset(\n target: Omit<OntimeView, 'editor'>,\n search: string,\n alias: string,\n locked: boolean,\n token: string | null,\n): string {\n const path = resolvePath(`${target}?${search}`);\n const searchParams = new URLSearchParams(path.search);\n\n // save the alias so we have a reference to it being a preset and can update if necessary\n searchParams.set('alias', alias);\n\n // maintain params from the URL search feature\n if (locked) {\n searchParams.set('n', '1');\n }\n\n if (token) {\n searchParams.set('token', token);\n }\n\n // return path concatenated without the leading slash\n return `${path.pathname}?${searchParams}`.substring(1);\n}\n\n/**\n * Utility checks if two paths are equivalent\n * For preset paths, only compares the path (since params are stored in session)\n * For regular paths, compares path and search params (ignoring token)\n */\nexport function arePathsEquivalent(currentPath: string, newPath: string): boolean {\n const currentUrl = new URL(currentPath, document.location.origin);\n const newUrl = new URL(newPath, document.location.origin);\n\n // For preset paths, only compare the path\n if (currentUrl.pathname.startsWith('/preset/') || newUrl.pathname.startsWith('/preset/')) {\n return currentUrl.pathname === newUrl.pathname;\n }\n\n // For regular paths, compare path and search params (ignoring token)\n if (currentUrl.pathname !== newUrl.pathname) {\n return false;\n }\n\n currentUrl.searchParams.delete('token');\n currentUrl.searchParams.delete('n');\n newUrl.searchParams.delete('token');\n newUrl.searchParams.delete('n');\n\n return currentUrl.searchParams.toString() === newUrl.searchParams.toString();\n}\n\n/**\n * Generates a URL preset from a user given alias and URL.\n */\nexport function generateUrlPresetOptions(alias: string, userUrl: string): URLPreset {\n let sanitisedUrl = userUrl;\n // we need to ensure the URL has a protocol, but it doesnt matter which\n if (!checkRegex.startsWithHttp(userUrl.toLowerCase())) {\n sanitisedUrl = `http://${sanitisedUrl}`;\n }\n\n const url = new URL(sanitisedUrl);\n const path = getCurrentPath(url);\n\n if (!isPresettableView(path)) {\n throw new Error(`Invalid target view: ${path}`);\n }\n\n return {\n alias,\n target: path,\n search: url.searchParams.toString(),\n enabled: true,\n };\n}\n\nfunction isPresettableView(view: string): view is OntimeViewPresettable {\n return view !== OntimeView.Editor && Object.values(OntimeView).includes(view as OntimeView);\n}\n\n/**\n * Check if current location is a preset path\n */\nexport function isPresetPath(location: Path): boolean {\n const segments = location.pathname.split('/').filter(Boolean);\n return segments[0] === 'preset';\n}\n","import { HTMLAttributes, PropsWithChildren, ReactNode } from 'react';\nimport { IoAdd } from 'react-icons/io5';\n\nimport Button from '../../../common/components/buttons/Button';\nimport { cx } from '../../../common/utils/styleUtils';\n\nimport style from './PanelUtils.module.scss';\n\nexport function Header({ children }: { children: ReactNode }) {\n return <h2 className={style.header}>{children}</h2>;\n}\n\nexport function SubHeader({ children }: { children: ReactNode }) {\n return <h3 className={style.subheader}>{children}</h3>;\n}\n\nexport function Title({ children }: { children: ReactNode }) {\n return <h4 className={style.title}>{children}</h4>;\n}\n\ntype AllowedTags = 'div' | 'form';\ntype SectionProps<C extends AllowedTags> = {\n as?: C;\n children: ReactNode;\n} & React.JSX.IntrinsicElements[C];\n\nexport function Section<C extends AllowedTags = 'div'>({ as, className, children, ...props }: SectionProps<C>) {\n const Element = as ?? 'div';\n return (\n <Element className={cx([style.section, className])} {...(props as HTMLAttributes<HTMLElement>)}>\n {children}\n </Element>\n );\n}\n\nexport function Indent<C extends AllowedTags = 'div'>({ as, className, children, ...props }: SectionProps<C>) {\n const Element = as ?? 'div';\n return (\n <Element className={cx([style.indent, className])} {...(props as HTMLAttributes<HTMLElement>)}>\n {children}\n </Element>\n );\n}\n\nexport function Paragraph({ children }: { children: ReactNode }) {\n return <p className={style.paragraph}>{children}</p>;\n}\n\nexport function Card({ children, className, ...props }: { children: ReactNode } & React.JSX.IntrinsicElements['div']) {\n return (\n <div className={cx([style.card, className])} {...props}>\n {children}\n </div>\n );\n}\n\nexport function Table({ className, children }: { className?: string; children: ReactNode }) {\n return (\n <div className={style.pad}>\n <table className={cx([style.table, className])}>{children}</table>\n </div>\n );\n}\n\nexport function TableEmpty({ label, handleClick }: { label?: string; handleClick?: () => void }) {\n return (\n <tr className={style.empty}>\n <td colSpan={99}>\n <div>{label ?? 'No data yet'}</div>\n {handleClick && (\n <Button onClick={handleClick} disabled={!handleClick} variant='primary'>\n New <IoAdd />\n </Button>\n )}\n </td>\n </tr>\n );\n}\n\nexport function ListGroup({ className, children }: { className?: string; children: ReactNode }) {\n return <ul className={cx([style.listGroup, className])}>{children}</ul>;\n}\n\nexport function ListItem({ children }: { children: ReactNode }) {\n return <li className={style.listItem}>{children}</li>;\n}\n\nexport function Field({ title, description, error }: { title: string; description: string; error?: string }) {\n return (\n <div className={style.fieldTitle}>\n {title}\n {error && <Error>{error}</Error>}\n {!error && description && <Description>{description}</Description>}\n </div>\n );\n}\n\nexport function Description({ children }: { children: ReactNode }) {\n return <div className={style.fieldDescription}>{children}</div>;\n}\n\nexport function Highlight({ children }: { children: ReactNode }) {\n return <code className={style.highlight}>{children}</code>;\n}\n\nexport function BlockQuote({ children }: { children: ReactNode }) {\n return <blockquote className={style.blockquote}>{children}</blockquote>;\n}\n\nexport function Error({ children, className }: { children: ReactNode } & React.JSX.IntrinsicElements['div']) {\n return <div className={cx([style.fieldError, className])}>{children}</div>;\n}\n\nexport function Divider() {\n return <hr className={style.divider} />;\n}\n\nexport function Loader({ isLoading }: { isLoading: boolean }) {\n if (!isLoading) {\n return null;\n }\n return (\n <div className={style.overlay}>\n <div className={style.loader} />\n </div>\n );\n}\n\ntype AllowedInlineTags = 'div' | 'td';\ntype InlineProps<C extends AllowedInlineTags> = {\n as?: C;\n relation?: 'inner' | 'component' | 'section';\n align?: 'start' | 'end' | 'apart';\n className?: string;\n};\n\nexport function InlineElements<C extends AllowedInlineTags = 'div'>({\n children,\n as,\n relation = 'component',\n align = 'start',\n className,\n}: PropsWithChildren<InlineProps<C>>) {\n const Element = as ?? 'div';\n return <Element className={cx([style.inlineElements, style[relation], style[align], className])}>{children}</Element>;\n}\n","import { useCallback, useState } from 'react';\nimport { IoClose } from 'react-icons/io5';\nimport { LogOrigin } from 'ontime-types';\n\nimport Button from '../../common/components/buttons/Button';\nimport { clearLogs, useLogData } from '../../common/stores/logger';\nimport * as Panel from '../app-settings/panel-utils/PanelUtils';\n\nimport style from './Log.module.scss';\n\nexport default function Log() {\n const { logs: logData } = useLogData();\n\n const [showClient, setShowClient] = useState(true);\n const [showServer, setShowServer] = useState(true);\n const [showRx, setShowRx] = useState(true);\n const [showTx, setShowTx] = useState(true);\n const [showPlayback, setShowPlayback] = useState(true);\n const [showUser, setShowUser] = useState(true);\n\n const matchers: LogOrigin[] = [];\n if (showUser) {\n matchers.push(LogOrigin.User);\n }\n if (showClient) {\n matchers.push(LogOrigin.Client);\n }\n if (showServer) {\n matchers.push(LogOrigin.Server);\n }\n if (showRx) {\n matchers.push(LogOrigin.Rx);\n }\n if (showTx) {\n matchers.push(LogOrigin.Tx);\n }\n if (showPlayback) {\n matchers.push(LogOrigin.Playback);\n }\n\n const filteredData = logData.filter((entry) => matchers.some((match) => entry.origin === match));\n\n const disableOthers = useCallback((toEnable: LogOrigin) => {\n toEnable === LogOrigin.User ? setShowUser(true) : setShowUser(false);\n toEnable === LogOrigin.Client ? setShowClient(true) : setShowClient(false);\n toEnable === LogOrigin.Server ? setShowServer(true) : setShowServer(false);\n toEnable === LogOrigin.Rx ? setShowRx(true) : setShowRx(false);\n toEnable === LogOrigin.Tx ? setShowTx(true) : setShowTx(false);\n toEnable === LogOrigin.Playback ? setShowPlayback(true) : setShowPlayback(false);\n }, []);\n\n return (\n <>\n <Panel.InlineElements className={style.buttonBar}>\n <Button\n variant={showUser ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowUser((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.User)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.User}\n </Button>\n <Button\n variant={showClient ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowClient((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.Client)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.Client}\n </Button>\n <Button\n variant={showServer ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowServer((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.Server)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.Server}\n </Button>\n <Button\n variant={showPlayback ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowPlayback((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.Playback)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.Playback}\n </Button>\n <Button\n variant={showRx ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowRx((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.Rx)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.Rx}\n </Button>\n <Button\n variant={showTx ? 'primary' : 'subtle'}\n size='small'\n onClick={() => setShowTx((s) => !s)}\n onAuxClick={() => disableOthers(LogOrigin.Tx)}\n onContextMenu={(e) => e.preventDefault()}\n >\n {LogOrigin.Tx}\n </Button>\n <Button variant='subtle-destructive' size='small' onClick={clearLogs} className={style.apart}>\n <IoClose /> Clear\n </Button>\n </Panel.InlineElements>\n <ul className={style.log}>\n {filteredData.map((logEntry) => (\n <li key={logEntry.id} className={`${style.logEntry} ${style[logEntry.level]} `}>\n <span className={style.time}>{logEntry.time}</span>\n <span className={style.origin}>{logEntry.origin}</span>\n <span className={style.msg}>{logEntry.text}</span>\n </li>\n ))}\n </ul>\n </>\n );\n}\n","import style from './Loader.module.scss';\n\nexport default function Loader() {\n return (\n <div className={style.loader}>\n <div className={style.ellipsis}>\n <div />\n <div />\n <div />\n <div />\n </div>\n </div>\n );\n}\n","import * as React from \"react\";\nconst SvgEmpty = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", width: 275, height: 275, fill: \"none\", viewBox: \"0 0 275 275\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { fill: \"#4D4D4D\", d: \"M49.83 133.919c0-18.343 3.531-34.692 10.595-49.048 7.064-14.355 17.204-25.464 30.42-33.325 13.33-7.861 28.768-11.792 46.313-11.792 24.952 0 45.288 7.633 61.011 22.9 15.837 15.267 24.666 36.003 26.489 62.207l.342 12.647c0 28.369-7.918 51.155-23.755 68.359-15.836 17.09-37.085 25.635-63.745 25.635-26.66 0-47.965-8.545-63.916-25.635-15.836-17.09-23.755-40.332-23.755-69.726v-2.222zm49.389 3.589c0 17.545 3.304 30.989 9.912 40.332 6.608 9.228 16.064 13.843 28.369 13.843 11.963 0 21.305-4.558 28.028-13.672 6.722-9.229 10.083-23.926 10.083-44.092 0-17.204-3.361-30.534-10.083-39.99-6.723-9.457-16.179-14.185-28.37-14.185-12.076 0-21.419 4.728-28.027 14.185-6.608 9.342-9.912 23.869-9.912 43.579z\" }), /* @__PURE__ */ React.createElement(\"mask\", { id: \"a\", width: 177, height: 193, x: 49, y: 39, maskUnits: \"userSpaceOnUse\" }, /* @__PURE__ */ React.createElement(\"path\", { fill: \"#fff\", d: \"M49.83 133.919c0-18.343 3.531-34.692 10.595-49.048 7.064-14.355 17.204-25.464 30.42-33.325 13.33-7.861 28.768-11.792 46.313-11.792 24.952 0 45.288 7.633 61.011 22.9 15.837 15.267 24.666 36.003 26.489 62.207l.342 12.647c0 28.369-7.918 51.155-23.755 68.359-15.836 17.09-37.085 25.635-63.745 25.635-26.66 0-47.965-8.545-63.916-25.635-15.836-17.09-23.755-40.332-23.755-69.726v-2.222zm49.389 3.589c0 17.545 3.304 30.989 9.912 40.332 6.608 9.228 16.064 13.843 28.369 13.843 11.963 0 21.305-4.558 28.028-13.672 6.722-9.229 10.083-23.926 10.083-44.092 0-17.204-3.361-30.534-10.083-39.99-6.723-9.457-16.179-14.185-28.37-14.185-12.076 0-21.419 4.728-28.027 14.185-6.608 9.342-9.912 23.869-9.912 43.579z\" })), /* @__PURE__ */ React.createElement(\"g\", { mask: \"url(#a)\" }, /* @__PURE__ */ React.createElement(\"path\", { fill: \"url(#paint0_linear)\", d: \"M19.07 95.347c15.556-6.524 14.288-34.989 22.08-30.11 9.74 6.099 0-23.084 13.549-16.56 21.714 10.455-10.977 18.645 12.296 32.007 23.274 13.362 117.508 24.346 150.898 90.045 12.812 25.21 19.341 32.653 21.836 34.543 1.508-.13 1.78 1.349 0 0-.38.033-.838.168-1.362.476-5.516 3.245-106.876 85.867-148.54 34.124C48.162 188.129 2.25 140.221 14.31 127.463c9.648-10.205 1.393-25.103 4.76-32.116z\" }), /* @__PURE__ */ React.createElement(\"path\", { fill: \"url(#paint1_linear)\", d: \"M42.153 69.754c-7.791-4.88-.412 13.939-24.087 22.582-3.366 7.013 4.63 19.904-5.018 30.109-12.06 12.757 37.623 69.197 79.288 120.94 41.664 51.743 123.453-24.356 128.969-27.6 5.515-3.245 14.092 10.618-10.114-37.154-33.382-65.882-126.481-75.197-149.59-98.582-20.018-20.26 33.92-42.547 10.662-37.896-30.11 6.022-20.37 33.7-30.11 27.6z\" })), /* @__PURE__ */ React.createElement(\"defs\", null, /* @__PURE__ */ React.createElement(\"linearGradient\", { id: \"paint0_linear\", x1: 93.96, x2: 67.62, y1: -33.993, y2: 351.251, gradientUnits: \"userSpaceOnUse\" }, /* @__PURE__ */ React.createElement(\"stop\", null), /* @__PURE__ */ React.createElement(\"stop\", { offset: 1, stopColor: \"#414141\", stopOpacity: 0 })), /* @__PURE__ */ React.createElement(\"linearGradient\", { id: \"paint1_linear\", x1: 88.433, x2: 62.092, y1: -37.321, y2: 347.924, gradientUnits: \"userSpaceOnUse\" }, /* @__PURE__ */ React.createElement(\"stop\", { stopColor: \"#FF005C\", stopOpacity: 0.74 }), /* @__PURE__ */ React.createElement(\"stop\", { offset: 0 }), /* @__PURE__ */ React.createElement(\"stop\", { offset: 1, stopColor: \"#242424\", stopOpacity: 0 }))));\nexport default SvgEmpty;\n","import EmptyImage from '../../../assets/images/empty.svg?react';\n\nimport style from './NotFound.module.scss';\n\nexport default function NotFound() {\n return (\n <div className={style.notFound}>\n <section className={style.content}>\n <EmptyImage />\n <h1>Not found</h1>\n <div>\n The page you are after was not found.\n <br />\n It may have moved or your URL may be incorrect.\n <br />\n Double check the URL and try again.\n </div>\n </section>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\nconst scriptTagId = 'ontime-override';\n\nexport const useRuntimeStylesheet = (pathToFile?: string): { shouldRender: boolean } => {\n const [shouldRender, setShouldRender] = useState(false);\n\n /**\n * When a view mounts or the stylesheet path changes we need to handle potentially loading a new stylesheet\n * - if no path is given, ensure there is no stylesheet loaded\n * - if a path is given, fetch the stylesheet and inject it into the document head\n * @returns { shouldRender: boolean } - after the stylesheet is handled and the clients are ready to render\n */\n useEffect(() => {\n if (!pathToFile) {\n handleNoStylesheet();\n return;\n }\n\n // there is already a stylesheet loaded, nothing further to do\n if (document.getElementById(scriptTagId)) {\n setShouldRender(true);\n return;\n }\n\n setShouldRender(false);\n\n fetchStylesheetData(pathToFile)\n .then((data: string | undefined) => {\n if (!data) {\n console.error('Error loading stylesheet: no data');\n return;\n }\n return injectStylesheet(data);\n })\n .catch((error: unknown) => {\n console.error(`Error loading stylesheet: ${error}`);\n })\n .finally(() => {\n // schedule render for next tick\n setTimeout(() => setShouldRender(true), 0);\n });\n\n /**\n * No stylesheet was provided, remove any existing stylesheet\n */\n function handleNoStylesheet() {\n document.getElementById(scriptTagId)?.remove();\n setShouldRender(true);\n }\n\n /**\n * Get data from backend\n */\n async function fetchStylesheetData(path: string) {\n const response = await fetch(path);\n if (response.ok) {\n return response.text();\n }\n return undefined;\n }\n\n /**\n * Add a stylesheet with given content to the document head\n */\n async function injectStylesheet(styleContent: string) {\n const styleSheet = document.createElement('style');\n styleSheet.setAttribute('id', scriptTagId);\n styleSheet.innerHTML = styleContent;\n document.head.append(styleSheet);\n }\n }, [pathToFile]);\n\n return { shouldRender };\n};\n","import axios from 'axios';\nimport type { ViewSettings } from 'ontime-types';\n\nimport { apiEntryUrl } from './constants';\n\nconst viewSettingsPath = `${apiEntryUrl}/view-settings`;\n\n/**\n * HTTP request to fetch view settings\n * @returns\n */\nexport async function getViewSettings(): Promise<ViewSettings> {\n const res = await axios.get(viewSettingsPath);\n return res.data;\n}\n\n/**\n * HTTP request to update view settings\n * needs to update entire objects, not just a patch\n */\nexport async function postViewSettings(data: ViewSettings): Promise<ViewSettings> {\n const res = await axios.post(viewSettingsPath, data);\n return res.data;\n}\n","import { ViewSettings } from 'ontime-types';\n\nexport const viewsSettingsPlaceholder: ViewSettings = {\n dangerColor: '#ff7300',\n normalColor: '#ffffffcc',\n overrideStyles: false,\n warningColor: '#ffa528',\n};\n","import { useMutation, useQuery } from '@tanstack/react-query';\nimport { MILLIS_PER_HOUR } from 'ontime-utils';\n\nimport { getViewSettings, postViewSettings } from '../../common/api/viewSettings';\nimport { ontimeQueryClient } from '../../common/queryClient';\nimport { VIEW_SETTINGS } from '../api/constants';\nimport { viewsSettingsPlaceholder } from '../models/ViewSettings.type';\n\nexport default function useViewSettings() {\n const { data, status } = useQuery({\n queryKey: VIEW_SETTINGS,\n queryFn: getViewSettings,\n placeholderData: (previousData, _previousQuery) => previousData,\n staleTime: MILLIS_PER_HOUR,\n });\n\n const { mutateAsync } = useMutation({\n mutationFn: postViewSettings,\n onMutate: () => {\n ontimeQueryClient.cancelQueries({ queryKey: VIEW_SETTINGS });\n },\n onSuccess: (data) => {\n ontimeQueryClient.setQueryData(VIEW_SETTINGS, data);\n },\n });\n\n return { data: data ?? viewsSettingsPlaceholder, status, mutateAsync };\n}\n","import { PropsWithChildren } from 'react';\n\nimport { overrideStylesURL } from '../common/api/constants';\nimport { useRuntimeStylesheet } from '../common/hooks/useRuntimeStylesheet';\nimport useViewSettings from '../common/hooks-query/useViewSettings';\n\nimport Loader from './common/loader/Loader';\n\nexport default function ViewLoader({ children }: PropsWithChildren) {\n const { data } = useViewSettings();\n const { shouldRender } = useRuntimeStylesheet(data.overrideStyles ? overrideStylesURL : undefined);\n\n // eventually we would want to leverage suspense here\n // while the feature is not ready, we simply trigger a loader\n // suspense would have the advantage of being triggered also by react-query\n\n if (!shouldRender) {\n return <Loader />;\n }\n\n // eslint-disable-next-line react/jsx-no-useless-fragment -- ensuring JSX return\n return <>{children}</>;\n}\n","export const ONTIME_VERSION = \"4.3.0\";\n","import React from 'react';\nimport { createRoutesFromChildren, matchRoutes, Routes, useLocation, useNavigationType } from 'react-router';\nimport * as Sentry from '@sentry/react';\n\nimport { ONTIME_VERSION } from './ONTIME_VERSION';\n\n// https://docs.sentry.io/platforms/javascript/configuration/filtering/#decluttering-sentry\nexport const sentryRecommendedIgnore = [\n // Random plugins/extensions\n 'top.GLOBALS',\n // See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html\n 'originalCreateNotification',\n 'canvas.contentDocument',\n 'MyApp_RemoveAllHighlights',\n 'http://tt.epicplay.com',\n \"Can't find variable: ZiteReader\",\n 'jigsaw is not defined',\n 'ComboSearch is not defined',\n 'http://loading.retry.widdit.com/',\n 'atomicFindClose',\n // Facebook borked\n 'fb_xd_fragment',\n // ISP \"optimizing\" proxy - `Cache-Control: no-transform` seems to\n // reduce this. (thanks @acdha)\n // See http://stackoverflow.com/questions/4113268\n 'bmi_SafeAddOnload',\n 'EBCallBackMessageReceived',\n // See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx\n 'conduitPage',\n];\nexport const sentryDsn = 'https://5e4d2c4b57ab409cb98d4c08b2014755@o4504288369836032.ingest.sentry.io/4504288371343360';\n\nexport const initializeSentry = () => {\n Sentry.init({\n dsn: sentryDsn,\n integrations: [\n Sentry.reactRouterV7BrowserTracingIntegration({\n useEffect: React.useEffect,\n useLocation,\n useNavigationType,\n createRoutesFromChildren,\n matchRoutes,\n }),\n ],\n tracesSampleRate: 0.3,\n release: ONTIME_VERSION,\n enabled: import.meta.env.PROD,\n ignoreErrors: [\n ...sentryRecommendedIgnore,\n // Dynamic imports and chunks\n /Unable to preload CSS/i,\n /dynamically imported module/i,\n /Failed to fetch dynamically imported module/i,\n /Loading chunk \\d+ failed/i,\n /Loading CSS chunk \\d+ failed/i,\n /ChunkLoadError/i,\n /Loading module .+ failed/i,\n // Data/offline related errors\n /Cannot read propert.* of undefined/i,\n /Cannot read propert.* of null/i,\n /Network request failed/i,\n /Failed to fetch/i,\n /NetworkError/i,\n /The operation couldn't be completed/i,\n ],\n denyUrls: [/extensions\\//i, /^chrome:\\/\\//i, /^chrome-extension:\\/\\//i, /external\\//i],\n beforeSend(event) {\n // Drop errors that happen during known data-unavailable states\n const error = event.exception?.values?.[0]?.value;\n if (\n error &&\n (error.includes('Cannot read property') ||\n error.includes('Cannot read properties') ||\n error.includes('Network request failed') ||\n error.includes('Failed to fetch'))\n ) {\n // Don't send these errors to Sentry since they're expected when data isn't available\n return null;\n }\n\n return event;\n },\n });\n\n return Sentry.withSentryReactRouterV6Routing(Routes);\n};\n","import { ComponentType, lazy, Suspense, useEffect, useMemo } from 'react';\nimport { Navigate, Route, useLocation, useNavigate, useParams } from 'react-router';\nimport { OntimeView, OntimeViewPresettable, URLPreset } from 'ontime-types';\n\nimport ViewNavigationMenu from './common/components/navigation-menu/ViewNavigationMenu';\nimport { PresetContext } from './common/context/PresetContext';\nimport { useClientPath } from './common/hooks/useClientPath';\nimport useUrlPresets from './common/hooks-query/useUrlPresets';\nimport { getRouteFromPreset } from './common/utils/urlPresets';\nimport Log from './features/log/Log';\nimport Loader from './views/common/loader/Loader';\nimport NotFound from './views/common/not-found/NotFound';\nimport ViewLoader from './views/ViewLoader';\nimport { getIsNavigationLocked, sessionScope } from './externals';\nimport { initializeSentry } from './sentry.config';\n\nconst Timer = lazy(() => import('./views/timer/Timer'));\nconst Countdown = lazy(() => import('./views/countdown/Countdown'));\nconst Backstage = lazy(() => import('./views/backstage/Backstage'));\nconst StudioClock = lazy(() => import('./views/studio/Studio'));\nconst Timeline = lazy(() => import('./views/timeline/TimelinePage'));\nconst ProjectInfo = lazy(() => import('./views/project-info/ProjectInfo'));\n\nconst Editor = lazy(() => import('./views/editor/ProtectedEditor'));\nconst Cuesheet = lazy(() => import('./views/cuesheet/ProtectedCuesheet'));\nconst Operator = lazy(() => import('./features/operator/OperatorExport'));\n\nconst EditorFeatureWrapper = lazy(() => import('./features/EditorFeatureWrapper'));\nconst RundownPanel = lazy(() => import('./features/rundown/RundownExport'));\nconst TimerControl = lazy(() => import('./features/control/playback/TimerControlExport'));\nconst MessageControl = lazy(() => import('./features/control/message/MessageControlExport'));\n\n// Initialize Sentry with our configuration\nconst SentryRouter = initializeSentry();\n\nexport default function AppRouter() {\n // handle client path changes\n useClientPath();\n\n return (\n <Suspense fallback={<Loader />}>\n <SentryRouter>\n <Route path='/' element={<Navigate to='/timer' />} />\n <Route\n path='timer'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <Timer />\n </ViewLoader>\n }\n />\n <Route\n path='countdown'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <Countdown />\n </ViewLoader>\n }\n />\n <Route\n path='backstage'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <Backstage />\n </ViewLoader>\n }\n />\n <Route\n path='studio'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <StudioClock />\n </ViewLoader>\n }\n />\n <Route\n path='timeline'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <Timeline />\n </ViewLoader>\n }\n />\n <Route\n path='info'\n element={\n <ViewLoader>\n <ViewNavigationMenu suppressSettings isNavigationLocked={getIsNavigationLocked()} />\n <ProjectInfo />\n </ViewLoader>\n }\n />\n {/*/!* Protected Routes *!/*/}\n <Route path='editor' element={<Editor />} />\n <Route path='cuesheet' element={<Cuesheet />} />\n <Route\n path='op'\n element={\n <ViewLoader>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />\n <Operator />\n </ViewLoader>\n }\n />\n {/*/!* Protected Routes - Elements *!/*/}\n <Route\n path='rundown'\n element={\n <EditorFeatureWrapper>\n <RundownPanel />\n </EditorFeatureWrapper>\n }\n />\n <Route\n path='timercontrol'\n element={\n <EditorFeatureWrapper>\n <TimerControl />\n </EditorFeatureWrapper>\n }\n />\n <Route\n path='messagecontrol'\n element={\n <EditorFeatureWrapper>\n <MessageControl />\n </EditorFeatureWrapper>\n }\n />\n <Route\n path='log'\n element={\n <EditorFeatureWrapper>\n <Log />\n </EditorFeatureWrapper>\n }\n />\n {/**\n * If the views are prefixed with the \"preset\" path, we are in a locked preset\n * Locked presets do not expose their parameters\n */}\n <Route path='preset/:alias' element={<PresetView />} />\n\n {/**\n * If we havent matched any views or presets, we may be in an unlocked preset\n * Unlocked presets are unwrapped to expose their target and parameters\n */}\n <Route path='*' element={<RedirectPreset />} />\n </SentryRouter>\n </Suspense>\n );\n}\n\nconst PresetViewMap: Record<OntimeViewPresettable, ComponentType> = {\n [OntimeView.Cuesheet]: Cuesheet,\n [OntimeView.Operator]: Operator,\n [OntimeView.Timer]: Timer,\n [OntimeView.Backstage]: Backstage,\n [OntimeView.Timeline]: Timeline,\n [OntimeView.StudioClock]: StudioClock,\n [OntimeView.Countdown]: Countdown,\n [OntimeView.ProjectInfo]: ProjectInfo,\n};\n\n/**\n * This view will mask a configured canonical route\n * and inject the preset search parameters to context\n * User are not able to configure the parameters locked presets\n */\nfunction PresetView() {\n const { data, status } = useUrlPresets();\n const { alias } = useParams();\n\n const preset: URLPreset | undefined = useMemo(() => {\n if (status === 'pending' || !alias) return;\n return data.find((p) => p.alias === alias && p.enabled);\n }, [data, status, alias]);\n\n if (status === 'pending') {\n return <Loader />;\n }\n\n /**\n * We need to check the session scope to determine if the user can navigate\n * If the user has a global scope, they can navigate freely\n * Otherwise, they are locked to the preset view\n */\n const showNav = sessionScope === 'rw';\n\n /**\n * If we are in a preset path but cannot find a preset, we will need to show a not found page\n * This can happen if the preset was deleted or disabled\n */\n if (!preset) {\n return (\n <>\n <ViewNavigationMenu isNavigationLocked={!showNav} suppressSettings />\n <NotFound />\n </>\n );\n }\n\n /**\n * Locked presets do not allow configuration changes\n * Whether the user can navigate is determined by the locked param\n *\n * We inject the preset to the context value for the view to consume\n */\n const Component = PresetViewMap[preset.target as OntimeViewPresettable];\n return (\n <PresetContext value={preset}>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} suppressSettings />\n {Component ? <Component /> : <NotFound />}\n </PresetContext>\n );\n}\n\nfunction RedirectPreset() {\n const { data, status } = useUrlPresets();\n const navigate = useNavigate();\n const location = useLocation();\n\n // checks if we are in a preset path and resolves a destination URL\n const destination = useMemo(() => {\n if (status === 'pending') return null;\n return getRouteFromPreset(location, data);\n }, [data, location, status]);\n\n // if we have a destination, we will navigate to it\n useEffect(() => {\n if (destination) {\n navigate(`/${destination}`, { replace: true });\n }\n }, [destination, navigate]);\n\n if (status === 'pending') {\n return <Loader />;\n }\n\n return (\n <>\n <ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} suppressSettings />\n <NotFound />\n </>\n );\n}\n","import { BrowserRouter } from 'react-router';\nimport { Tooltip } from '@base-ui/react/tooltip';\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools';\n\nimport ErrorBoundary from './common/components/error-boundary/ErrorBoundary';\nimport IdentifyOverlay from './common/components/identify-overlay/IdentifyOverlay';\nimport { AppContextProvider } from './common/context/AppContext';\nimport { ontimeQueryClient } from './common/queryClient';\nimport { connectSocket } from './common/utils/socket';\nimport KeepAwake from './features/keep-awake/KeepAwake';\nimport { TranslationProvider } from './translation/TranslationProvider';\nimport AppRouter from './AppRouter';\nimport { baseURI } from './externals';\n\nconnectSocket();\n\nfunction App() {\n return (\n <QueryClientProvider client={ontimeQueryClient}>\n <AppContextProvider>\n <Tooltip.Provider>\n <BrowserRouter basename={baseURI}>\n <div className='App'>\n <ErrorBoundary>\n <TranslationProvider>\n <IdentifyOverlay />\n <KeepAwake />\n <AppRouter />\n </TranslationProvider>\n </ErrorBoundary>\n <ReactQueryDevtools initialIsOpen={false} />\n </div>\n <ErrorBoundary>\n <div id='identify-portal' />\n </ErrorBoundary>\n </BrowserRouter>\n </Tooltip.Provider>\n </AppContextProvider>\n </QueryClientProvider>\n );\n}\n\nexport default App;\n","import { StrictMode } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport App from './App';\n\nimport './index.scss';\n\nconst container = document.getElementById('root');\nconst root = createRoot(container as Element);\n\nroot.render(\n <StrictMode>\n <App />\n </StrictMode>,\n);\n"],"file":"assets/index-B81u4hxi.js"}