@24i/bigscreen-sdk 1.0.4 → 1.0.5-4.alpha-2832

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 (292) hide show
  1. package/README.md +2 -3
  2. package/ci/is_ci_job_skippable.sh +153 -0
  3. package/package.json +55 -34
  4. package/packages/adobe-heartbeat/src/AdobeHeartbeat.ts +9 -9
  5. package/packages/analytics/README.md +8 -0
  6. package/packages/analytics/src/A.ts +1 -0
  7. package/packages/analytics/src/Analytics.ts +1 -0
  8. package/packages/analytics/src/analyticsOnScroll.ts +1 -0
  9. package/packages/analytics/src/clients/ConsoleAnalytics/ConsoleAnalytics.ts +1 -0
  10. package/packages/analytics/src/clients/ConsoleAnalytics/index.ts +1 -0
  11. package/packages/analytics/src/clients/GoogleAnalytics/GoogleAnalytics.ts +196 -0
  12. package/packages/analytics/src/clients/GoogleAnalytics/constants.ts +126 -0
  13. package/packages/analytics/src/clients/GoogleAnalytics/getUrl.ts +17 -0
  14. package/packages/analytics/src/clients/GoogleAnalytics/index.ts +2 -0
  15. package/packages/analytics/src/clients/GoogleAnalytics/interface.ts +82 -0
  16. package/packages/analytics/src/clients/GoogleAnalytics/mapPayload.ts +51 -0
  17. package/packages/analytics/src/clients/GoogleAnalytics/prepareBody.ts +14 -0
  18. package/packages/analytics/src/clients/TealiumAnalytics/TealiumAnalytics.ts +181 -0
  19. package/packages/analytics/src/clients/TealiumAnalytics/constants.ts +106 -0
  20. package/packages/analytics/src/clients/TealiumAnalytics/findForLanguage.ts +9 -0
  21. package/packages/analytics/src/clients/TealiumAnalytics/index.ts +4 -0
  22. package/packages/analytics/src/clients/TealiumAnalytics/interface.ts +35 -0
  23. package/packages/analytics/src/clients/TealiumAnalytics/mappers/__mocks__/mediaPayload.ts +72 -0
  24. package/packages/analytics/src/clients/TealiumAnalytics/mappers/helper.ts +36 -0
  25. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapAppError.ts +13 -0
  26. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapAppOpen.ts +13 -0
  27. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapFavoriteAdd.ts +11 -0
  28. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapFavoriteRemove.ts +11 -0
  29. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapPlayerClose.ts +15 -0
  30. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapPlayerOpen.ts +15 -0
  31. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSceneView.ts +18 -0
  32. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearch.ts +18 -0
  33. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearchFailed.ts +8 -0
  34. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearchSuccess.ts +8 -0
  35. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoPause.ts +15 -0
  36. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoProgress.ts +18 -0
  37. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoResume.ts +15 -0
  38. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoStart.ts +15 -0
  39. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoStop.ts +15 -0
  40. package/packages/analytics/src/clients/TealiumAnalytics/types.ts +161 -0
  41. package/packages/analytics/src/clients/TwentyFourIQ/TwentyFourIQClient.ts +107 -0
  42. package/packages/analytics/src/clients/TwentyFourIQ/constants.ts +111 -0
  43. package/packages/analytics/src/clients/TwentyFourIQ/helper.ts +34 -0
  44. package/packages/analytics/src/clients/TwentyFourIQ/index.ts +2 -0
  45. package/packages/analytics/src/clients/TwentyFourIQ/interface.ts +34 -0
  46. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdEvent.ts +20 -0
  47. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBase.ts +24 -0
  48. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBuffering.ts +15 -0
  49. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerClose.ts +25 -0
  50. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerOpen.ts +17 -0
  51. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapSceneView.ts +15 -0
  52. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapScroll.ts +17 -0
  53. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoComplete.ts +22 -0
  54. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoPause.ts +25 -0
  55. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoProgress.ts +25 -0
  56. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStart.ts +34 -0
  57. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStop.ts +32 -0
  58. package/packages/analytics/src/clients/TwentyFourIQ/types.ts +132 -0
  59. package/packages/analytics/src/constants.ts +1 -0
  60. package/packages/analytics/src/index.ts +3 -0
  61. package/packages/analytics/src/interface.ts +1 -0
  62. package/packages/analytics/src/utils/generateSessionId.ts +8 -0
  63. package/packages/async-image/src/AsyncImage.tsx +15 -10
  64. package/packages/developer-tools/PlayerDebugWindow/README.md +1 -1
  65. package/packages/developer-tools/src/DeveloperConsole/DeveloperConsole.tsx +1 -0
  66. package/packages/developer-tools/src/DeveloperToolsService/DeveloperToolsList.tsx +11 -0
  67. package/packages/developer-tools/src/PlayerDebugWindow/PlayerDebugWindow.tsx +5 -5
  68. package/packages/developer-tools/src/PlayerDebugWindow/constants.ts +15 -0
  69. package/packages/developer-tools/src/TechnicalInfo/TechnicalInfo.tsx +2 -0
  70. package/packages/developer-tools/src/TechnicalInfo/TechnicalInfoDetail.tsx +2 -1
  71. package/packages/developer-tools/src/TechnicalInfo/TechnicalInfoProvider.ts +57 -5
  72. package/packages/developer-tools/src/TechnicalInfo/__mocks__/Device.ts +12 -0
  73. package/packages/developer-tools/src/TechnicalInfo/translations.ts +8 -0
  74. package/packages/device/src/driver/index.android.tv.ts +1 -0
  75. package/packages/device/src/driver/index.firetv.ts +1 -0
  76. package/packages/device/src/driver/index.smartcast.tv.ts +1 -0
  77. package/packages/device/src/getKeyDigit.ts +2 -2
  78. package/packages/device/src/resolver/resolver.ts +19 -0
  79. package/packages/digital-clock/src/DigitalClock.tsx +15 -4
  80. package/packages/driver-androidtv/src/DeviceAndroidTV.ts +262 -0
  81. package/packages/driver-androidtv/src/__mocks__/javaScriptBridge.ts +45 -0
  82. package/packages/driver-androidtv/src/formatUserAgent.ts +11 -0
  83. package/packages/driver-androidtv/src/index.ts +2 -0
  84. package/packages/driver-androidtv/src/keymap.ts +27 -0
  85. package/packages/driver-androidtv/src/types.ts +155 -0
  86. package/packages/driver-base/src/DeviceBase.ts +73 -2
  87. package/packages/driver-base/src/KeyMap/Key.ts +8 -1
  88. package/packages/driver-base/src/KeyMap/KeyMap.ts +4 -0
  89. package/packages/driver-base/src/KeyMap/interface.ts +1 -0
  90. package/packages/driver-base/src/KeyMap/overrideValues.ts +2 -1
  91. package/packages/driver-base/src/__mocks__/DeviceBase.ts +24 -0
  92. package/packages/driver-base/src/__mocks__/keyMap.ts +1 -0
  93. package/packages/driver-base/src/index.ts +3 -0
  94. package/packages/driver-base/src/types/AdInfo.ts +5 -0
  95. package/packages/driver-base/src/types/DeviceEvent.ts +2 -0
  96. package/packages/driver-base/src/types/InAppPurchase.ts +20 -0
  97. package/packages/driver-base/src/types/KeycodeKeyMap.ts +1 -0
  98. package/packages/driver-browser/src/DeviceBrowser.ts +26 -0
  99. package/packages/driver-browser/src/keymap.ts +8 -0
  100. package/packages/driver-entone/src/DeviceEntone.ts +31 -1
  101. package/packages/driver-entone/src/keymap.ts +1 -0
  102. package/packages/driver-firetv/src/DeviceFireTV.ts +86 -0
  103. package/packages/driver-firetv/src/__mocks__/javaScriptBridge.ts +45 -0
  104. package/packages/driver-firetv/src/index.ts +1 -0
  105. package/packages/driver-firetv/src/types.ts +1 -0
  106. package/packages/driver-hbbtv/src/DeviceHbbTV.ts +26 -0
  107. package/packages/driver-kreatv/src/DeviceKreaTV.ts +26 -0
  108. package/packages/driver-saphi/src/DeviceSaphi.ts +26 -0
  109. package/packages/driver-smartcast/src/DeviceSmartCast.ts +380 -0
  110. package/packages/driver-smartcast/src/__mocks__/api.ts +69 -0
  111. package/packages/driver-smartcast/src/index.ts +1 -0
  112. package/packages/driver-smartcast/src/keymap.ts +9 -0
  113. package/packages/driver-smartcast/src/types.ts +102 -0
  114. package/packages/driver-tizen/src/DeviceTizen.ts +121 -7
  115. package/packages/driver-tizen/src/ITizen.ts +15116 -202
  116. package/packages/driver-tizen/src/IWebapis.ts +8643 -87
  117. package/packages/driver-tizen/src/TizenKeys.ts +4 -2
  118. package/packages/driver-tizen/src/__mocks__/tizen.ts +7 -8
  119. package/packages/driver-tizen/src/constants.ts +1 -195
  120. package/packages/driver-vidaa/src/DeviceVidaa.ts +29 -2
  121. package/packages/driver-vidaa/src/__mocks__/vidaa.ts +1 -1
  122. package/packages/driver-vidaa/src/keymap.ts +2 -0
  123. package/packages/driver-webos/src/DeviceWebos.ts +55 -0
  124. package/packages/driver-webos/src/__mocks__/webos.ts +33 -0
  125. package/packages/driver-webos/src/constants.ts +1 -0
  126. package/packages/driver-webos/src/keymap.ts +2 -1
  127. package/packages/driver-webos/src/types.ts +30 -0
  128. package/packages/driver-xbox/src/DeviceXbox.ts +30 -1
  129. package/packages/driver-xbox/src/keymap.ts +1 -1
  130. package/packages/epg/README.md +3 -1
  131. package/packages/epg/src/v2/Cell.tsx +16 -2
  132. package/packages/epg/src/v2/DataManager.ts +112 -41
  133. package/packages/epg/src/v2/DatePicker.tsx +9 -3
  134. package/packages/epg/src/v2/DateToast/DateToast.tsx +12 -9
  135. package/packages/epg/src/v2/Day.tsx +6 -3
  136. package/packages/epg/src/v2/Epg.tsx +5 -5
  137. package/packages/epg/src/v2/MockGenerator/generator.ts +3 -2
  138. package/packages/epg/src/v2/ProgramInfo/utils.ts +4 -3
  139. package/packages/epg/src/v2/Row.tsx +3 -1
  140. package/packages/epg/src/v2/TimelineSection.tsx +4 -1
  141. package/packages/epg/src/v2/basic/CellsManager.tsx +7 -2
  142. package/packages/epg/src/v2/basic/RowsManager.tsx +3 -1
  143. package/packages/epg/src/v2/interface.ts +13 -0
  144. package/packages/events-manager/src/EventsManager.ts +1 -56
  145. package/packages/focus/README.md +33 -0
  146. package/packages/focus/src/IFocusable.ts +1 -0
  147. package/packages/focus/src/Layout/Base.tsx +41 -6
  148. package/packages/focus/src/Layout/Matrix.tsx +51 -19
  149. package/packages/focus/src/focusFirstExisting.ts +7 -1
  150. package/packages/focus/src/hasFocus.ts +36 -0
  151. package/packages/focus/src/index.ts +2 -1
  152. package/packages/gallup/src/Gallup.ts +3 -3
  153. package/packages/grid/src/Base/Base.tsx +15 -10
  154. package/packages/grid/src/FirstOnlyGrid/FirstOnlyGrid.tsx +4 -2
  155. package/packages/grid/src/UnifiedGridController/UnifiedGridController.ts +6 -6
  156. package/packages/icon/src/Icon.tsx +27 -5
  157. package/packages/input/README.md +1 -1
  158. package/packages/input/src/Input.tsx +10 -10
  159. package/packages/interactable/README.md +2 -1
  160. package/packages/interactable/src/Interactable.tsx +9 -3
  161. package/packages/interactable/src/interface.ts +1 -0
  162. package/packages/jsx/src/index.ts +1 -1
  163. package/packages/jsx/src/test-utils/index.ts +1 -0
  164. package/packages/jsx/src/test-utils/keyup.ts +27 -0
  165. package/packages/keyboard/README.md +2 -0
  166. package/packages/keyboard/src/Backdrop/Backdrop.scss +2 -0
  167. package/packages/keyboard/src/KeyboardBase.tsx +16 -4
  168. package/packages/keyboard/src/WhitelabelKeyboard/Keyboard.scss +10 -0
  169. package/packages/keyboard/src/WhitelabelKeyboard/Keyboard.tsx +128 -142
  170. package/packages/keyboard/src/WhitelabelKeyboard/WhitelabelStyles/whitelabel.scss +4 -0
  171. package/packages/keyboard/src/WhitelabelKeyboard/_sizes.1080.scss +1 -0
  172. package/packages/keyboard/src/WhitelabelKeyboard/_sizes.scss +1 -0
  173. package/packages/keyboard/src/WhitelabelKeyboard/icons/key_language.svg +20 -0
  174. package/packages/keyboard/src/WhitelabelKeyboard/index.ts +1 -1
  175. package/packages/keyboard/src/WhitelabelKeyboard/layouts/arabic.ts +27 -0
  176. package/packages/keyboard/src/WhitelabelKeyboard/layouts/burmese.ts +27 -0
  177. package/packages/keyboard/src/WhitelabelKeyboard/layouts/dari.ts +28 -0
  178. package/packages/keyboard/src/WhitelabelKeyboard/layouts/hebrew.ts +28 -0
  179. package/packages/keyboard/src/WhitelabelKeyboard/layouts/index.ts +15 -0
  180. package/packages/keyboard/src/WhitelabelKeyboard/layouts/korean.ts +26 -0
  181. package/packages/keyboard/src/WhitelabelKeyboard/layouts/latin.ts +26 -0
  182. package/packages/keyboard/src/WhitelabelKeyboard/layouts/pashto.ts +27 -0
  183. package/packages/keyboard/src/WhitelabelKeyboard/layouts/persian.ts +27 -0
  184. package/packages/keyboard/src/WhitelabelKeyboard/layouts/russian.ts +27 -0
  185. package/packages/keyboard/src/WhitelabelKeyboard/layouts/spanish.ts +26 -0
  186. package/packages/keyboard/src/WhitelabelKeyboard/layouts/special.ts +28 -0
  187. package/packages/keyboard/src/WhitelabelKeyboard/layouts/tibetan.ts +26 -0
  188. package/packages/keyboard/src/WhitelabelKeyboard/layouts/turkish.ts +26 -0
  189. package/packages/keyboard/src/WhitelabelKeyboard/layouts/ukrainian.ts +27 -0
  190. package/packages/keyboard/src/WhitelabelKeyboard/layouts/urdu.ts +26 -0
  191. package/packages/keyboard/src/WhitelabelKeyboard/types.ts +22 -2
  192. package/packages/keyboard/src/types/index.ts +1 -1
  193. package/packages/keyboard/src/utils/caret.ts +5 -8
  194. package/packages/keyboard/src/utils/input.ts +5 -6
  195. package/packages/keyboard/src/utils/setInputSelectionRange.ts +10 -0
  196. package/packages/l10n/README.md +18 -0
  197. package/packages/l10n/src/date/common.ts +18 -6
  198. package/packages/l10n/src/date/cs.ts +2 -8
  199. package/packages/l10n/src/date/de.ts +97 -0
  200. package/packages/l10n/src/date/en-001.ts +3 -3
  201. package/packages/l10n/src/date/en-common.ts +5 -4
  202. package/packages/l10n/src/date/en-us.ts +3 -3
  203. package/packages/l10n/src/date/es.ts +71 -0
  204. package/packages/l10n/src/date/fr.ts +94 -0
  205. package/packages/l10n/src/date/he.ts +101 -0
  206. package/packages/l10n/src/date/iso.ts +12 -13
  207. package/packages/l10n/src/date/types.ts +9 -0
  208. package/packages/l10n/src/l10n.ts +61 -3
  209. package/packages/list/src/Base/Base.tsx +19 -9
  210. package/packages/list/src/Base/interface.ts +2 -2
  211. package/packages/list/src/BasicList/BasicList.tsx +7 -7
  212. package/packages/list/src/CenteredList/CenteredList.tsx +2 -2
  213. package/packages/list/src/CenteredList/controller.ts +0 -1
  214. package/packages/list/src/EdgeOffsetList/EdgeOffsetList.tsx +10 -10
  215. package/packages/list/src/FirstOnlyList/FirstOnlyList.tsx +2 -2
  216. package/packages/list/src/FirstOnlyVariedList/FirstOnlyVariedList.tsx +2 -2
  217. package/packages/list/src/FixedToEndList/FixedToEndList.tsx +2 -2
  218. package/packages/list/src/UnifiedListController/UnifiedListController.ts +6 -2
  219. package/packages/list/src/interface.ts +2 -2
  220. package/packages/logger/src/loggers/ConsoleLogger/ConsoleLogger.ts +7 -1
  221. package/packages/logger/src/loggers/SentryLogger/Sentry.ts +1 -0
  222. package/packages/logger/src/loggers/SentryLogger/SentryLogger.ts +5 -3
  223. package/packages/menu/src/MenuAndContentContainer/MenuAndContentContainer.tsx +31 -3
  224. package/packages/menu/src/MenuAndContentContainer/interface.ts +8 -0
  225. package/packages/modal-service/README.md +4 -1
  226. package/packages/modal-service/src/ModalService.tsx +29 -5
  227. package/packages/perf-utils/README.md +1 -120
  228. package/packages/perf-utils/src/array/filter.ts +1 -54
  229. package/packages/perf-utils/src/array/find.ts +1 -43
  230. package/packages/perf-utils/src/array/findIndex.ts +1 -43
  231. package/packages/perf-utils/src/array/forEach.ts +1 -48
  232. package/packages/perf-utils/src/array/includes.ts +1 -41
  233. package/packages/perf-utils/src/array/includesNaN.ts +1 -32
  234. package/packages/perf-utils/src/array/index.ts +1 -7
  235. package/packages/perf-utils/src/array/map.ts +1 -52
  236. package/packages/player-ui/README.md +1 -1
  237. package/packages/player-ui/src/CurrentTime.tsx +2 -2
  238. package/packages/player-ui/src/Duration.tsx +2 -2
  239. package/packages/player-ui/src/PauseButton.tsx +8 -0
  240. package/packages/player-ui/src/PlayerInteractable.tsx +1 -0
  241. package/packages/player-ui/src/PlayerTime.tsx +3 -1
  242. package/packages/player-ui/src/PlayerUI.tsx +68 -35
  243. package/packages/player-ui/src/RemainingTime.tsx +2 -2
  244. package/packages/player-ui/src/Seekbar.tsx +110 -18
  245. package/packages/player-ui/src/Seeking.ts +57 -16
  246. package/packages/player-ui/src/Subtitles.tsx +2 -2
  247. package/packages/player-ui/src/index.ts +1 -0
  248. package/packages/player-ui/src/mocks.ts +32 -8
  249. package/packages/player-ui/src/timeUtils.ts +3 -3
  250. package/packages/player-ui/src/types.ts +9 -3
  251. package/packages/router/README.md +1 -0
  252. package/packages/router/src/Route.tsx +61 -27
  253. package/packages/router/src/Router.tsx +63 -14
  254. package/packages/router/src/history.ts +8 -1
  255. package/packages/router/src/index.ts +1 -1
  256. package/packages/router/src/utils.ts +9 -4
  257. package/packages/sass-utils/src/linear-gradient.scss +9 -4
  258. package/packages/sass-utils/src/scale.1080.scss +3 -1
  259. package/packages/sass-utils/src/scale.720.scss +1 -1
  260. package/packages/time/README.md +4 -1
  261. package/packages/time/src/Time.ts +35 -13
  262. package/packages/time/src/adapters/24iMediaTimeApi.ts +47 -0
  263. package/packages/time/src/constants.ts +1 -0
  264. package/packages/time/src/services/24iMediaTimeApi/24iMediaTimeApi.ts +43 -0
  265. package/packages/time/src/services/24iMediaTimeApi/index.ts +6 -0
  266. package/packages/toast/src/ToastService.scss +1 -0
  267. package/packages/toast/src/ToastService.tsx +16 -5
  268. package/packages/types-bigscreen-jsx/README.md +5 -4
  269. package/packages/types-bigscreen-jsx/index.d.ts +72 -67
  270. package/packages/utils/README.md +27 -0
  271. package/packages/utils/src/elementUtils.ts +25 -0
  272. package/packages/utils/src/forceReflow.ts +14 -0
  273. package/packages/utils/src/index.ts +8 -0
  274. package/packages/utils/src/keyPress/index.ts +6 -0
  275. package/packages/utils/src/keyPress/keyPressSimulator.ts +74 -0
  276. package/packages/utils/src/keyPress/simulateKeyPress.ts +25 -0
  277. package/packages/utils/src/scaledImage.ts +6 -3
  278. package/packages/utils/src/textUtils.ts +46 -14
  279. package/packages/utils/src/wait.ts +3 -1
  280. package/packages/utils/src/xhr/xhrSend.ts +3 -1
  281. package/packages/utils/src/xhr/xhrSendRetry.ts +3 -1
  282. package/packages/zapping/src/ChannelZapping.ts +9 -0
  283. package/packages/zapping/src/Zapping.tsx +10 -0
  284. package/utils/release/release.ts +156 -0
  285. package/packages/driver-tizen/src/types.ts +0 -14
  286. package/packages/focus/src/Layout/__test__/Base.spec.ts +0 -180
  287. package/packages/focus/src/Layout/__test__/Horizontal.spec.ts +0 -94
  288. package/packages/focus/src/Layout/__test__/Matrix.spec.ts +0 -261
  289. package/packages/focus/src/Layout/__test__/Vertical.spec.ts +0 -46
  290. package/packages/focus/src/Layout/__test__/isRtl.spec.ts +0 -23
  291. package/packages/focus/src/Layout/__test__/shared.ts +0 -19
  292. package/packages/keyboard/src/WhitelabelKeyboard/focusMatrix.ts +0 -19
