Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/new arch #427

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6ae5b1a
Add newArch enabled build property
tvanlaerhoven Sep 3, 2024
4d6f994
Add support for Fabric
tvanlaerhoven Sep 3, 2024
a292491
Add support for Fabric events
tvanlaerhoven Sep 3, 2024
e52d5b9
Initialize after view is attached
tvanlaerhoven Sep 3, 2024
bf0d549
Upgrade dependency
tvanlaerhoven Sep 3, 2024
af77592
Enable newArch by default
tvanlaerhoven Sep 3, 2024
122882a
Enabled bridgeless by default
tvanlaerhoven Sep 3, 2024
aeaab3f
Add missing implementation for daiSetSnapback for setup without ad fe…
wvanhaevre Sep 3, 2024
a164046
Update bundle setup
wvanhaevre Sep 4, 2024
8cea26c
Apply newer native app setup
wvanhaevre Sep 4, 2024
88d8f38
Update podfile
wvanhaevre Sep 4, 2024
e156deb
Update iOS project
wvanhaevre Sep 4, 2024
bf5b143
add ios pod scripts to package.json
wvanhaevre Sep 11, 2024
df1e69b
Bump slider version and prevent it from autolinking for tvOS.
wvanhaevre Sep 11, 2024
bbb12c8
TEMP: add new architecture check
wvanhaevre Sep 11, 2024
332b86d
Fix fullscreen on Android
tvanlaerhoven Sep 16, 2024
5efccbe
Update iOS e2e project
tvanlaerhoven Oct 24, 2024
e4dd633
Drop local file
tvanlaerhoven Oct 24, 2024
b042d3a
Simplify viewResolver
tvanlaerhoven Oct 24, 2024
6bf9fd0
Modify android e2e pipeline
tvanlaerhoven Oct 24, 2024
e6c3664
Update iOS workflow
tvanlaerhoven Oct 24, 2024
3ccb8f8
Update workflow
tvanlaerhoven Oct 24, 2024
0aa23c2
Drop connector test for now
tvanlaerhoven Oct 24, 2024
62b3089
Add slider dependency
tvanlaerhoven Oct 25, 2024
d596d1e
Fix project name
tvanlaerhoven Oct 25, 2024
7ecd498
Add stable connectors
tvanlaerhoven Oct 25, 2024
91786c3
Disable connector tests for new arch
tvanlaerhoven Oct 30, 2024
71f1b17
Update ios lock
tvanlaerhoven Nov 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .bundle/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1
10 changes: 9 additions & 1 deletion .github/workflows/pr_android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ name: Build Android on PRs
on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
types: [ opened, reopened, synchronize ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
api-level: [ 34 ]
newArchEnabled: [ false, true ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -69,6 +70,13 @@ jobs:
disable-animations: true
script: echo "Generated AVD snapshot for caching."

- name: Modify gradle.properties for newArchEnabled
working-directory: e2e/android
run: |
# Modify or add the newArchEnabled property in gradle.properties
echo "newArchEnabled=${{ matrix.newArchEnabled }}" >> ./gradle.properties
cat ./gradle.properties

- name: Run e2e tests
uses: reactivecircus/android-emulator-runner@v2
with:
Expand Down
19 changes: 16 additions & 3 deletions .github/workflows/pr_ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ name: Build iOS on PRs
on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
types: [ opened, reopened, synchronize ]

jobs:
build:
runs-on: macos-14
strategy:
matrix:
xcode_version: [ '15.2' ]
runs-on: macos-14
newArchEnabled: [ 0, 1 ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -25,6 +26,14 @@ jobs:
node-version: '18'
cache: 'npm'

- name: Cache Ruby Gems
uses: actions/cache@v4
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-

- name: Cache CocoaPods
uses: actions/cache@v4
with:
Expand All @@ -44,10 +53,13 @@ jobs:
cd e2e
npm ci

- name: Install Ruby dependencies
run: bundle install

- name: Run pod install & update dependencies
working-directory: e2e/ios
run: |
pod update
RCT_NEW_ARCH_ENABLED=${{ matrix.newArchEnabled }} bundle exec pod update

- name: Start iOS simulator
uses: futureware-tech/simulator-action@v3
Expand All @@ -61,4 +73,5 @@ jobs:

- name: Summarize results
working-directory: e2e
if: always()
run: cat cavy_results.md >> $GITHUB_STEP_SUMMARY
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]

# Needed for `jekyll serve`
gem "webrick", "~> 1.8"

# Cocoapods 1.15 introduced a bug which breaks the build.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
10 changes: 10 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ static def versionString(version) {
return "${version == '+' ? 'latest' : version}"
}

def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}

// Extensions
def enabledGoogleIMA = safeExtGet("THEOplayer_extensionGoogleIMA", 'false').toBoolean()
def enabledGoogleDAI = safeExtGet("THEOplayer_extensionGoogleDAI", 'false').toBoolean()
Expand Down Expand Up @@ -66,6 +74,8 @@ android {
buildConfigField "boolean", "EXTENSION_ADS", "${enabledAds}"
buildConfigField "boolean", "EXTENSION_CAST", "${enabledCast}"
buildConfigField "boolean", "EXTENSION_MEDIASESSION", "${enabledMediaSession}"

buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
}

buildTypes {
Expand Down
12 changes: 8 additions & 4 deletions android/src/main/java/com/theoplayer/PlayerEventEmitter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.common.UIManagerType
import com.theoplayer.ads.AdEventAdapter
import com.theoplayer.ads.AdEventAdapter.AdEventEmitter
import com.theoplayer.android.api.THEOplayerGlobal
Expand Down Expand Up @@ -47,7 +47,6 @@ import com.theoplayer.track.*
import com.theoplayer.util.PayloadBuilder
import kotlin.math.floor


private val TAG = PlayerEventEmitter::class.java.name

private const val EVENT_PLAYER_READY = "onNativePlayerReady"
Expand Down Expand Up @@ -613,8 +612,13 @@ class PlayerEventEmitter internal constructor(
} catch (ignore: RuntimeException) {
}
}
val uiManager = UIManagerHelper.getUIManager(reactContext, ViewUtil.getUIManagerType(viewId))
uiManager?.receiveEvent(UIManagerHelper.getSurfaceId(reactContext), viewId, type, event)
UIManagerHelper.getUIManager(
reactContext,
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
UIManagerType.FABRIC
} else {
UIManagerType.DEFAULT
})?.receiveEvent(UIManagerHelper.getSurfaceId(playerView), viewId, type, event)
}

