@applicaster/zapp-react-native-utils 14.0.0-rc.3 → 14.0.0-rc.31

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 (52) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +1 -1
  2. package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
  3. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  4. package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
  5. package/analyticsUtils/events.ts +8 -0
  6. package/appUtils/accessibilityManager/index.ts +5 -2
  7. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  8. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  9. package/arrayUtils/__tests__/isEmptyArray.test.ts +63 -0
  10. package/arrayUtils/__tests__/isFilledArray.test.ts +1 -1
  11. package/arrayUtils/index.ts +7 -2
  12. package/audioPlayerUtils/__tests__/getArtworkImage.test.ts +144 -0
  13. package/audioPlayerUtils/__tests__/getBackgroundImage.test.ts +72 -0
  14. package/audioPlayerUtils/__tests__/getImageFromEntry.test.ts +110 -0
  15. package/audioPlayerUtils/assets/index.ts +2 -0
  16. package/audioPlayerUtils/index.ts +242 -0
  17. package/conf/player/__tests__/selectors.test.ts +34 -0
  18. package/conf/player/selectors.ts +10 -0
  19. package/configurationUtils/__tests__/configurationUtils.test.js +0 -31
  20. package/configurationUtils/__tests__/getMediaItems.test.ts +65 -0
  21. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +34 -0
  22. package/configurationUtils/index.ts +63 -34
  23. package/focusManager/FocusManager.ts +26 -16
  24. package/focusManager/Tree.ts +25 -21
  25. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  26. package/manifestUtils/_internals/getDefaultConfiguration.js +28 -0
  27. package/manifestUtils/{_internals.js → _internals/index.js} +2 -25
  28. package/manifestUtils/createConfig.js +4 -1
  29. package/manifestUtils/defaultManifestConfigurations/player.js +1239 -200
  30. package/manifestUtils/progressBar/__tests__/mobileProgressBar.test.js +0 -30
  31. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +1 -2
  32. package/package.json +2 -2
  33. package/playerUtils/__tests__/configurationUtils.test.ts +1 -65
  34. package/playerUtils/__tests__/getPlayerActionButtons.test.ts +54 -0
  35. package/playerUtils/_internals/__tests__/utils.test.ts +71 -0
  36. package/playerUtils/_internals/index.ts +1 -0
  37. package/playerUtils/_internals/utils.ts +31 -0
  38. package/playerUtils/configurationUtils.ts +0 -44
  39. package/playerUtils/getPlayerActionButtons.ts +17 -0
  40. package/playerUtils/index.ts +2 -0
  41. package/playerUtils/useValidatePlayerConfig.tsx +22 -19
  42. package/reactHooks/feed/useBatchLoading.ts +3 -3
  43. package/reactHooks/feed/usePipesCacheReset.ts +1 -1
  44. package/reactHooks/layout/isTablet/index.ts +5 -2
  45. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  46. package/reactHooks/screen/useScreenContext.ts +1 -1
  47. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  48. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  49. package/services/js2native.ts +1 -0
  50. package/time/BackgroundTimer.ts +5 -3
  51. package/utils/index.ts +16 -1
  52. package/playerUtils/configurationGenerator.ts +0 -2572
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_IMAGE =
2
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABwgAAAP0CAYAAAC+jGj3AAAxj0lEQVR4AezdIWyd59nH4af9piKXbKAOGXJQpShGJTYacXisSUOxIo1FQZNmBWyaFCXSVBCltHLQpMpGIzYasVFJjUpiVJKgEhuN9Nv9tk7bKI59nnOOfY7/1yW9Ou2aej7PW/bTfT8f3Lp164cGAAAAAAAARPiwAQAAAAAAADEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAAAAAAAAQRCAEAAAAAACAIAIhAAAAAAAABBEIAQAAAAAAIIhACAAAAAAAAEEEQgAAAAAAAAgiEAIAAAAAAEAQgRAAAAAAAACCCIQAADQAAAAAcgiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAA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Odi7UrXWiT59+nTkVaqn72ReVrACAADMAoEQAADggmqt6DjTao8ePeoOWbW6c9bV/YA96kxrZWiv07WkAAAAXIxACAAAcAE1/TfOmtBScXB7e7v16I1vl6l3enDc8FoODg66JzQBAADSCIQAAAAX0Bv23lb35vVMEdb6zll38+bNNqoKg+OG11MVGgEAADifQAgAAHCOCno1oTapn1X37Y2qJ75dtp6I+fLlyzYpR0dH7iIEAAC4AIEQAADgHBWervrnLSwstFnXEwgnuRa04uC4q0oBAAASCIQAAADnOD4+bpPUM+U2D4Gwx6Qn/iY5kQgAAHBdCYQAAADnsLYSAACA60QgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAACc48aNG22SFhYWGtMx6XcFAABwHQmEAABAlJOTkzaqpaWlNkmLi4ttVK9fv26zrud3nPTZ9vy8nv8mAAAA5plACAAAROmJWDXxd/v27TYpq6urbVTzEAh7QlvPWZyl4mDPdOY8nC0AAMAkCYQAAECU3hg0qUBYP6dngvD4+LjNupcvX7ZR1VlM6mzX19dbj6OjowYAAJBEIAQAAKIcHh62HhWfesLe2x48eNB69P7el6k3tG1sbLRx1btZW1trPQRCAAAgjUAIAABEqTWYvWtGHz9+3MZRIaz3zr15CIS9v2NNEI4bCXvfTcVBdxACAABpBEIAACDO/v5+61Fxb3Nzs/W4c+dOu3fvXutRQXMeptzGiW11Nnfv3m096p30htdvvvmmAQAApBEIAQCAOAcHB61XrbH88ssvL7xutCYPa63oX//619arN2hehe3t7darzmmUScJ6B/UueleLlr29vQYAAJDmg1u3bv3QAAAAwjx79mxYbTmOiksVxN413VdhsO4trHg17t2Ff/zjH7vWol6F+q5fffVVG0d9162trWFl6bu+d7231dXV4WzrnHvVe7t//34DAABIIxACAACRKjJVJJyEWqtZsaliVgWrWnc5bhQ8tbu7254+fdrmySTi66nTtaV1tnWmdbbjRMFfevLkiQlCAAAgkkAIAADEmmTImpZ5mh48VRGvVn/OsjrTOlsAAIBE7iAEAABi1RrLWVbrS+ctDpaa+hvnLsLL8OjRowYAAJBKIAQAAGLVHXezGrIqDL548aLNq/rdZzVunnVvJAAAQAqBEAAAiDarIasm3OruvXlVv3vd8Tdr5j28AgAATIJACAAARKuQ9fDhw5mKhM+fP78WE241oVnfZVbUO653Pc/hFQAAYBL+75NPPvl7AwAACFbBqGLWH/7wh/bRRx+1q1T3Iv7rX/9q18W33347fC4vL7erVO/4L3/5S/vuu+8aAABAOoEQAADgf77//vv29ddft88++6wtLCy0q1Bx8Dquv6z4Wq4qEtbkYMVB9w4CAAD8SCAEAAD4SUXCg4ODtrq6eqmRsKbbPv/887azs9Ouq4qE9T0//fTTS53SPF0ranIQAADgZx/cunXrhwYAAMAbFQfv3bvX1tfX27TVVNujR49m6g7EaVpcXGzPnj0bPqdte3t7mMh05yAAAMCvCYQAAABnWFpaao8fP55KzKpoVStFr/PU4PvcvXt3CLDTONuaVqyzPV1tCgAAwK8JhAAAAOdYW1sbYlYFw3FVGKzJtgqD6ZNtFQfrbO/cuTORUCgMAgAAXIxACAAAcEEVCCtoLS8vjxQLKwTW3Ya7u7vi1RlWVlaGZ9T7H2s16/7+/nC+zhYAAOBiBEIAAIAOFbEqEtZT028ff/zxr/75q1evhnhV0SrlfsFJOT3T+rxx48av/tnx8fFwnqdn635BAACA0QmEAAAAAAAAEOTDBgAAAAAAAMQQCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAAAAAAAAggiEAAAAAAAAEEQgBAAAAAAAgCACIQAAAAAAAAQRCAEAAAAAACCIQAgAAAAAAABBBEIAAAAAAAAIIhACAAAAAABAEIEQAADg/9uzAwEAAAAAQf7Wg1waAQAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADAiCAEAAAAAACAEUEIAAAAAAAAI4IQAAAAAAAARgQhAAAAAAAAjAhCAAAAAAAAGBGEAAAAAAAAMCIIAQAAAAAAYEQQAgAAAAAAwIggBAAAAAAAgBFBCAAAAAAAACOCEAAAAAAAAEYEIQAAAAAAAIwIQgAAAAAAABgRhAAAAAAAADAiCAEAAAAAAGBEEAIAAAAAAMCIIAQAAAAAAIARQQgAAAAAAAAjghAAAAAAAABGBCEAAAAAAACMCEIAAAAAAAAYEYQAAAAAAAAwIggBAAAAAABgRBACAAAAAADASOotf98aH400AAAAAElFTkSuQmCC";
@@ -0,0 +1,242 @@
1
+ import * as React from "react";
2
+ import { get, has } from "@applicaster/zapp-react-native-utils/utils";
3
+ import { useZStore } from "@applicaster/zapp-react-native-utils/reactHooks";
4
+ import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
+
6
+ import { isNotEmptyString } from "@applicaster/zapp-react-native-utils/stringUtils";
7
+ import { getMediaItems } from "@applicaster/zapp-react-native-utils/configurationUtils";
8
+
9
+ import { DEFAULT_IMAGE } from "./assets";
10
+
11
+ export function getImageFromEntry({
12
+ entry,
13
+ imageKey,
14
+ }: {
15
+ entry: ZappEntry;
16
+ imageKey: Option<string>;
17
+ }): Option<string> {
18
+ const mediaItems = getMediaItems(entry);
19
+
20
+ if (!mediaItems) {
21
+ return undefined;
22
+ }
23
+
24
+ // Find the media item with the matching key
25
+ const found = mediaItems.find((item) => item.key === imageKey);
26
+ const src = found?.src;
27
+
28
+ // Special case for react native - uri cannot be an empty string (yellow warning).
29
+ return isNotEmptyString(src) ? src : undefined;
30
+ }
31
+
32
+ const getPropertyFromExtensions = (
33
+ key: string,
34
+ entry: ZappEntry
35
+ ): Option<string> => entry?.extensions?.[key];
36
+
37
+ const getPropertyFromConfiguration = (
38
+ key: string,
39
+ plugin_configuration: Record<string, any>
40
+ ) => plugin_configuration?.[key];
41
+
42
+ type GetBackgroundImageParams = {
43
+ entry: ZappEntry;
44
+ plugin_configuration: Record<string, any>;
45
+ };
46
+
47
+ export const getBackgroundImage = ({
48
+ entry,
49
+ plugin_configuration,
50
+ }: GetBackgroundImageParams): string => {
51
+ // 1) image_key from extensions
52
+ const imageKeyFromExtensions = getPropertyFromExtensions("image_key", entry);
53
+
54
+ const imageFromExtensions = getImageFromEntry({
55
+ entry,
56
+ imageKey: imageKeyFromExtensions,
57
+ });
58
+
59
+ if (imageFromExtensions) {
60
+ return imageFromExtensions;
61
+ }
62
+
63
+ // 2) audio_player_background_image from extensions(KAN case)
64
+ const audioPlayerBackgroundImageFromExtensions = getPropertyFromExtensions(
65
+ "audio_player_background_image",
66
+ entry
67
+ );
68
+
69
+ if (isNotEmptyString(audioPlayerBackgroundImageFromExtensions)) {
70
+ return audioPlayerBackgroundImageFromExtensions;
71
+ }
72
+
73
+ // 3) image_key from configuration
74
+ const imageKeyFromConfiguration = getPropertyFromConfiguration(
75
+ "audio_player_image_key",
76
+ plugin_configuration
77
+ );
78
+
79
+ const imageFromConfiguration = getImageFromEntry({
80
+ entry,
81
+ imageKey: imageKeyFromConfiguration,
82
+ });
83
+
84
+ if (imageFromConfiguration) {
85
+ return imageFromConfiguration;
86
+ }
87
+
88
+ // 4) audio_player_background_image from configuration
89
+ const audioPlayerBackgroundImageFromConfiguration =
90
+ getPropertyFromConfiguration(
91
+ "audio_player_background_image",
92
+ plugin_configuration
93
+ );
94
+
95
+ if (isNotEmptyString(audioPlayerBackgroundImageFromConfiguration)) {
96
+ return audioPlayerBackgroundImageFromConfiguration;
97
+ }
98
+
99
+ // default image
100
+ return DEFAULT_IMAGE;
101
+ };
102
+
103
+ type GetArtworkImageParams = {
104
+ key: string;
105
+ entry: ZappEntry;
106
+ plugin_configuration: Record<string, any>;
107
+ };
108
+
109
+ export const getArtworkImage = ({
110
+ key,
111
+ entry,
112
+ plugin_configuration,
113
+ }: GetArtworkImageParams): string => {
114
+ // 1) image_key from extensions
115
+ const imageKeyFromExtensions = getPropertyFromExtensions(key, entry);
116
+
117
+ const imageFromExtensions = getImageFromEntry({
118
+ entry,
119
+ imageKey: imageKeyFromExtensions,
120
+ });
121
+
122
+ if (imageFromExtensions) {
123
+ return imageFromExtensions;
124
+ }
125
+
126
+ // 2) image_key from configuration
127
+ const imageKeyFromConfiguration = getPropertyFromConfiguration(
128
+ key,
129
+ plugin_configuration
130
+ );
131
+
132
+ const imageFromConfiguration = getImageFromEntry({
133
+ entry,
134
+ imageKey: imageKeyFromConfiguration,
135
+ });
136
+
137
+ if (imageFromConfiguration) {
138
+ return imageFromConfiguration;
139
+ }
140
+
141
+ // default image
142
+ return DEFAULT_IMAGE;
143
+ };
144
+
145
+ const useAdjustedKeyFromScreenData = ({ config, keys }) => {
146
+ const { screenData } = useRoute();
147
+
148
+ const adjustedConfig = { ...config };
149
+
150
+ keys.forEach((key) => {
151
+ const path = ["targetScreen", "styles", key];
152
+
153
+ if (has(screenData, path)) {
154
+ const value = get(screenData, path);
155
+
156
+ adjustedConfig[key] = value;
157
+ }
158
+ });
159
+
160
+ return adjustedConfig;
161
+ };
162
+
163
+ const AUDIO_PLAYER_ARTWORK_IMAGE_KEY = "audio_player_artwork_image_key";
164
+
165
+ const audioPlayerArtworkImageKeySelector = (config) =>
166
+ config?.[AUDIO_PLAYER_ARTWORK_IMAGE_KEY];
167
+
168
+ export const useArtworkImage = (entry: ZappEntry): string => {
169
+ const configuration = useZStore("playerConfiguration");
170
+
171
+ const audio_player_artwork_image_key_value = configuration(
172
+ audioPlayerArtworkImageKeySelector
173
+ );
174
+
175
+ const pluginConfiguration = React.useMemo(
176
+ () => ({
177
+ audio_player_artwork_image_key: audio_player_artwork_image_key_value,
178
+ }),
179
+ [audio_player_artwork_image_key_value]
180
+ );
181
+
182
+ // HACK: for override [key] from screenData, because we treat empty string value as missing key and replace it to initial_value from manifest(which is wrong)
183
+ const adjustedPluginConfiguration = useAdjustedKeyFromScreenData({
184
+ keys: [AUDIO_PLAYER_ARTWORK_IMAGE_KEY],
185
+ config: pluginConfiguration,
186
+ });
187
+
188
+ return React.useMemo(
189
+ () =>
190
+ getArtworkImage({
191
+ key: AUDIO_PLAYER_ARTWORK_IMAGE_KEY,
192
+ entry,
193
+ plugin_configuration: adjustedPluginConfiguration,
194
+ }),
195
+ []
196
+ );
197
+ };
198
+
199
+ const AUDIO_PLAYER_IMAGE_KEY = "audio_player_image_key";
200
+ const AUDIO_PLAYER_BACKGROUND_IMAGE = "audio_player_background_image";
201
+
202
+ const audioPlayerImageKeySelector = (config) =>
203
+ config?.[AUDIO_PLAYER_IMAGE_KEY];
204
+
205
+ const audioPlayerBackgroundImageSelector = (config) =>
206
+ config?.[AUDIO_PLAYER_BACKGROUND_IMAGE];
207
+
208
+ export const useBackgroundImage = (entry: ZappEntry): { uri: string } => {
209
+ const configuration = useZStore("playerConfiguration");
210
+
211
+ const audio_player_image_key_value = configuration(
212
+ audioPlayerImageKeySelector
213
+ );
214
+
215
+ const audio_player_background_image_value = configuration(
216
+ audioPlayerBackgroundImageSelector
217
+ );
218
+
219
+ const pluginConfiguration = React.useMemo(
220
+ () => ({
221
+ audio_player_image_key: audio_player_image_key_value,
222
+ audio_player_background_image: audio_player_background_image_value,
223
+ }),
224
+ [audio_player_image_key_value, audio_player_background_image_value]
225
+ );
226
+
227
+ // HACK: for override [key] from screenData, because we treat empty string value as missing key and replace it to initial_value from manifest(which is wrong)
228
+ const adjustedPluginConfiguration = useAdjustedKeyFromScreenData({
229
+ keys: [AUDIO_PLAYER_IMAGE_KEY, AUDIO_PLAYER_BACKGROUND_IMAGE],
230
+ config: pluginConfiguration,
231
+ });
232
+
233
+ return React.useMemo(
234
+ () => ({
235
+ uri: getBackgroundImage({
236
+ entry,
237
+ plugin_configuration: adjustedPluginConfiguration,
238
+ }),
239
+ }),
240
+ [entry, adjustedPluginConfiguration]
241
+ );
242
+ };
@@ -0,0 +1,34 @@
1
+ import { selectActionButtons } from "@applicaster/zapp-react-native-utils/conf/player/selectors";
2
+
3
+ describe("selectActionButtons", () => {
4
+ it("returns the player_action_buttons array if present", () => {
5
+ const pluginConf = {
6
+ player_action_buttons: [
7
+ { id: "like", label: "Like" },
8
+ { id: "share", label: "Share" },
9
+ ],
10
+ };
11
+
12
+ expect(selectActionButtons(pluginConf)).toEqual(
13
+ pluginConf.player_action_buttons
14
+ );
15
+ });
16
+
17
+ it("returns null if player_action_buttons is not present", () => {
18
+ const pluginConf = { some_other_key: [] };
19
+ expect(selectActionButtons(pluginConf)).toBeNull();
20
+ });
21
+
22
+ it("returns null if pluginConf is undefined", () => {
23
+ expect(selectActionButtons(undefined)).toBeNull();
24
+ });
25
+
26
+ it("returns null if pluginConf is null", () => {
27
+ expect(selectActionButtons(null)).toBeNull();
28
+ });
29
+
30
+ it("returns null if player_action_buttons is explicitly set to null", () => {
31
+ const pluginConf = { player_action_buttons: null };
32
+ expect(selectActionButtons(pluginConf)).toBeNull();
33
+ });
34
+ });
@@ -0,0 +1,10 @@
1
+ import { get } from "@applicaster/zapp-react-native-utils/utils";
2
+
3
+ /**
4
+ * Selects the action buttons from the player configuration.
5
+ * @param {Object} pluginConf - player plugin config
6
+ * @returns {Array|null} An array of action buttons or null if not found.
7
+ */
8
+ export const selectActionButtons = (pluginConf: any) => {
9
+ return get(pluginConf, "player_action_buttons", null);
10
+ };
@@ -1,11 +1,8 @@
1
- import * as R from "ramda";
2
1
  import {
3
2
  populateConfigurationValues,
4
- imageSrcFromMediaItem,
5
3
  getBoolFromConfigValue,
6
4
  remapUpdatedKeys,
7
5
  } from "../";