@@ -10,6 +10,7 @@ type Props = {
10
10
  children: JSX.Element[],
11
11
  defaultPath?: string,
12
12
  detachInactiveRoutes?: boolean,
13
+ canBack?: (event: KeyboardEvent) => boolean,
13
14
  };
14
15
 
15
16
  type RoutePath = {
@@ -28,9 +29,12 @@ const filterNulls = (allChildren: (JSX.Element | null)[]) => (
28
29
  export class Router extends Component<Props> {
29
30
  paths: { [key: string]: RoutePath } = {};
30
31
 
32
+ routerDomRef = createRef<HTMLDivElement>();
33
+
31
34
  static defaultProps = {
32
35
  defaultPath: '/',
33
36
  detachInactiveRoutes: true,
37
+ canBack: () => true,
34
38
  };
35
39
 
36
40
  declare props: DeclareProps<Props, typeof Router.defaultProps>;
@@ -38,12 +42,14 @@ export class Router extends Component<Props> {
38
42
  constructor(props: Props) {
39
43
  super(props);
40
44
  routerRef.current = this;
41
- this.createRefs();
45
+ const { children } = this.props;
46
+ this.createRefs(children);
42
47
  }
43
48
 
44
49
  componentDidMount() {
45
50
  window.document.addEventListener('keydown', this.onKeyDown, false);
46
51
  window.addEventListener('hashchange', this.onHashChange, false);
52
+ this.hideAllRoutes();
47
53
  this.goToDefaultPath();
48
54
  }
49
55
 
@@ -57,7 +63,8 @@ export class Router extends Component<Props> {
57
63
  };
58
64
 
59
65
  onKeyDown = (event: KeyboardEvent) => {
60
- if (history.length > 1 && device.isBackOrEscape(event)) {
66
+ const { canBack } = this.props;
67
+ if (history.length > 1 && device.isBackOrEscape(event) && canBack(event)) {
61
68
  back();
62
69
  stopEventImmediately(event);
63
70
  }
@@ -91,6 +98,8 @@ export class Router extends Component<Props> {
91
98
  return activeRoutePath?.ref.current || null;
92
99
  }
93
100
 
101
+ // TODO: refactor to reduce complexity
102
+ // eslint-disable-next-line sonarjs/cognitive-complexity
94
103
  switchRoutes(
95
104
  routePathToHide: RoutePath | null,
96
105
  routePathToShow: RoutePath | null,
@@ -104,18 +113,31 @@ export class Router extends Component<Props> {
104
113
  } else if (routePathToShow) {
105
114
  routeToHide!.hide();
106
115
  routePathToHide.isVisible = false;
107
- if (detachInactiveRoutes) routeToHide!.replace(routeToShow!);
116
+ if (detachInactiveRoutes) {
117
+ routeToHide!.replace(routeToShow!);
118
+ } else {
119
+ routeToHide!.hideRoute();
120
+ routeToShow!.showRoute();
121
+ }
108
122
  routeToShow!.show();
109
123
  routePathToShow.isVisible = true;
110
124
  return;
111
125
  } else {
112
126
  routeToHide!.hide();
113
127
  routePathToHide.isVisible = false;
114
- if (detachInactiveRoutes) routeToHide!.detach();
128
+ if (detachInactiveRoutes) {
129
+ routeToHide!.detach();
130
+ } else {
131
+ routeToHide!.hideRoute();
132
+ }
115
133
  }
116
134
  }
117
135
  if (routePathToShow) {
118
- if (detachInactiveRoutes) routeToShow!.attach();
136
+ if (detachInactiveRoutes) {
137
+ routeToShow!.attach();
138
+ } else {
139
+ routeToShow!.showRoute();
140
+ }
119
141
  routeToShow!.show();
120
142
  routePathToShow.isVisible = true;
121
143
  }
@@ -125,11 +147,10 @@ export class Router extends Component<Props> {
125
147
  this.getActiveRoute()?.focus();
126
148
  }
127
149
 
128
- createRefs() {
129
- const { children } = this.props;
130
- forEach(children, (child: JSX.Element) => {
131
- if (child.type === Route) {
132
- const { path } = child.props;
150
+ createRefs(routes: JSX.Element[]) {
151
+ forEach(routes, (route: JSX.Element) => {
152
+ if (route.type === Route) {
153
+ const { path } = route.props;
133
154
  const { regexpPath, paramNames } = pathToRegExp(path);
134
155
  this.paths[path] = {
135
156
  ref: createRef<Route>(),
@@ -151,9 +172,28 @@ export class Router extends Component<Props> {
151
172
  }
152
173
  }
153
174
 
154
- render() {
155
- const { children, detachInactiveRoutes } = this.props;
156
- return filterNulls(map(children, (child: JSX.Element) => {
175
+ hideAllRoutes() {
176
+ const { detachInactiveRoutes } = this.props;
177
+ forEach(Object.keys(this.paths), (key: string) => {
178
+ const route = this.paths[key];
179
+ if (!route.isVisible) {
180
+ if (detachInactiveRoutes) {
181
+ route.ref.current!.detach();
182
+ } else {
183
+ route.ref.current!.hideRoute();
184
+ }
185
+ }
186
+ });
187
+ }
188
+
189
+ appendRoutes(routes: JSX.Element[]) {
190
+ this.createRefs(routes);
191
+ this.appendMount(this.renderRoutes(routes), this.routerDomRef);
192
+ this.hideAllRoutes();
193
+ }
194
+
195
+ renderRoutes(routes: JSX.Element[]) {
196
+ return filterNulls(map(routes, (child: JSX.Element) => {
157
197
  if (child.type === Route) {
158
198
  const { path, Component: RouteComponent } = child.props;
159
199
  const route = this.paths[path];
@@ -161,14 +201,23 @@ export class Router extends Component<Props> {
161
201
  <Route
162
202
  ref={route.ref}
163
203
  path={path}
204
+ domParent={this.routerDomRef}
164
205
  regexpPath={route.regexpPath}
165
206
  Component={RouteComponent}
166
207
  paramNames={route.paramNames}
167
- isDetachable={detachInactiveRoutes}
168
208
  />
169
209
  );
170
210
  }
171
211
  return null;
172
212
  }));
173
213
  }
214
+
215
+ render() {
216
+ const { children } = this.props;
217
+ return (
218
+ <div ref={this.routerDomRef} className="router">
219
+ {this.renderRoutes(children)}
220
+ </div>
221
+ );
222
+ }
174
223
  }
@@ -2,8 +2,10 @@ import { NavigationConfig } from './types';
2
2
 
3
3
  export const history: string[] = [];
4
4
 
5
+ const pathWithHash = (path:string) => `#${path}`;
6
+
5
7
  const navigate = (path: string) => {
6
- window.location.href = `#${path}`;
8
+ window.location.href = pathWithHash(path);
7
9
  };
8
10
 
9
11
  export const go = (path: string, { skipHistory, replaceHistory }: NavigationConfig = {}) => {
@@ -22,3 +24,8 @@ export const back = () => {
22
24
  export const clearHistory = () => {
23
25
  history.length = 0;
24
26
  };
27
+
28
+ export const replaceState = (path: string) => {
29
+ history[history.length - 1] = path;
30
+ window.history.replaceState(null, '', pathWithHash(path));
31
+ };
@@ -1,6 +1,6 @@
1
1
  export { Router } from './Router';
2
2
  export { Route } from './Route';
3
3
  export type { IRoute } from './types';
4
- export { history, go, back, clearHistory } from './history';
4
+ export { history, go, back, clearHistory, replaceState } from './history';
5
5
  export { focusActiveRoute } from './focusActiveRoute';
6
6
  export { fromSafeUrl, toSafeUrl } from './utils';
@@ -6,14 +6,16 @@ export const isPathVisible = (hash: string, regexpPath?: RegExp) => (
6
6
 
7
7
  export const getCurrentHash = () => window.location.href.split('#')[1] || '';
8
8
 
9
- const PARAM = '([a-zA-Z0-9-=.:%_()\\[\\]{}]+)';
9
+ // eslint-disable-next-line no-useless-escape
10
+ const PARAM_REGEX = /([^/]+)/;
11
+ export const PARAM_REGEX_STR = PARAM_REGEX.source;
10
12
 
11
13
  export const pathToRegExp = (path: string) => {
12
14
  const regexpParts: string[] = [];
13
15
  const paramNames: string[] = [];
14
16
  forEach(path.split('/'), (pathPart) => {
15
17
  if (pathPart.indexOf(':') === 0) {
16
- regexpParts.push(PARAM);
18
+ regexpParts.push(PARAM_REGEX_STR);
17
19
  paramNames.push(pathPart.replace(':', ''));
18
20
  } else regexpParts.push(pathPart);
19
21
  });
@@ -23,10 +25,13 @@ export const pathToRegExp = (path: string) => {
23
25
  };
24
26
  };
25
27
 
28
+ const toUrlSafeBase64 = (param: string) => btoa(param).replace('/', '_');
29
+ const fromUrlSafeBase64 = (base64: string) => atob(base64.replace('_', '/'));
30
+
26
31
  export const toSafeUrl = (param: string) => (
27
- btoa(unescape(encodeURIComponent(param)))
32
+ toUrlSafeBase64(unescape(encodeURIComponent(param)))
28
33
  );
29
34
 
30
35
  export const fromSafeUrl = (base64: string) => (
31
- decodeURIComponent(escape(atob(base64)))
36
+ decodeURIComponent(escape(fromUrlSafeBase64(base64)))
32
37
  );
@@ -1,3 +1,8 @@
1
+ @use 'sass:list';
2
+ @use 'sass:math';
3
+ @use 'sass:meta';
4
+ @use 'sass:map';
5
+
1
6
  @function legacy-direction($value) {
2
7
  @if is-direction($value) == false {
3
8
  @error "Cannot convert `#{$value}` to legacy syntax because it doesn't seem to be a direction.";
@@ -16,18 +21,18 @@
16
21
  to left top : right bottom,
17
22
  to top left : bottom right
18
23
  );
19
- @if map-has-key($conversion-map, $value) {
20
- @return map-get($conversion-map, $value);
24
+ @if map.has-key($conversion-map, $value) {
25
+ @return map.get($conversion-map, $value);
21
26
  }
22
27
  @return 90deg - $value;
23
28
  }
24
29
 
25
30
  @function is-direction($value) {
26
- $is-keyword: index((
31
+ $is-keyword: list.index((
27
32
  to top, to top right, to right top, to right, to bottom right, to right bottom,
28
33
  to bottom, to bottom left, to left bottom, to left, to left top, to top left,
29
34
  ), $value);
30
- $is-angle: type-of($value) == 'number' and index('deg' 'grad' 'turn' 'rad', unit($value));
35
+ $is-angle: meta.type-of($value) == 'number' and list.index('deg' 'grad' 'turn' 'rad', math.unit($value));
31
36
 
32
37
  @return $is-keyword or $is-angle;
33
38
  }
@@ -1,3 +1,5 @@
1
+ @use 'sass:math';
2
+
1
3
  @function scale($value) {
2
- @return round($number: $value);
4
+ @return math.round($number: $value);
3
5
  }
@@ -1,5 +1,5 @@
1
1
  @use 'sass:math';
2
2
 
3
3
  @function scale($value) {
4
- @return round($number: math.div($value, 1.5));
4
+ @return math.round($number: math.div($value, 1.5));
5
5
  }
@@ -52,7 +52,7 @@ await time.init({
52
52
  ```
53
53
 
54
54
  ### `getCurrentTime(): Date`
55
- It returns date object having local time set to server current time.
55
+ It returns date object having UTC time set to local time.
56
56
 
57
57
  ### `getCurrentUnixTime(): number`
58
58
  It returns UNIX time in milliseconds of server UTC time.
@@ -60,6 +60,9 @@ It returns UNIX time in milliseconds of server UTC time.
60
60
  ### `getTimezoneOffset(): number`
61
61
  It returns timezone offset in minutes, for UTC+1 (Germany) is 60.
62
62
 
63
+ ### `getTimezoneOffsetMs(): number`
64
+ It returns timezone offset in milliseconds, for UTC+1 (Germany) is 3600000.
65
+
63
66
  ### `initStatus: InitStatus`
64
67
  To check what time you are using, just check the `initStatus` property.
65
68
 
@@ -1,6 +1,6 @@
1
1
  import { createInterval } from '@24i/bigscreen-sdk/utils/timers';
2
2
  import { parseIsoDate, getDayStart, getDayEnd } from './utils';
3
- import { InitStatus, ErrorCode } from './constants';
3
+ import { InitStatus, ErrorCode, MS_PER_MINUTE } from './constants';
4
4
  import { Config, TimeServiceResp } from './types';
5
5
 
6
6
  /**
@@ -22,6 +22,9 @@ class Time {
22
22
  /** The difference in milliseconds between System Date and Server Date */
23
23
  offsetMs = 0;
24
24
 
25
+ /** The difference Date object internally adds to timestamp if not asking for UTC time. */
26
+ deviceOffset = new Date().getTimezoneOffset() * MS_PER_MINUTE;
27
+
25
28
  /** Timer for periodical time update */
26
29
  syncInterval = createInterval();
27
30
 
@@ -113,7 +116,7 @@ class Time {
113
116
  this.currentTime = currentTime;
114
117
  this.serverTime = date;
115
118
  this.serverUnixTime = unixTime;
116
- this.offsetMs = this.currentTime.getTime() - this.serverTime.getTime();
119
+ this.offsetMs = this.currentTime.getTime() - this.serverTime.getTime() + this.deviceOffset;
117
120
  this.timezoneOffset = timezoneOffset;
118
121
  }
119
122
 
@@ -168,6 +171,15 @@ class Time {
168
171
  return this.timezoneOffset;
169
172
  }
170
173
 
174
+ /**
175
+ * Returns the timezone offset in milliseconds.
176
+ *
177
+ * @returns Timezone offset in milliseconds, e.g. for UTC+1 (Germany) is 3600000.
178
+ */
179
+ getTimezoneOffsetMs() {
180
+ return this.timezoneOffset * MS_PER_MINUTE;
181
+ }
182
+
171
183
  /**
172
184
  * Returns offset (milliseconds) between System and Server Date object.
173
185
  *
@@ -192,24 +204,34 @@ class Time {
192
204
  }
193
205
 
194
206
  /**
195
- * Returns current time.
207
+ * Returns time, which is manipulated, based on the fact, that UI is displaying values in UTC.
196
208
  *
197
- * @returns Current time.
209
+ * @returns Current time values as being in UTC zone.
198
210
  */
199
211
  getCurrentTime() {
200
212
  const now = new Date().getTime();
201
213
  return new Date(now - this.offsetMs);
202
214
  }
203
215
 
216
+ /**
217
+ * Returns current time.
218
+ *
219
+ * @returns Current time.
220
+ */
221
+ getCurrentTimeReal() {
222
+ const nowShifted = this.getCurrentTime().getTime();
223
+ return new Date(nowShifted + this.deviceOffset);
224
+ }
225
+
204
226
  /**
205
227
  * Returns whether the timestamp belongs to today
206
228
  * @param timestamp to check
207
229
  * @returns true if the timestamp falls between start and end of today
208
230
  */
209
231
  isToday(timestamp: number) {
210
- const currentTime = this.getCurrentTime();
211
- const startOfToday = getDayStart(currentTime);
212
- const endOfToday = getDayEnd(currentTime);
232
+ const currentDate = this.getCurrentTimeReal();
233
+ const startOfToday = getDayStart(currentDate) - this.deviceOffset; // We must get 00:00 UTC
234
+ const endOfToday = getDayEnd(currentDate) - this.deviceOffset;
213
235
  return startOfToday <= timestamp && timestamp < endOfToday;
214
236
  }
215
237
 
@@ -219,10 +241,10 @@ class Time {
219
241
  * @returns true if the timestamp falls between start and end of tomorrow
220
242
  */
221
243
  isTomorrow(timestamp: number) {
222
- const currentTime = this.getCurrentTime();
223
- const startOfTomorrow = getDayEnd(currentTime);
244
+ const currentDate = this.getCurrentTimeReal();
245
+ const startOfTomorrow = getDayEnd(currentDate) - this.deviceOffset;
224
246
  const tommorow = new Date(startOfTomorrow + 1);
225
- const endOfTomorrow = getDayEnd(tommorow);
247
+ const endOfTomorrow = getDayEnd(tommorow) - this.deviceOffset;
226
248
  return startOfTomorrow <= timestamp && timestamp < endOfTomorrow;
227
249
  }
228
250
 
@@ -232,10 +254,10 @@ class Time {
232
254
  * @returns true if the timestamp falls between start and end of yesterday
233
255
  */
234
256
  isYesterday(timestamp: number) {
235
- const currentTime = this.getCurrentTime();
236
- const endOfYesterday = getDayStart(currentTime);
257
+ const currentDate = this.getCurrentTimeReal();
258
+ const endOfYesterday = getDayStart(currentDate) - this.deviceOffset;
237
259
  const yesterday = new Date(endOfYesterday - 1);
238
- const startOfYesterday = getDayStart(yesterday);
260
+ const startOfYesterday = getDayStart(yesterday) - this.deviceOffset;
239
261
  return startOfYesterday <= timestamp && timestamp < endOfYesterday;
240
262
  }
241
263
  }
@@ -0,0 +1,47 @@
1
+ import { HOUR_IN_MS, MINUTE_IN_MS } from '@24i/bigscreen-sdk/utils';
2
+ import * as TwentyFourIMediaTimeApi from '../services/24iMediaTimeApi';
3
+
4
+ type ParamOptions = TwentyFourIMediaTimeApi.ParamOptions;
5
+
6
+ const defaultOptions: ParamOptions = {
7
+ timeoutInMs: 30000,
8
+ retryConfig: {
9
+ retry: 2,
10
+ },
11
+ };
12
+
13
+ /**
14
+ * Returns a tring in ISO format followed by +/-hh:mm suffix for timezone offset.
15
+ * @param resp Time api response.
16
+ * @returns ISO string with timezone data.
17
+ */
18
+ const getIsoDateString = (resp: TwentyFourIMediaTimeApi.ServiceDataResponse): string => {
19
+ let datetime = new Date(resp.timestamp + resp.timezone_offset).toISOString();
20
+ const offset = resp.timezone_offset / HOUR_IN_MS;
21
+ if (offset) {
22
+ const sign = offset > 0 ? '+' : '-';
23
+ const hours = Math.abs(offset);
24
+ const minutes = Math.floor((resp.timezone_offset % HOUR_IN_MS) / MINUTE_IN_MS);
25
+ // eslint-disable-next-line no-magic-numbers, sonarjs/no-nested-template-literals
26
+ const timeString = `${sign + `0${hours}`.slice(-2)}:${`0${minutes}`.slice(-2)}`;
27
+ datetime = datetime.replace('Z', timeString);
28
+ }
29
+ return datetime;
30
+ };
31
+
32
+ /**
33
+ * Wrapper over "TwentyFourIMediaTimeApi.getTime" method requesting the current time
34
+ * from timekeeping server. Transforms the result to ISO string with timezone offset data
35
+ * included.
36
+ *
37
+ * @param options Options object
38
+ */
39
+ export const getTime = async (options: ParamOptions = {}) => {
40
+ const opts = { ...defaultOptions, ...options };
41
+ const resp = await TwentyFourIMediaTimeApi.getTime(opts);
42
+
43
+ if ('timestamp' in resp && 'timezone_offset' in resp && 'in_dst' in resp) {
44
+ return { datetime: getIsoDateString(resp) };
45
+ }
46
+ return null;
47
+ };
@@ -9,5 +9,6 @@ export const ErrorCode = {
9
9
  NO_TIME_SERVICE_PROVIDER: 'NO_TIME_SERVICE_PROVIDER',
10
10
  };
11
11
 
12
+ export const MS_PER_MINUTE = 60000;
12
13
  export const MINUTES_PER_HOUR = 60;
13
14
  export const HOURS_PER_DAY = 24;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Package "24iMediaTimeApi" provides a single function to obtain the current time
3
+ * adjusted by local timezone and daylight savings time for use in time package,
4
+ * from 24i time API at https://time.24imedia.tv/
5
+ */
6
+ import {
7
+ xhrSendRetry, type RetryConfig, type XhrResponse,
8
+ } from '@24i/bigscreen-sdk/utils/xhr';
9
+
10
+ const API_URL = 'https://time.24imedia.tv/';
11
+
12
+ export type Options = {
13
+ /** The request timeout in milliseconds. The value 0 for no timeout */
14
+ timeoutInMs: number,
15
+ /** Retry configuration */
16
+ retryConfig: RetryConfig,
17
+ };
18
+ export type ParamOptions = Partial<Options>;
19
+
20
+ export type ServiceDataResponse = {
21
+ /** Is dailight savings time */
22
+ in_dst: boolean,
23
+ /** Current time in GMT, in milliseconds */
24
+ timestamp: number,
25
+ /** Timezeone offset in milliseconds */
26
+ timezone_offset: number,
27
+ };
28
+
29
+ /**
30
+ * Request the current time based on public IP of request.
31
+ *
32
+ * @param options Options object
33
+ */
34
+ export async function getTime(options?: ParamOptions): Promise<ServiceDataResponse> {
35
+ try {
36
+ const resp = (await xhrSendRetry(API_URL, options)) as XhrResponse;
37
+ const data: any = resp.dataJson || {};
38
+ return data as ServiceDataResponse;
39
+ } catch (e) {
40
+ console.error('[24iMediaTimeApi] Failed to get time', e);
41
+ throw e;
42
+ }
43
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ Options,
3
+ ParamOptions,
4
+ ServiceDataResponse,
5
+ getTime,
6
+ } from './24iMediaTimeApi';
@@ -1,6 +1,7 @@
1
1
  .toast-service-root {
2
2
  position: absolute;
3
3
  left: 0;
4
+ right: 0;
4
5
  top: 0;
5
6
  width: 0;
6
7
  height: 0;
@@ -34,11 +34,22 @@ export class ToastService<T extends MinimalToastProps> extends Component<Props<T
34
34
  this.serviceContinue();
35
35
  },
36
36
  } as T);
37
- if (!this.isShowingToast) {
38
- this.appendMount(toastElement, this.rootDivRef);
39
- this.isShowingToast = true;
40
- } else {
41
- this.toastElementBuffer.push(toastElement);
37
+
38
+ // Check if toast element with the same message already exists in stack
39
+ const elementExists = this.toastElementBuffer.find((item) => {
40
+ const { message: newMessage } = toastElement.props;
41
+ const { message } = item.props;
42
+
43
+ return message === newMessage;
44
+ }) !== undefined;
45
+
46
+ if (!elementExists) {
47
+ if (!this.isShowingToast) {
48
+ this.appendMount(toastElement, this.rootDivRef);
49
+ this.isShowingToast = true;
50
+ } else {
51
+ this.toastElementBuffer.push(toastElement);
52
+ }
42
53
  }
43
54
  }
44
55
 
@@ -1,11 +1,12 @@
1
1
  # BIGscreen JSX Types
2
2
  BIGscreen JSX is a set of tools that allow you to write JSX and converts it to JS Dom API.
3
- This package contains types originally from @types/react, modified for smartapps-bigscreen-jsx needs.
3
+ This package contains types originally from @types/react, modified for bigscreen-jsx needs.
4
4
 
5
5
  # Contributing
6
- Navigate to `<root>/packages/types-smartapps-bigscreen-jsx/node_modules/@types/react/`.
7
- All react types are inside files `index.d.ts` and `global.d.ts`. Modify them to suit your needs and afterwards run this command in the `packages/types-smartapps-bigscreen-jsx/` directory:
6
+ Navigate to `<root>/node_modules/@types/react/`.
7
+ All react types are inside files `index.d.ts` and `global.d.ts`. Modify them to suit your needs and afterwards run this commands in the `<root>` directory:
8
8
 
9
9
  `npx patch-package @types/react`
10
+ `npm install`
10
11
 
11
- You can confirm everything worked by looking into `packages/types-smartapps-bigscreen-jsx/patches/`. You should see a file named `@types+react+<version-etc>.patch` that includes diff of your changes.
12
+ You can confirm everything worked by looking into `<root>/patches/`. You should see a file named `@types+react+<version-etc>.patch` that includes diff of your changes.