private fun attachListeners(player: Player) {
Expand Down
19 changes: 15 additions & 4 deletions android/src/main/java/com/theoplayer/ReactTHEOplayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ReactTHEOplayerView(private val reactContext: ThemedReactContext) :
var presentationManager: PresentationManager? = null
var playerContext: ReactTHEOplayerContext? = null
private var isInitialized: Boolean = false
private var config: PlayerConfigAdapter? = null

val adsApi: AdsApiWrapper

Expand All @@ -40,36 +41,46 @@ class ReactTHEOplayerView(private val reactContext: ThemedReactContext) :
adsApi = AdsApiWrapper()
}

fun initialize(configProps: ReadableMap?) {
fun initialize(config: PlayerConfigAdapter) {
if (BuildConfig.LOG_VIEW_EVENTS) {
Log.d(TAG, "Initialize view")
}
if (isInitialized) {
Log.w(TAG, "Already initialized view")
return
}
this.config = config
if (!isAttachedToWindow) {
// The view is not attached to the window yet, postpone the initialization.
return
}
isInitialized = true
playerContext = ReactTHEOplayerContext.create(
reactContext,
PlayerConfigAdapter(configProps)
config
)
playerContext?.apply {
adsApi.initialize(player, imaIntegration, daiIntegration)
val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
playerView.layoutParams = layoutParams
(playerView.parent as? ViewGroup)?.removeView(playerView)
addView(playerView, 0, layoutParams)

presentationManager = PresentationManager(
this,
reactContext,
eventEmitter
)

eventEmitter.preparePlayer(player)
}
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (!isInitialized) {
config?.let { initialize(it) }
}
}

override fun setId(id: Int) {
super.setId(id)
eventEmitter.setViewId(id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ReactTHEOplayerViewManager : ViewGroupManager<ReactTHEOplayerView>() {

@ReactProp(name = PROP_CONFIG)
fun setConfig(videoView: ReactTHEOplayerView, config: ReadableMap?) {
videoView.initialize(config)
videoView.initialize(PlayerConfigAdapter(config))
}

override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import com.facebook.react.ReactRootView
import com.facebook.react.runtime.ReactSurfaceView
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.views.view.ReactViewGroup
import com.theoplayer.BuildConfig
Expand Down Expand Up @@ -211,7 +212,7 @@ class PresentationManager(
// Get the player's ReactViewGroup parent, which contains THEOplayerView and its children (typically the UI).
val reactPlayerGroup: ReactViewGroup? = getClosestParentOfType(this.viewCtx.playerView)

// Get ReactNative's root node or the render hiearchy
// Get ReactNative's root node or the render hierarchy
val root: ReactRootView? = getClosestParentOfType(reactPlayerGroup)

if (fullscreen) {
Expand All @@ -223,7 +224,11 @@ class PresentationManager(
if (!BuildConfig.REPARENT_ON_FULLSCREEN) {
return
}
playerGroupParentNode = (reactPlayerGroup?.parent as ReactViewGroup?)?.also { parent ->
playerGroupParentNode = if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
reactPlayerGroup?.parent as? ReactSurfaceView?
} else {
reactPlayerGroup?.parent as? ReactViewGroup?
}?.also { parent ->
playerGroupChildIndex = parent.indexOfChild(reactPlayerGroup)
// Re-parent the playerViewGroup to the root node
parent.removeView(reactPlayerGroup)
Expand Down
23 changes: 10 additions & 13 deletions android/src/main/java/com/theoplayer/util/ViewResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,28 @@ package com.theoplayer.util
import android.util.Log
import android.view.View
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.UIManagerHelper

private const val TAG = "ViewResolver"
private const val INVALID_TAG = -1

@Suppress("UNCHECKED_CAST")
class ViewResolver(private val reactContext: ReactApplicationContext) {
private var uiManager: UIManagerModule? = null

fun <T: View> resolveViewByTag(tag: Int, onResolved: (view: T?) -> Unit) {
if (tag == INVALID_TAG) {
// Don't bother trying to resolve an invalid tag.
onResolved(null)
}
if (uiManager == null) {
uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
}
uiManager?.addUIBlock {
try {
onResolved(it.resolveView(tag) as? T?)
} catch (e: Exception) {
// The View instance could not be resolved: log but do not forward exception.
Log.e(TAG, "Failed to resolve View tag $tag: $e")
onResolved(null)
try {
reactContext.runOnUiQueueThread {
UIManagerHelper.getUIManagerForReactTag(reactContext, tag)?.let {
onResolved(it.resolveView(tag) as? T?)
}
}
} catch (e: Exception) {
// The ReactTHEOplayerView instance could not be resolved: log but do not forward exception.
Log.e(TAG, "Failed to resolve ReactTHEOplayerView tag $tag: $e")
onResolved(null)
}
}
}
2 changes: 1 addition & 1 deletion e2e/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that
# are providing them.
newArchEnabled=false
#newArchEnabled=false

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
Expand Down
1 change: 1 addition & 0 deletions e2e/ios/.xcode.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export NODE_BINARY=$(command -v node)
29 changes: 19 additions & 10 deletions e2e/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip

source 'https://github.com/react-native-tvos/react-native-tvos-podspecs.git'
source 'https://github.com/NielsenDigitalSDK/nielsenappsdk-ios-specs-dynamic.git'
# source 'https://github.com/NielsenDigitalSDK/nielsenappsdk-ios-specs-dynamic.git'
source 'https://cdn.cocoapods.org/'

prepare_react_native_project!
config = use_native_modules!

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
Expand All @@ -17,14 +23,14 @@ target 'ReactNativeTHEOplayer' do

platform :ios, '13.4'

config = use_native_modules!

use_react_native!(
:path => config[:reactNativePath]
:path => config[:reactNativePath],
:app_path => "#{Pod::Config.instance.installation_root}/.."
)

pod 'react-native-theoplayer', :path => '../..'
pod 'react-native-google-cast', :git => 'https://github.com/Danesz/react-native-google-cast.git', branch: 'feature/guestmode_apple_silicon'
pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'

target 'ReactNativeTHEOplayerTests' do
inherit! :complete
Expand All @@ -37,10 +43,9 @@ target 'ReactNativeTHEOplayer-tvOS' do

platform :tvos, '13.4'

config = use_native_modules!

use_react_native!(
:path => config[:reactNativePath]
:path => config[:reactNativePath],
:app_path => "#{Pod::Config.instance.installation_root}/.."
)

pod 'react-native-theoplayer', :path => '../..'
Expand All @@ -53,5 +58,9 @@ target 'ReactNativeTHEOplayer-tvOS' do
end

post_install do |installer|
react_native_post_install(installer)
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false
)
end
Loading
Loading