From 1a4dc97b48cf3ca4abeaef50e348ee99f8a8997f Mon Sep 17 00:00:00 2001 From: Vehovec Date: Mon, 28 Oct 2024 15:19:18 +0100 Subject: [PATCH 01/12] Update Bitmovin player version --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 55fe458f..46980e61 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -105,5 +105,5 @@ dependencies { // Bitmovin implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.33.0' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' - implementation 'com.bitmovin.player:player:3.82.0+jason' + implementation 'com.bitmovin.player:player:3.90.0+jason' } From 5fd9a4e1ed8b7fe2dfb81b014c54cf8eb296a5cf Mon Sep 17 00:00:00 2001 From: Vehovec Date: Mon, 28 Oct 2024 15:19:49 +0100 Subject: [PATCH 02/12] Add WebUiConfig variant --- src/components/PlayerView/playerViewConfig.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/components/PlayerView/playerViewConfig.ts b/src/components/PlayerView/playerViewConfig.ts index d61df77d..b82dfd47 100644 --- a/src/components/PlayerView/playerViewConfig.ts +++ b/src/components/PlayerView/playerViewConfig.ts @@ -43,4 +43,55 @@ export interface WebUiConfig extends UiConfig { * Default is `true`. */ playbackSpeedSelectionEnabled?: boolean; + /** + * The Ui variant to use for the Bitmovin Player Web UI. + */ + variant?: SmallScreenUi | TvUi | CustomUi; + /** + * Whether the WebView should be focused on initialization. + * + * By default this is enabled only for the TV UI variant, as it's needed there to + * initiate spatial navigation using the remote control. + * + * @platform Android + */ + focusUiOnInitialization?: boolean; +} + +export abstract class Variant { + /** + * Specifies the function name that will be used to initialize the `UIManager` + * for the Bitmovin Player Web UI. + * + * The function is called on the `window` object with the `Player` as the first argument and + * the `UIConfig` as the second argument. + * + * Example: + * When you added a new function or want to use a different function of our + * [`UIFactory`](https://github.com/bitmovin/bitmovin-player-ui/blob/develop/src/ts/uifactory.ts#L60), + * you can specify the full qualifier name including namespaces. + * e.g. `bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI` for the SmallScreenUi + * + * Notes: + * - It's not necessary to use our `UIFactory`. Any static function can be specified. + */ + constructor(public readonly uiManagerFactoryFunction: string) {} +} + +export class SmallScreenUi extends Variant { + constructor() { + super('bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI'); + } +} + +export class TvUi extends Variant { + constructor() { + super('bitmovin.playerui.UIFactory.buildDefaultTvUI'); + } +} + +export class CustomUi extends Variant { + constructor(uiManagerFactoryFunction: string) { + super(uiManagerFactoryFunction); + } } From f3de306996dfc095fa14b5e3fd9042441f2b9eb3 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Mon, 28 Oct 2024 15:20:14 +0100 Subject: [PATCH 03/12] Support WebUiConfig.Variant on Android --- .../reactnative/converter/JsonConverter.kt | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt index bb83e8ca..281cf64d 100644 --- a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +++ b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt @@ -755,14 +755,32 @@ fun ReadableMap.toPictureInPictureConfig(): PictureInPictureConfig = PictureInPi /** * Converts the [json] to a `RNUiConfig` object. */ -fun toPlayerViewConfig(json: ReadableMap) = PlayerViewConfig( - uiConfig = UiConfig.WebUi( - playbackSpeedSelectionEnabled = json.getMap("uiConfig") - ?.getBooleanOrNull("playbackSpeedSelectionEnabled") - ?: true, - ), - hideFirstFrame = json.getBooleanOrNull("hideFirstFrame") ?: false, -) +fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig { + val uiConfig = getMap("uiConfig") ?: return PlayerViewConfig() + val variant = uiConfig.toVariant() ?: UiConfig.WebUi.Variant.SmallScreenUi + val focusUiOnInitialization = uiConfig.getBooleanOrNull("focusUiOnInitialization") + val defaultFocusUiOnInitialization = variant == UiConfig.WebUi.Variant.TvUi + + return PlayerViewConfig( + uiConfig = UiConfig.WebUi( + playbackSpeedSelectionEnabled = uiConfig + .getBooleanOrNull("playbackSpeedSelectionEnabled") + ?: true, + variant = variant, + focusUiOnInitialization = focusUiOnInitialization ?: defaultFocusUiOnInitialization, + ), + hideFirstFrame = getBooleanOrNull("hideFirstFrame") ?: false, + ) +} + +private fun ReadableMap.toVariant(): UiConfig.WebUi.Variant? { + val uiManagerFactoryFunction = this.getMap("variant")?.getString("uiManagerFactoryFunction") ?: return null + return when (uiManagerFactoryFunction) { + "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI" -> UiConfig.WebUi.Variant.SmallScreenUi + "bitmovin.playerui.UIFactory.buildDefaultTvUI" -> UiConfig.WebUi.Variant.TvUi + else -> UiConfig.WebUi.Variant.Custom(uiManagerFactoryFunction) + } +} private fun ReadableMap.toUserInterfaceTypeFromPlayerConfig(): UserInterfaceType? = when (getMap("styleConfig")?.getString("userInterfaceType")) { @@ -775,7 +793,7 @@ private fun ReadableMap.toUserInterfaceTypeFromPlayerConfig(): UserInterfaceType * Converts the [this@toRNPlayerViewConfigWrapper] to a `RNPlayerViewConfig` object. */ fun ReadableMap.toRNPlayerViewConfigWrapper() = RNPlayerViewConfigWrapper( - playerViewConfig = toPlayerViewConfig(this), + playerViewConfig = toPlayerViewConfig(), pictureInPictureConfig = getMap("pictureInPictureConfig")?.toPictureInPictureConfig(), ) From 9a526c8949672d2cbcd2fa75def2fca450c25379 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Mon, 28 Oct 2024 15:35:41 +0100 Subject: [PATCH 04/12] Add TvUi sample --- example/src/screens/BasicPlayback.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/example/src/screens/BasicPlayback.tsx b/example/src/screens/BasicPlayback.tsx index 027bad63..8f47cedf 100644 --- a/example/src/screens/BasicPlayback.tsx +++ b/example/src/screens/BasicPlayback.tsx @@ -6,6 +6,9 @@ import { usePlayer, PlayerView, SourceType, + TvUi, + SmallScreenUi, + PlayerViewConfig, } from 'bitmovin-player-react-native'; import { useTVGestures } from '../hooks'; @@ -22,6 +25,12 @@ export default function BasicPlayback() { }, }); + const config: PlayerViewConfig = { + uiConfig: { + variant: Platform.isTV ? new TvUi() : new SmallScreenUi(), + }, + }; + useFocusEffect( useCallback(() => { player.load({ @@ -56,6 +65,7 @@ export default function BasicPlayback() { Date: Tue, 29 Oct 2024 12:07:13 +0100 Subject: [PATCH 05/12] Styling --- .../player/reactnative/converter/JsonConverter.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt index 281cf64d..cdef9c09 100644 --- a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +++ b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt @@ -757,7 +757,7 @@ fun ReadableMap.toPictureInPictureConfig(): PictureInPictureConfig = PictureInPi */ fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig { val uiConfig = getMap("uiConfig") ?: return PlayerViewConfig() - val variant = uiConfig.toVariant() ?: UiConfig.WebUi.Variant.SmallScreenUi + val variant = uiConfig.toVariant() val focusUiOnInitialization = uiConfig.getBooleanOrNull("focusUiOnInitialization") val defaultFocusUiOnInitialization = variant == UiConfig.WebUi.Variant.TvUi @@ -773,10 +773,11 @@ fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig { ) } -private fun ReadableMap.toVariant(): UiConfig.WebUi.Variant? { - val uiManagerFactoryFunction = this.getMap("variant")?.getString("uiManagerFactoryFunction") ?: return null +private fun ReadableMap.toVariant(): UiConfig.WebUi.Variant { + val uiManagerFactoryFunction = getMap("variant")?.getString("uiManagerFactoryFunction") + return when (uiManagerFactoryFunction) { - "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI" -> UiConfig.WebUi.Variant.SmallScreenUi + "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI", null -> UiConfig.WebUi.Variant.SmallScreenUi "bitmovin.playerui.UIFactory.buildDefaultTvUI" -> UiConfig.WebUi.Variant.TvUi else -> UiConfig.WebUi.Variant.Custom(uiManagerFactoryFunction) } From b86af06b476087b3ed3763a13367e6f149fec50c Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 12:08:35 +0100 Subject: [PATCH 06/12] iOS support --- ios/RCTConvert+BitmovinPlayer.swift | 7 ++++++- ios/RNPlayerViewManager.swift | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ios/RCTConvert+BitmovinPlayer.swift b/ios/RCTConvert+BitmovinPlayer.swift index e425f07b..ef80c629 100644 --- a/ios/RCTConvert+BitmovinPlayer.swift +++ b/ios/RCTConvert+BitmovinPlayer.swift @@ -1239,9 +1239,13 @@ extension RCTConvert { guard let json = json as? [String: Any?] else { return nil } + let variant = json["variant"] as? [String: Any?] + let uiManagerFactoryFunction = variant?["uiManagerFactoryFunction"] as? String + let defaultUiManagerFactoryFunction = "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI" return RNUiConfig( - playbackSpeedSelectionEnabled: json["playbackSpeedSelectionEnabled"] as? Bool ?? true + playbackSpeedSelectionEnabled: json["playbackSpeedSelectionEnabled"] as? Bool ?? true, + uiManagerFactoryFunction: uiManagerFactoryFunction ?? defaultUiManagerFactoryFunction ) } @@ -1369,6 +1373,7 @@ internal struct RNPlayerViewConfig { */ internal struct RNUiConfig { let playbackSpeedSelectionEnabled: Bool + let uiManagerFactoryFunction: String } /** diff --git a/ios/RNPlayerViewManager.swift b/ios/RNPlayerViewManager.swift index d6a381be..96390e3f 100644 --- a/ios/RNPlayerViewManager.swift +++ b/ios/RNPlayerViewManager.swift @@ -74,6 +74,7 @@ public class RNPlayerViewManager: RCTViewManager { if let uiConfig = playerViewConfig?.uiConfig { bitmovinUserInterfaceConfig .playbackSpeedSelectionEnabled = uiConfig.playbackSpeedSelectionEnabled + bitmovinUserInterfaceConfig.uiManagerFactoryFunction = uiConfig.uiManagerFactoryFunction } if let hideFirstFrame = playerViewConfig?.hideFirstFrame { bitmovinUserInterfaceConfig.hideFirstFrame = hideFirstFrame From fe529ab490c5554a4b7b79ebd999b38ec204c159 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 12:12:22 +0100 Subject: [PATCH 07/12] Styling --- .../bitmovin/player/reactnative/converter/JsonConverter.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt index cdef9c09..601f7d21 100644 --- a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +++ b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt @@ -763,9 +763,7 @@ fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig { return PlayerViewConfig( uiConfig = UiConfig.WebUi( - playbackSpeedSelectionEnabled = uiConfig - .getBooleanOrNull("playbackSpeedSelectionEnabled") - ?: true, + playbackSpeedSelectionEnabled = uiConfig.getBooleanOrNull("playbackSpeedSelectionEnabled") ?: true, variant = variant, focusUiOnInitialization = focusUiOnInitialization ?: defaultFocusUiOnInitialization, ), From 3665c307e8bc1546d08ba1efcf7826bc48020ea9 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 12:23:17 +0100 Subject: [PATCH 08/12] Documentation improvements --- src/components/PlayerView/playerViewConfig.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/PlayerView/playerViewConfig.ts b/src/components/PlayerView/playerViewConfig.ts index b82dfd47..e7b53994 100644 --- a/src/components/PlayerView/playerViewConfig.ts +++ b/src/components/PlayerView/playerViewConfig.ts @@ -45,6 +45,8 @@ export interface WebUiConfig extends UiConfig { playbackSpeedSelectionEnabled?: boolean; /** * The Ui variant to use for the Bitmovin Player Web UI. + * + * Default is {@link SmallScreenUi} */ variant?: SmallScreenUi | TvUi | CustomUi; /** @@ -67,10 +69,10 @@ export abstract class Variant { * the `UIConfig` as the second argument. * * Example: - * When you added a new function or want to use a different function of our - * [`UIFactory`](https://github.com/bitmovin/bitmovin-player-ui/blob/develop/src/ts/uifactory.ts#L60), + * When you added a new function or want to use a different function of our `UIFactory`, * you can specify the full qualifier name including namespaces. - * e.g. `bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI` for the SmallScreenUi + * e.g. `bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI` for the SmallScreenUi. + * @see UIFactory https://github.com/bitmovin/bitmovin-player-ui/blob/develop/src/ts/uifactory.ts#L60 * * Notes: * - It's not necessary to use our `UIFactory`. Any static function can be specified. From 3de5fb43046866271c0fbb7ed6b8ba5050670f43 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 12:27:34 +0100 Subject: [PATCH 09/12] Type definition improvement --- src/components/PlayerView/playerViewConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlayerView/playerViewConfig.ts b/src/components/PlayerView/playerViewConfig.ts index e7b53994..baddca09 100644 --- a/src/components/PlayerView/playerViewConfig.ts +++ b/src/components/PlayerView/playerViewConfig.ts @@ -48,7 +48,7 @@ export interface WebUiConfig extends UiConfig { * * Default is {@link SmallScreenUi} */ - variant?: SmallScreenUi | TvUi | CustomUi; + variant?: Variant; /** * Whether the WebView should be focused on initialization. * From 9f1c84d329b57b7e3e362ca43addfb84ae393e5d Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 13:00:03 +0100 Subject: [PATCH 10/12] Add changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index be39b9ee..7a9b334a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## Unreleased + +### Added + +- `WebUiConfig.variant` to set the UI variant that should be used by the Bitmovin Web UI + +### Fixed + +- Spatial navigation in the Web UI does not work properly + ## [0.29.0] - 2024-09-09 ### Added From bab7f62b0c1c1fb9e9e994135984e4bf4849b9e8 Mon Sep 17 00:00:00 2001 From: Vehovec Date: Tue, 29 Oct 2024 15:58:04 +0100 Subject: [PATCH 11/12] Split toUiConfig out of toPlayerViewConfig --- .../reactnative/converter/JsonConverter.kt | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt index 601f7d21..cd6bec77 100644 --- a/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +++ b/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt @@ -752,30 +752,28 @@ fun ReadableMap.toPictureInPictureConfig(): PictureInPictureConfig = PictureInPi isEnabled = getBooleanOrNull("isEnabled") ?: false, ) -/** - * Converts the [json] to a `RNUiConfig` object. - */ -fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig { - val uiConfig = getMap("uiConfig") ?: return PlayerViewConfig() - val variant = uiConfig.toVariant() - val focusUiOnInitialization = uiConfig.getBooleanOrNull("focusUiOnInitialization") +fun ReadableMap.toPlayerViewConfig(): PlayerViewConfig = PlayerViewConfig( + uiConfig = getMap("uiConfig")?.toUiConfig() ?: UiConfig.WebUi(), + hideFirstFrame = getBooleanOrNull("hideFirstFrame") ?: false, +) + +private fun ReadableMap.toUiConfig(): UiConfig { + val variant = toVariant() ?: UiConfig.WebUi.Variant.SmallScreenUi + val focusUiOnInitialization = getBooleanOrNull("focusUiOnInitialization") val defaultFocusUiOnInitialization = variant == UiConfig.WebUi.Variant.TvUi - return PlayerViewConfig( - uiConfig = UiConfig.WebUi( - playbackSpeedSelectionEnabled = uiConfig.getBooleanOrNull("playbackSpeedSelectionEnabled") ?: true, - variant = variant, - focusUiOnInitialization = focusUiOnInitialization ?: defaultFocusUiOnInitialization, - ), - hideFirstFrame = getBooleanOrNull("hideFirstFrame") ?: false, + return UiConfig.WebUi( + playbackSpeedSelectionEnabled = getBooleanOrNull("playbackSpeedSelectionEnabled") ?: true, + variant = variant, + focusUiOnInitialization = focusUiOnInitialization ?: defaultFocusUiOnInitialization, ) } -private fun ReadableMap.toVariant(): UiConfig.WebUi.Variant { - val uiManagerFactoryFunction = getMap("variant")?.getString("uiManagerFactoryFunction") +private fun ReadableMap.toVariant(): UiConfig.WebUi.Variant? { + val uiManagerFactoryFunction = getMap("variant")?.getString("uiManagerFactoryFunction") ?: return null return when (uiManagerFactoryFunction) { - "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI", null -> UiConfig.WebUi.Variant.SmallScreenUi + "bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI" -> UiConfig.WebUi.Variant.SmallScreenUi "bitmovin.playerui.UIFactory.buildDefaultTvUI" -> UiConfig.WebUi.Variant.TvUi else -> UiConfig.WebUi.Variant.Custom(uiManagerFactoryFunction) } From dbc6cc129d27b39ddfa3e681527d6dc817131fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Vehovec?= Date: Tue, 29 Oct 2024 15:58:50 +0100 Subject: [PATCH 12/12] Update src/components/PlayerView/playerViewConfig.ts Co-authored-by: Lukas Knoch-Girstmair --- src/components/PlayerView/playerViewConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlayerView/playerViewConfig.ts b/src/components/PlayerView/playerViewConfig.ts index baddca09..33e474df 100644 --- a/src/components/PlayerView/playerViewConfig.ts +++ b/src/components/PlayerView/playerViewConfig.ts @@ -44,7 +44,7 @@ export interface WebUiConfig extends UiConfig { */ playbackSpeedSelectionEnabled?: boolean; /** - * The Ui variant to use for the Bitmovin Player Web UI. + * The UI variant to use for the Bitmovin Player Web UI. * * Default is {@link SmallScreenUi} */