8
- import { entry } from "./testEntry";
9
6
 
10
7
  describe("getBoolFromConfigValue", () => {
11
8
  it('returns true if value is "true" string', () => {
@@ -57,34 +54,6 @@ describe("getBoolFromConfigValue", () => {
57
54
  });
58
55
  });
59
56
 
60
- describe("imageSrcFromMediaItem", () => {
61
- describe("returns the src value of first media_item", () => {
62
- it("when the matching key is found and the src is not empty", () => {
63
- const result = imageSrcFromMediaItem(entry, ["logo_thumbnail"]);
64
-
65
- expect(result).toEqual(entry.media_group[1].media_item[0].src);
66
- expect(result).not.toEqual("");
67
- });
68
- });
69
-
70
- it("returns a media item with the 'image_base' key as a fallback", () => {
71
- const result = imageSrcFromMediaItem(entry, ["does_not_exist"]);
72
- const fallback = entry.media_group[0].media_item[0];
73
- expect(result).toEqual(fallback.src);
74
- expect(fallback.key).toBe("image_base");
75
- });
76
-
77
- it("returns undefined if the key was found but the source was empty", () => {
78
- const badEntry = R.set(
79
- R.lensPath(["media_group", 0, "media_item", 0, "src"]),
80
- "",
81
- entry
82
- );
83
-
84
- expect(imageSrcFromMediaItem(badEntry, ["image_base"])).toBeUndefined();
85
- });
86
- });
87
-
88
57
  describe("populateConfigurationValues", () => {
89
58
  it("transforms and returns the valid values", () => {
90
59
  const fields = [
@@ -0,0 +1,65 @@
1
+ import { getMediaItems } from "..";
2
+ import { entry as baseEntry } from "./testEntry";
3
+
4
+ describe("getMediaItems", () => {
5
+ it("returns both image and thumbnail media items", () => {
6
+ const items = getMediaItems(baseEntry);
7
+ expect(items).toHaveLength(2);
8
+ expect(items[0].key).toBe("image_base");
9
+ expect(items[1].key).toBe("logo_thumbnail");
10
+ });
11
+
12
+ it("returns only image media items if no thumbnail present", () => {
13
+ const entry = {
14
+ ...baseEntry,
15
+ media_group: [
16
+ {
17
+ type: "image",
18
+ media_item: [
19
+ { key: "image_base", src: "img.png" },
20
+ { key: "other", src: "other.png" },
21
+ ],
22
+ },
23
+ ],
24
+ };
25
+
26
+ const items = getMediaItems(entry);
27
+ expect(items).toHaveLength(2);
28
+ expect(items[0].key).toBe("image_base");
29
+ expect(items[1].key).toBe("other");
30
+ });
31
+
32
+ it("returns only thumbnail media items if no image present", () => {
33
+ const entry = {
34
+ ...baseEntry,
35
+ media_group: [
36
+ {
37
+ type: "thumbnail",
38
+ media_item: [{ key: "thumb1", src: "thumb1.png" }],
39
+ },
40
+ ],
41
+ };
42
+
43
+ const items = getMediaItems(entry);
44
+ expect(items).toHaveLength(1);
45
+ expect(items[0].key).toBe("thumb1");
46
+ });
47
+
48
+ it("returns undefined if no media_group present", () => {
49
+ const entry = { ...baseEntry };
50
+ delete entry.media_group;
51
+ expect(getMediaItems(entry)).toBeUndefined();
52
+ });
53
+
54
+ it("returns undefined if media_group is present but has no image or thumbnail", () => {
55
+ const entry = {
56
+ ...baseEntry,
57
+ media_group: [
58
+ { type: "audio", media_item: [{ key: "audio1", src: "audio1.mp3" }] },
59
+ ],
60
+ };
61
+
62
+ const items = getMediaItems(entry);
63
+ expect(items).toBeUndefined();
64
+ });
65
+ });
@@ -0,0 +1,34 @@
1
+ import * as R from "ramda";
2
+ import { imageSrcFromMediaItem } from "../";
3
+ import { entry } from "./testEntry";
4
+
5
+ describe("imageSrcFromMediaItem", () => {
6
+ it("when the matching key is found and the src is not empty", () => {
7
+ const result = imageSrcFromMediaItem(entry as ZappEntry, [
8
+ "logo_thumbnail",
9
+ ]);
10
+
11
+ expect(result).toEqual(entry.media_group[1].media_item[0].src);
12
+ expect(result).not.toEqual("");
13
+ });
14
+
15
+ it("returns a media item with the 'image_base' key as a fallback", () => {
16
+ const result = imageSrcFromMediaItem(entry as ZappEntry, [
17
+ "does_not_exist",
18
+ ]);
19
+
20
+ const fallback = entry.media_group[0].media_item[0];
21
+ expect(result).toEqual(fallback.src);
22
+ expect(fallback.key).toBe("image_base");
23
+ });
24
+
25
+ it("returns undefined if the key was found but the source was empty", () => {
26
+ const badEntry: ZappEntry = R.set(
27
+ R.lensPath(["media_group", 0, "media_item", 0, "src"]),
28
+ "",
29
+ entry
30
+ );
31
+
32
+ expect(imageSrcFromMediaItem(badEntry, ["image_base"])).toBeUndefined();
33
+ });
34
+ });
@@ -1,6 +1,12 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import * as R from "ramda";
3
3
  import { Platform } from "react-native";
4
+ import {
5
+ isFilledArray,
6
+ isEmptyArray,
7
+ } from "@applicaster/zapp-react-native-utils/arrayUtils";
8
+ import { isEmpty } from "@applicaster/zapp-react-native-utils/utils";
9
+
4
10
  import { applyTransform } from "../transform";
5
11
  import { ManifestField } from "../types";
6
12
  import { isNilOrEmpty } from "../reactUtils/helpers";
@@ -122,54 +128,77 @@ export function flattenFields(
122
128
  }
123
129
 
124
130
  /**
125
- * Retrieves the value of the "src" in the first media_item
126
- * that has the matching key provided in args.
127
- * Fallbacks: "image_base" key, or first media_item that has any "src"
128
- * @param {Object} entry Single entry from a feed
129
- * @param {Array} arg Array with a single element - the key of the media item
130
- * from which the "src" should be retrieved
131
- * @returns {?String} Value of "src", usually a URI
131
+ * Retrieves all media items from the entry's media_group that are of type "image" or "thumbnail".
132
+ *
133
+ * @param {ZappEntry} entry - The entry object containing the media_group array.
134
+ * @returns {Option<ZappMediaItem[]>} An array of media items of type "image" or "thumbnail", or undefined if no media_group is present.
135
+ */
136
+ export function getMediaItems(entry: ZappEntry): Option<ZappMediaItem[]> {
137
+ const mediaGroup = entry?.media_group || [];
138
+
139
+ if (isEmptyArray(mediaGroup)) {
140
+ return undefined;
141
+ }
142
+
143
+ const mediaItems = mediaGroup
144
+ .filter((group) => ["image", "thumbnail"].includes(group.type))
145
+ .flatMap((group) =>
146
+ Array.isArray(group.media_item) ? group.media_item : [group.media_item]
147
+ );
148
+
149
+ if (isFilledArray(mediaItems)) {
150
+ return mediaItems;
151
+ }
152
+
153
+ return undefined;
154
+ }
155
+
156
+ /**
157
+ * Retrieves the "src" value from a media item in the entry's media group,
158
+ * based on a provided key, with fallback logic.
159
+ *
160
+ * Fallback order:
161
+ * 1. Attempts to find a media item with the specified key (or "image_base" if none provided).
162
+ * 2. If not found, attempts to find a media item with the key "image_base".
163
+ * 3. If still not found, falls back to the first available media item.
164
+ *
165
+ * Special handling: If the resolved item's "src" is an empty string, returns undefined,
166
+ * since empty URIs are invalid in some platforms (e.g., React Native).
167
+ *
168
+ * @param {ZappEntry} entry - The entry object containing a media group.
169
+ * @param {string[] | unknown} arg - A single-element array containing the key to look up, or any unknown value.
170
+ * @returns {?string} The "src" URI from the matched media item, or undefined if not found or empty.
132
171
  */
133
172
  export function imageSrcFromMediaItem(
134
173
  entry: ZappEntry,
135
174
  arg: string[] | unknown
136
- ) {
175
+ ): Option<string> {
137
176
  const args: unknown = R.unless(Array.isArray, Array)(arg || []);
138
177
  const imageKey: string = args?.[0] || "image_base"; // always a single key in this function
139
- const mediaGroup = R.path<ZappMediaGroup[]>(["media_group"], entry);
140
178
 
141
- if (!mediaGroup) {
179
+ const mediaItems = getMediaItems(entry);
180
+
181
+ if (!mediaItems) {
142
182
  return undefined;
143
183
  }
144
184
 
145
- const hasTypeImageOrThumbnail = R.either(
146
- R.propEq("type", "image"),
147
- R.propEq("type", "thumbnail")
148
- );
149
-
150
- const pickMediaItemProp = R.prop<ZappMediaItem>("media_item");
185
+ // Try to find the item with the given key
186
+ let foundItem = mediaItems.find((item) => item.key === imageKey);
151
187
 
152
- const mediaItems = R.compose(
153
- R.flatten,
154
- R.map(pickMediaItemProp),
155
- R.filter(hasTypeImageOrThumbnail)
156
- )(mediaGroup);
188
+ // If not found and key was not "image_base", try to find "image_base"
189
+ if (!foundItem && imageKey !== "image_base") {
190
+ foundItem = mediaItems.find((item) => item.key === "image_base");
191
+ }
157
192
 
158
- if (!mediaItems) {
159
- return undefined;
193
+ // If still not found, default to first item
194
+ if (!foundItem) {
195
+ foundItem = mediaItems[0];
160
196
  }
161
197
 
162
- const src = R.compose(
163
- R.prop("src"),
164
- R.defaultTo(R.head(mediaItems)),
165
- R.when(R.isNil, () => R.find(R.propEq("key", "image_base"), mediaItems)),
166
- R.find(R.propEq("key", imageKey))
167
- )(mediaItems);
168
-
169
- // Special case for react native - uri cannot be an empty string (yellow warning).
170
- // R.isEmpty is tailored specifically for checks like these,
171
- // it returns false for undefined values.
172
- return R.isEmpty(src) ? undefined : src;
198
+ const src = foundItem?.src;
199
+
200
+ // React Native quirk: empty string is invalid for URIs
201
+ return isEmpty(src) ? undefined : src;
173
202
  }
174
203
 
175
204
  /**
@@ -176,18 +176,30 @@ class FocusManager {
176
176
  }
177
177
  }
178
178
 
179
- registerFocusable(
180
- component: FocusManager.TouchableReactRef,
181
- parentFocusable: FocusManager.TouchableReactRef,
182
- isFocusableCell: boolean
183
- ) {
184
- const focusableId = getFocusableId(component);
179
+ registerFocusable({
180
+ touchableRef,
181
+ parentFocusableRef,
182
+ isFocusableCell,
183
+ parentFocusableId,
184
+ }: {
185
+ touchableRef: FocusManager.TouchableReactRef;
186
+ parentFocusableRef: FocusManager.TouchableReactRef;
187
+ isFocusableCell: boolean;
188
+ parentFocusableId: string;
189
+ }) {
190
+ const focusableId = getFocusableId(touchableRef);
191
+
185
192
  const focusableComponent = FocusManager.findFocusable(focusableId);
186
193
 
187
- if (!focusableComponent && component) {
188
- this.focusableComponents.push(component);
194
+ if (!focusableComponent && touchableRef) {
195
+ this.focusableComponents.push(touchableRef);
189
196
 
190
- this.tree.add(component, parentFocusable, isFocusableCell);
197
+ this.tree.add(
198
+ touchableRef,
199
+ parentFocusableRef,
200
+ isFocusableCell,
201
+ parentFocusableId
202
+ );
191
203
  } else {
192
204
  logger.warning("Focusable component already registered", {
193
205
  id: focusableId,
@@ -243,12 +255,10 @@ class FocusManager {
243
255
  }
244
256
 
245
257
  blurPrevious(options?: FocusManager.Android.CallbackOptions) {
246
- if (options) {
247
- FocusManager.instance.prevFocused?.onBlur?.(
248
- FocusManager.instance.prevFocused,
249
- options
250
- );
251
- }
258
+ FocusManager.instance.prevFocused?.onBlur?.(
259
+ FocusManager.instance.prevFocused,
260
+ options ?? {} // Adding fallback to avoid potential regression caused by #7509
261
+ );
252
262
  }
253
263
 
254
264
  onDisableFocusChange = (id) => {
@@ -269,7 +279,7 @@ class FocusManager {
269
279
 
270
280
  if (nextFocus) {
271
281
  // HACK: hack to fix the hack below
272
- // HACK: putting call to the end of the event loop so the next component has a chane to be registered
282
+ // HACK: putting call to the end of the event loop so the next component has a chance to be registered
273
283
  setTimeout(() => {
274
284
  FocusManager.instance.setFocus(nextFocus, {
275
285
  direction: "down",