From 6799b76deac04289c996ec4f3b7f089a48a72f47 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Wed, 14 Jan 2026 12:03:20 +0100 Subject: [PATCH 01/40] Add initial template --- bitmovin/.gitignore | 70 + bitmovin/CHANGELOG.md | 7 + bitmovin/README.md | 17 + bitmovin/android/build.gradle | 97 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59821 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + bitmovin/android/gradlew | 234 + bitmovin/android/gradlew.bat | 89 + bitmovin/android/src/main/AndroidManifest.xml | 4 + .../bitmovin/ReactTHEOplayerBitmovinModule.kt | 40 + .../ReactTHEOplayerBitmovinPackage.kt | 16 + bitmovin/babel.config.js | 3 + bitmovin/ios/THEOplayerBitmovinRCTBridge.m | 17 + .../ios/THEOplayerBitmovinRCTNielsenAPI.swift | 53 + .../ios/TheoplayerBitmovin-Bridging-Header.h | 4 + .../project.pbxproj | 283 ++ bitmovin/manifest.js | 6 + bitmovin/package-lock.json | 3996 +++++++++++++++++ bitmovin/package.json | 92 + .../react-native-theoplayer-bitmovin.podspec | 44 + bitmovin/src/__tests__/index.test.tsx | 1 + bitmovin/src/api/BitmovinAnalyticsConfig.ts | 73 + bitmovin/src/api/BitmovinConnector.ts | 32 + bitmovin/src/api/hooks/useBitmovin.ts | 38 + bitmovin/src/index.ts | 4 + .../src/internal/BitmovinConnectorAdapter.ts | 35 + .../internal/BitmovinConnectorAdapter.web.ts | 20 + bitmovin/src/internal/version/Version.ts | 9 + bitmovin/tsconfig.build.json | 5 + bitmovin/tsconfig.json | 11 + bitmovin/typedoc.json | 12 + 31 files changed, 5317 insertions(+) create mode 100644 bitmovin/.gitignore create mode 100644 bitmovin/CHANGELOG.md create mode 100644 bitmovin/README.md create mode 100644 bitmovin/android/build.gradle create mode 100644 bitmovin/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 bitmovin/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 bitmovin/android/gradlew create mode 100644 bitmovin/android/gradlew.bat create mode 100644 bitmovin/android/src/main/AndroidManifest.xml create mode 100644 bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt create mode 100644 bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinPackage.kt create mode 100644 bitmovin/babel.config.js create mode 100644 bitmovin/ios/THEOplayerBitmovinRCTBridge.m create mode 100644 bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift create mode 100644 bitmovin/ios/TheoplayerBitmovin-Bridging-Header.h create mode 100644 bitmovin/ios/TheoplayerBitmovin.xcodeproj/project.pbxproj create mode 100755 bitmovin/manifest.js create mode 100644 bitmovin/package-lock.json create mode 100644 bitmovin/package.json create mode 100644 bitmovin/react-native-theoplayer-bitmovin.podspec create mode 100644 bitmovin/src/__tests__/index.test.tsx create mode 100644 bitmovin/src/api/BitmovinAnalyticsConfig.ts create mode 100644 bitmovin/src/api/BitmovinConnector.ts create mode 100644 bitmovin/src/api/hooks/useBitmovin.ts create mode 100644 bitmovin/src/index.ts create mode 100644 bitmovin/src/internal/BitmovinConnectorAdapter.ts create mode 100644 bitmovin/src/internal/BitmovinConnectorAdapter.web.ts create mode 100644 bitmovin/src/internal/version/Version.ts create mode 100644 bitmovin/tsconfig.build.json create mode 100644 bitmovin/tsconfig.json create mode 100644 bitmovin/typedoc.json diff --git a/bitmovin/.gitignore b/bitmovin/.gitignore new file mode 100644 index 00000000..75356714 --- /dev/null +++ b/bitmovin/.gitignore @@ -0,0 +1,70 @@ +# OSX +# +.DS_Store + +# XDE +.expo/ + +# VSCode +.vscode/ +jsconfig.json + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# Android/IJ +# +.classpath +.cxx +.gradle +.idea +.project +.settings +local.properties +android.iml + +# Cocoapods +# +example/ios/Pods + +# Ruby +example/vendor/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +android/app/libs +android/keystores/debug.keystore + +# Expo +.expo/ + +# Turborepo +.turbo/ + +# generated by bob +lib/ diff --git a/bitmovin/CHANGELOG.md b/bitmovin/CHANGELOG.md new file mode 100644 index 00000000..7565ff35 --- /dev/null +++ b/bitmovin/CHANGELOG.md @@ -0,0 +1,7 @@ +# @theoplayer/react-native-analytics-bitmovin + +## 1.0.0 + +### ✨ Features + +- Initial release diff --git a/bitmovin/README.md b/bitmovin/README.md new file mode 100644 index 00000000..3b8ddee3 --- /dev/null +++ b/bitmovin/README.md @@ -0,0 +1,17 @@ +# THEOplayer React-Native Bitmovin Connector + +A Bitmovin analytics connector for `@theoplayer/react-native`. + +## Installation + +```sh +npm install @theoplayer/react-native-analytics-bitmovin +``` + +[//]: # (npm install @theoplayer/react-native-analytics-bitmovin) + +## Usage + +### Configuring the connector + +# TODO: Add usage instructions diff --git a/bitmovin/android/build.gradle b/bitmovin/android/build.gradle new file mode 100644 index 00000000..1dfe7915 --- /dev/null +++ b/bitmovin/android/build.gradle @@ -0,0 +1,97 @@ +buildscript { + // Buildscript is evaluated before everything else so we can't use getExtOrDefault + def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : '2.2.10' + + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "com.android.tools.build:gradle:8.12.3" + // noinspection DifferentKotlinGradleVersion + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +def isNewArchitectureEnabled() { + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} + +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + +android { + compileSdkVersion safeExtGet("THEOplayerBitmovin_compileSdkVersion", 36) + + defaultConfig { + minSdkVersion safeExtGet("THEOplayerBitmovin_minSdkVersion", 21) + targetSdkVersion safeExtGet("THEOplayerBitmovin_targetSdkVersion", 36) + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + } + } + + lintOptions { + disable "GradleCompatible" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +repositories { + mavenLocal() + google() + mavenCentral() + // Local Maven repo + maven { url("local") } + maven { url "https://maven.theoplayer.com/releases" } +} + +rootProject.allprojects { + repositories { +// maven { url 'https://bitmovin-repo' } + } +} + +// The Bitmovin connector requires at least THEOplayer SDK v10.0.0. +def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[10.0.0, 11.0.0)') +def kotlin_version = safeExtGet("THEOplayerBitmovin_kotlinVersion", "2.2.10") +def bitmovin_version = safeExtGet("THEOplayerBitmovin_bitmovinVersion", "+") + +// By default, take the connector version that aligns with the THEOplayer SDK version. +def theoplayer_bitmovin_connector_version = safeExtGet('THEOplayerBitmovin_connectorVersion', theoplayer_sdk_version) + +dependencies { + // For < 0.71, this will be from the local maven repo + // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin + //noinspection GradleDynamicVersion + implementation "com.facebook.react:react-native" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.lifecycle:lifecycle-process:2.5.1' + + // THEOplayer dependencies + compileOnly "com.theoplayer.theoplayer-sdk-android:core:$theoplayer_sdk_version" + compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:$theoplayer_sdk_version" + implementation project(':react-native-theoplayer') + + // Align the Kotlin SDK libraries with the same version. + implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version")) +} diff --git a/bitmovin/android/gradle/wrapper/gradle-wrapper.jar b/bitmovin/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..41d9927a4d4fb3f96a785543079b8df6723c946b GIT binary patch literal 59821 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 literal 0 HcmV?d00001 diff --git a/bitmovin/android/gradle/wrapper/gradle-wrapper.properties b/bitmovin/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..2733ed5d --- /dev/null +++ b/bitmovin/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/bitmovin/android/gradlew b/bitmovin/android/gradlew new file mode 100755 index 00000000..1b6c7873 --- /dev/null +++ b/bitmovin/android/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/bitmovin/android/gradlew.bat b/bitmovin/android/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/bitmovin/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/bitmovin/android/src/main/AndroidManifest.xml b/bitmovin/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..be2802c1 --- /dev/null +++ b/bitmovin/android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt new file mode 100644 index 00000000..334412ce --- /dev/null +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt @@ -0,0 +1,40 @@ +package com.theoplayer.reactnative.bitmovin + +import com.facebook.react.bridge.* +import com.theoplayer.ReactTHEOplayerView +import com.theoplayer.util.ViewResolver + +private const val TAG = "BitmovinModule" + +class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : + ReactContextBaseJavaModule(context) { + + private val viewResolver: ViewResolver = ViewResolver(context) + + //private var bitmovinConnectors: HashMap = HashMap() + + override fun getName(): String { + return TAG + } + + @ReactMethod + fun initialize(tag: Int, config: ReadableMap) { + viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? -> + view?.player?.let { player -> + // Optionally destroy any existing connector for this player. + //bitmovinConnectors[tag]?.destroy() + //bitmovinConnectors[tag] = BitmovinConnector(view.context, debug) + } + } + } + + @ReactMethod + fun updateMetadata(tag: Int, metadata: ReadableMap) { + //bitmovinConnectors[tag]?.updateMetadata(metadata.toHashMap() as HashMap) + } + + @ReactMethod + fun destroy(tag: Int) { + //bitmovinConnectors[tag]?.destroy() + } +} diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinPackage.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinPackage.kt new file mode 100644 index 00000000..eb0519e9 --- /dev/null +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinPackage.kt @@ -0,0 +1,16 @@ +package com.theoplayer.reactnative.bitmovin + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + +class ReactTHEOplayerBitmovinPackage : ReactPackage { + override fun createNativeModules(reactContext: ReactApplicationContext): List { + return listOf(ReactTHEOplayerBitmovinModule(reactContext)) + } + + override fun createViewManagers(reactContext: ReactApplicationContext): List> { + return emptyList() + } +} diff --git a/bitmovin/babel.config.js b/bitmovin/babel.config.js new file mode 100644 index 00000000..f842b77f --- /dev/null +++ b/bitmovin/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], +}; diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBridge.m b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m new file mode 100644 index 00000000..2a428845 --- /dev/null +++ b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m @@ -0,0 +1,17 @@ +#import +#import +#import + +// ---------------------------------------------------------------------------- +// Bitmovin Module +// ---------------------------------------------------------------------------- +@interface RCT_EXTERN_REMAP_MODULE(BitmovinModule, THEOplayerBitmovinRCTBitmovinAPI, NSObject) + +RCT_EXTERN_METHOD(initialize:(nonnull NSNumber *)node + bitmovinConfig:(NSDictionary)bitmovinConfig) + +RCT_EXTERN_METHOD(updateMetadata:(nonnull NSNumber *)node metadata:(nonnull NSDictionary *)metadata) + +RCT_EXTERN_METHOD(destroy:(nonnull NSNumber *)node) + +@end diff --git a/bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift new file mode 100644 index 00000000..dcb26693 --- /dev/null +++ b/bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift @@ -0,0 +1,53 @@ + +import Foundation +import UIKit +import react_native_theoplayer +import THEOplayerConnectorBitmovin +import THEOplayerSDK + +func log(_ text: String) { + #if DEBUG + print("[react-native-theoplayer-bitmovin]", text) + #endif +} + +@objc(THEOplayerBitmovinRCTBitmovinAPI) +class THEOplayerBitmovinRCTBitmovinAPI: NSObject, RCTBridgeModule { + @objc var bridge: RCTBridge! + +// var connectors = [NSNumber: BitmovinConnector]() + + static func moduleName() -> String! { + return "BitmovinModule" + } + + static func requiresMainQueueSetup() -> Bool { + return false + } + + @objc(initialize:bitmovinOptions:) + func initialize(_ node: NSNumber, bitmovinConfig: NSDictionary) -> Void { + log("initialize triggered.") + + DispatchQueue.main.async { + log("\(bitmovinConfig)") + let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView + if let player = theView?.player, + var options = bitmovinConfig as? [String:Any] { + } + } + } + + @objc(updateMetadata:metadata:) + func updateMetadata(for node: NSNumber, metadata: NSDictionary) { + log("Warning: updating metadata not possible on iOS.") + } + + @objc(destroy:) + func destroy(_ node: NSNumber) -> Void { + log("destroy triggered for \(node).") +// DispatchQueue.main.async { +// self.connectors.removeValue(forKey: node) +// } + } +} diff --git a/bitmovin/ios/TheoplayerBitmovin-Bridging-Header.h b/bitmovin/ios/TheoplayerBitmovin-Bridging-Header.h new file mode 100644 index 00000000..7ecf415d --- /dev/null +++ b/bitmovin/ios/TheoplayerBitmovin-Bridging-Header.h @@ -0,0 +1,4 @@ +#import +#import +#import +#import diff --git a/bitmovin/ios/TheoplayerBitmovin.xcodeproj/project.pbxproj b/bitmovin/ios/TheoplayerBitmovin.xcodeproj/project.pbxproj new file mode 100644 index 00000000..75e78496 --- /dev/null +++ b/bitmovin/ios/TheoplayerBitmovin.xcodeproj/project.pbxproj @@ -0,0 +1,283 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5E555C0D2413F4C50049A1A2 /* TheoplayerBitmovin.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* TheoplayerBitmovin.m */; }; + F4FF95D7245B92E800C19C63 /* TheoplayerBitmovin.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* TheoplayerBitmovin.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 58B511D91A9E6C8500147676 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 134814201AA4EA6300B7C361 /* libTheoplayerBitmovin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTheoplayerBitmovin.a; sourceTree = BUILT_PRODUCTS_DIR; }; + B3E7B5891CC2AC0600A0062D /* TheoplayerBitmovin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TheoplayerBitmovin.m; sourceTree = ""; }; + F4FF95D5245B92E700C19C63 /* TheoplayerBitmovin-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TheoplayerBitmovin-Bridging-Header.h"; sourceTree = ""; }; + F4FF95D6245B92E800C19C63 /* TheoplayerBitmovin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheoplayerBitmovin.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 58B511D81A9E6C8500147676 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 134814211AA4EA7D00B7C361 /* Products */ = { + isa = PBXGroup; + children = ( + 134814201AA4EA6300B7C361 /* libTheoplayerBitmovin.a */, + ); + name = Products; + sourceTree = ""; + }; + 58B511D21A9E6C8500147676 = { + isa = PBXGroup; + children = ( + F4FF95D6245B92E800C19C63 /* TheoplayerBitmovin.swift */, + B3E7B5891CC2AC0600A0062D /* TheoplayerBitmovin.m */, + F4FF95D5245B92E700C19C63 /* TheoplayerBitmovin-Bridging-Header.h */, + 134814211AA4EA7D00B7C361 /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 58B511DA1A9E6C8500147676 /* TheoplayerBitmovin */ = { + isa = PBXNativeTarget; + buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "TheoplayerBitmovin" */; + buildPhases = ( + 58B511D71A9E6C8500147676 /* Sources */, + 58B511D81A9E6C8500147676 /* Frameworks */, + 58B511D91A9E6C8500147676 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TheoplayerBitmovin; + productName = RCTDataManager; + productReference = 134814201AA4EA6300B7C361 /* libTheoplayerBitmovin.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 58B511D31A9E6C8500147676 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 58B511DA1A9E6C8500147676 = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "TheoplayerBitmovin" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + ); + mainGroup = 58B511D21A9E6C8500147676; + productRefGroup = 58B511D21A9E6C8500147676; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 58B511DA1A9E6C8500147676 /* TheoplayerBitmovin */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 58B511D71A9E6C8500147676 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F4FF95D7245B92E800C19C63 /* TheoplayerBitmovin.swift in Sources */, + B3E7B58A1CC2AC0600A0062D /* TheoplayerBitmovin.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 58B511ED1A9E6C8500147676 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=*]" = arm64; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 58B511EE1A9E6C8500147676 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=*]" = arm64; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 58B511F01A9E6C8500147676 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../../React/**", + "$(SRCROOT)/../../react-native/React/**", + ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = TheoplayerBitmovin; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "TheoplayerBitmovin-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 58B511F11A9E6C8500147676 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../../React/**", + "$(SRCROOT)/../../react-native/React/**", + ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = TheoplayerBitmovin; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "TheoplayerBitmovin-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "TheoplayerBitmovin" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511ED1A9E6C8500147676 /* Debug */, + 58B511EE1A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "TheoplayerBitmovin" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511F01A9E6C8500147676 /* Debug */, + 58B511F11A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 58B511D31A9E6C8500147676 /* Project object */; +} diff --git a/bitmovin/manifest.js b/bitmovin/manifest.js new file mode 100755 index 00000000..e7629f28 --- /dev/null +++ b/bitmovin/manifest.js @@ -0,0 +1,6 @@ +const manifest = { + version: process.env.npm_package_version, + buildDate: new Date().toISOString(), +}; + +console.log(JSON.stringify(manifest)); diff --git a/bitmovin/package-lock.json b/bitmovin/package-lock.json new file mode 100644 index 00000000..c4e482a3 --- /dev/null +++ b/bitmovin/package-lock.json @@ -0,0 +1,3996 @@ +{ + "name": "@theoplayer/react-native-analytics-bitmovin", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@theoplayer/react-native-analytics-bitmovin", + "version": "1.0.0", + "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "dependencies": { + "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-theoplayer": "^7 || ^8 || ^9 || ^10", + "theoplayer": "^7 || ^8 || ^9 || ^10" + }, + "peerDependenciesMeta": { + "theoplayer": { + "optional": true + } + } + }, + "node_modules/@babel/code-frame": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse--for-generate-function-map": { + "name": "@babel/traverse", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT", + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@qualabs/bitmovin-analytics-collector-theoplayer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@qualabs/bitmovin-analytics-collector-theoplayer/-/bitmovin-analytics-collector-theoplayer-1.0.4.tgz", + "integrity": "sha512-Vn+/0Bj+G3zBvT9p/kKAP1+YB/NnzLBsOXGii5x/LwBbcWyAM8n+nE/kP/YeIZxMqwueGCiemDHSFIcjNUjSTw==", + "peerDependencies": { + "theoplayer": "^8.10.0" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.83.1.tgz", + "integrity": "sha512-AT7/T6UwQqO39bt/4UL5EXvidmrddXrt0yJa7ENXndAv+8yBzMsZn6fyiax6+ERMt9GLzAECikv3lj22cn2wJA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.83.1.tgz", + "integrity": "sha512-FpRxenonwH+c2a5X5DZMKUD7sCudHxB3eSQPgV9R+uxd28QWslyAWrpnJM/Az96AEksHnymDzEmzq2HLX5nb+g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.32.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.83.1.tgz", + "integrity": "sha512-FqR1ftydr08PYlRbrDF06eRiiiGOK/hNmz5husv19sK6iN5nHj1SMaCIVjkH/a5vryxEddyFhU6PzO/uf4kOHg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-native/dev-middleware": "0.83.1", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "metro": "^0.83.3", + "metro-config": "^0.83.3", + "metro-core": "^0.83.3", + "semver": "^7.1.3" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@react-native-community/cli": "*", + "@react-native/metro-config": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli": { + "optional": true + }, + "@react-native/metro-config": { + "optional": true + } + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.83.1.tgz", + "integrity": "sha512-01Rn3goubFvPjHXONooLmsW0FLxJDKIUJNOlOS0cPtmmTIx9YIjxhe/DxwHXGk7OnULd7yl3aYy7WlBsEd5Xmg==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/debugger-shell": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.83.1.tgz", + "integrity": "sha512-d+0w446Hxth5OP/cBHSSxOEpbj13p2zToUy6e5e3tTERNJ8ueGlW7iGwGTrSymNDgXXFjErX+dY4P4/3WokPIQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "fb-dotslash": "0.5.8" + }, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.83.1.tgz", + "integrity": "sha512-QJaSfNRzj3Lp7MmlCRgSBlt1XZ38xaBNXypXAp/3H3OdFifnTZOeYOpFmcpjcXYnDqkxetuwZg8VL65SQhB8dg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.83.1", + "@react-native/debugger-shell": "0.83.1", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "serve-static": "^1.16.2", + "ws": "^7.5.10" + }, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.83.1.tgz", + "integrity": "sha512-6ESDnwevp1CdvvxHNgXluil5OkqbjkJAkVy7SlpFsMGmVhrSxNAgD09SSRxMNdKsnLtzIvMsFCzyHLsU/S4PtQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.83.1.tgz", + "integrity": "sha512-qgPpdWn/c5laA+3WoJ6Fak8uOm7CG50nBsLlPsF8kbT7rUHIVB9WaP6+GPsoKV/H15koW7jKuLRoNVT7c3Ht3w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.83.1.tgz", + "integrity": "sha512-84feABbmeWo1kg81726UOlMKAhcQyFXYz2SjRKYkS78QmfhVDhJ2o/ps1VjhFfBz0i/scDwT1XNv9GwmRIghkg==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.83.1.tgz", + "integrity": "sha512-MdmoAbQUTOdicCocm5XAFDJWsswxk7hxa6ALnm6Y88p01HFML0W593hAn6qOt9q6IM1KbAcebtH6oOd4gcQy8w==", + "license": "MIT", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@types/react": "^19.2.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT", + "peer": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@theoplayer/cmcd-connector-web": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@theoplayer/cmcd-connector-web/-/cmcd-connector-web-1.4.0.tgz", + "integrity": "sha512-fOl94/HKnJLiBwhy4KPLOtxcNksUHfCyXQTvTM0kVBdd+Y6DwgreGpk6RXeHpxzkVXgH0Sx1DjNutwfIqLk/yA==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "theoplayer": "^5 || ^6 || ^7 || ^8 || ^9 || ^10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.8.tgz", + "integrity": "sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT", + "peer": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT", + "peer": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT", + "peer": true + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.32.0.tgz", + "integrity": "sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg==", + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-parser": "0.32.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "license": "MIT", + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "peer": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "peer": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT", + "peer": true + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001764", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", + "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0", + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", + "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "peer": true + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "peer": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT", + "peer": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT", + "peer": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "license": "ISC", + "peer": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "peer": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT", + "peer": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT", + "peer": true + }, + "node_modules/fb-dotslash": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", + "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", + "license": "(MIT OR Apache-2.0)", + "peer": true, + "bin": { + "dotslash": "bin/dotslash" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "peer": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT", + "peer": true + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "peer": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "peer": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "peer": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-compiler": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-0.14.0.tgz", + "integrity": "sha512-clxa193o+GYYwykWVFfpHduCATz8fR5jvU7ngXpfKHj+E9hr9vjLNtdLSEe8MUbObvVexV3wcyxQ00xTPIrB1Q==", + "license": "MIT", + "peer": true + }, + "node_modules/hermes-estree": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", + "license": "MIT", + "peer": true + }, + "node_modules/hermes-parser": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-estree": "0.32.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/image-size": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", + "peer": true, + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "peer": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC", + "peer": true + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "peer": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "peer": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "peer": true + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD", + "peer": true + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", + "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT", + "peer": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT", + "peer": true + }, + "node_modules/metro": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.3.tgz", + "integrity": "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "@babel/types": "^7.25.2", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.32.0", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-config": "0.83.3", + "metro-core": "0.83.3", + "metro-file-map": "0.83.3", + "metro-resolver": "0.83.3", + "metro-runtime": "0.83.3", + "metro-source-map": "0.83.3", + "metro-symbolicate": "0.83.3", + "metro-transform-plugins": "0.83.3", + "metro-transform-worker": "0.83.3", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz", + "integrity": "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.32.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-cache": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz", + "integrity": "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "https-proxy-agent": "^7.0.5", + "metro-core": "0.83.3" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-cache-key": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.3.tgz", + "integrity": "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-config": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.3.tgz", + "integrity": "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==", + "license": "MIT", + "peer": true, + "dependencies": { + "connect": "^3.6.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.7.0", + "metro": "0.83.3", + "metro-cache": "0.83.3", + "metro-core": "0.83.3", + "metro-runtime": "0.83.3", + "yaml": "^2.6.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-core": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.3.tgz", + "integrity": "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.83.3" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-file-map": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.3.tgz", + "integrity": "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz", + "integrity": "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-resolver": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.3.tgz", + "integrity": "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-runtime": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.3.tgz", + "integrity": "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-source-map": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.3.tgz", + "integrity": "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.83.3", + "nullthrows": "^1.1.1", + "ob1": "0.83.3", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz", + "integrity": "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.83.3", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz", + "integrity": "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz", + "integrity": "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "metro": "0.83.3", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-minify-terser": "0.83.3", + "metro-source-map": "0.83.3", + "metro-transform-plugins": "0.83.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT", + "peer": true + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "peer": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT", + "peer": true + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "license": "MIT", + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT", + "peer": true + }, + "node_modules/ob1": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.3.tgz", + "integrity": "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==", + "license": "MIT", + "peer": true, + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC", + "peer": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz", + "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==", + "license": "MIT", + "peer": true, + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT", + "peer": true + }, + "node_modules/react-native": { + "version": "0.83.1", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.83.1.tgz", + "integrity": "sha512-mL1q5HPq5cWseVhWRLl+Fwvi5z1UO+3vGOpjr+sHFwcUletPRZ5Kv+d0tUfqHmvi73/53NjlQqX1Pyn4GguUfA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/create-cache-key-function": "^29.7.0", + "@react-native/assets-registry": "0.83.1", + "@react-native/codegen": "0.83.1", + "@react-native/community-cli-plugin": "0.83.1", + "@react-native/gradle-plugin": "0.83.1", + "@react-native/js-polyfills": "0.83.1", + "@react-native/normalize-colors": "0.83.1", + "@react-native/virtualized-lists": "0.83.1", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-syntax-hermes-parser": "0.32.0", + "base64-js": "^1.5.1", + "commander": "^12.0.0", + "flow-enums-runtime": "^0.0.6", + "glob": "^7.1.1", + "hermes-compiler": "0.14.0", + "invariant": "^2.2.4", + "jest-environment-node": "^29.7.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.83.3", + "metro-source-map": "^0.83.3", + "nullthrows": "^1.1.1", + "pretty-format": "^29.7.0", + "promise": "^8.3.0", + "react-devtools-core": "^6.1.5", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.27.0", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@types/react": "^19.1.1", + "react": "^19.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-theoplayer": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/react-native-theoplayer/-/react-native-theoplayer-10.7.1.tgz", + "integrity": "sha512-3xfcrsGtrnyN4LQE/uszViIpp+gcEGjVr5PtafgISGZwuzpMfpHW3RucAuxSoKkCaqTtieXArG6E3E1ijS3hEw==", + "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "peer": true, + "dependencies": { + "@theoplayer/cmcd-connector-web": "^1.4.0", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": "*", + "react-native": "*", + "theoplayer": "^9.12.0 || ^10" + }, + "peerDependenciesMeta": { + "theoplayer": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "peer": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT", + "peer": true + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/send/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC", + "peer": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "peer": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT", + "peer": true + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "license": "MIT", + "peer": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT", + "peer": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/theoplayer": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/theoplayer/-/theoplayer-10.7.0.tgz", + "integrity": "sha512-EYltR/TIgJm6OnRgZSly7QWSoJIDP3970eFXrlx/30upIsH03lOLbyt5zFA2if6Z3Kupq1hNwb7UaMPE/s3V7w==", + "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "peer": true + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT", + "peer": true + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT", + "peer": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT", + "peer": true + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT", + "peer": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC", + "peer": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC", + "peer": true + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/bitmovin/package.json b/bitmovin/package.json new file mode 100644 index 00000000..637e2e88 --- /dev/null +++ b/bitmovin/package.json @@ -0,0 +1,92 @@ +{ + "name": "@theoplayer/react-native-analytics-bitmovin", + "version": "1.0.0", + "description": "Bitmovin analytics connector for @theoplayer/react-native", + "main": "lib/commonjs/index", + "module": "lib/module/index", + "types": "lib/typescript/src/index.d.ts", + "react-native": "src/index", + "source": "src/index", + "files": [ + "src", + "lib", + "android", + "ios", + "cpp", + "*.podspec", + "*.tgz", + "CHANGELOG.md", + "!lib/typescript/example", + "!ios/build", + "!android/build", + "!android/gradle", + "!android/gradlew", + "!android/gradlew.bat", + "!android/local.properties", + "!**/__tests__", + "!**/__fixtures__", + "!**/__mocks__", + "!**/.*" + ], + "scripts": { + "typescript": "tsc --noEmit", + "build": "bob build", + "manifest": "node manifest.js > src/manifest.json", + "prepare": "npm run manifest && npm run build", + "clean": "rimraf lib android/build example/android/build example/android/app/build example/ios/build" + }, + "keywords": [ + "react-native", + "THEOplayer", + "ios", + "android", + "bitmovin" + ], + "repository": { + "type": "git", + "url": "git@github.com:THEOplayer/react-native-connectors.git" + }, + "author": "THEO Technologies", + "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "homepage": "https://github.com/THEOplayer/react-native-connectors/tree/main/bitmovin#readme", + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "dependencies": { + "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-theoplayer": "^7 || ^8 || ^9 || ^10", + "theoplayer": "^7 || ^8 || ^9 || ^10" + }, + "peerDependenciesMeta": { + "theoplayer": { + "optional": true + } + }, + "overrides": { + "@qualabs/bitmovin-analytics-collector-theoplayer": { + "theoplayer": "^10" + } + }, + "eslintIgnore": [ + "node_modules/", + "lib/" + ], + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + "commonjs", + "module", + [ + "typescript", + { + "project": "tsconfig.build.json" + } + ] + ] + } +} diff --git a/bitmovin/react-native-theoplayer-bitmovin.podspec b/bitmovin/react-native-theoplayer-bitmovin.podspec new file mode 100644 index 00000000..b64e0a49 --- /dev/null +++ b/bitmovin/react-native-theoplayer-bitmovin.podspec @@ -0,0 +1,44 @@ +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + +Pod::Spec.new do |s| + s.name = "react-native-theoplayer-bitmovin" + s.version = package["version"] + s.summary = package["description"] + s.homepage = package["homepage"] + s.license = package["license"] + s.authors = package["author"] + + s.platforms = { :ios => "13.4", :tvos => "13.4" } + s.source = { :git => "https://github.com/THEOplayer/react-native-connectors.git", :tag => "bitmovin_v#{s.version}" } + + s.source_files = "ios/**/*.{h,m,mm,swift}" + + s.dependency "react-native-theoplayer" + s.dependency "THEOplayer-Connector-Bitmovin", "~> 10.0" + + # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. + # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. + if respond_to?(:install_modules_dependencies, true) + install_modules_dependencies(s) + else + s.dependency "React-Core" + + # Don't install the dependencies when we run `pod install` in the old architecture. + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + s.dependency "React-Codegen" + s.dependency "RCT-Folly" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end + end +end diff --git a/bitmovin/src/__tests__/index.test.tsx b/bitmovin/src/__tests__/index.test.tsx new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/bitmovin/src/__tests__/index.test.tsx @@ -0,0 +1 @@ +export {}; diff --git a/bitmovin/src/api/BitmovinAnalyticsConfig.ts b/bitmovin/src/api/BitmovinAnalyticsConfig.ts new file mode 100644 index 00000000..482e7eb1 --- /dev/null +++ b/bitmovin/src/api/BitmovinAnalyticsConfig.ts @@ -0,0 +1,73 @@ +export interface BitmovinAnalyticsConfig extends BitmovinCustomData { + licenseKey: string; + adTrackingDisabled?: boolean; + randomizeUserId?: boolean; + backendUrl?: string; + cdnProvider?: string; + customUserId?: string; + sourceMetadata?: BitmovinSourceMetadata; + cookiesEnabled?: boolean; + cookiesDomain?: string; + cookiesMaxAge?: number; +} + +export interface BitmovinSourceMetadata { + title?: string; + videoId?: string; + cdnProvider?: string; + path?: string; + isLive?: boolean; +} + +export interface BitmovinCustomData { + customData1?: string; + customData2?: string; + customData3?: string; + customData4?: string; + customData5?: string; + customData6?: string; + customData7?: string; + customData8?: string; + customData9?: string; + customData10?: string; + customData11?: string; + customData12?: string; + customData13?: string; + customData14?: string; + customData15?: string; + customData16?: string; + customData17?: string; + customData18?: string; + customData19?: string; + customData20?: string; + customData21?: string; + customData22?: string; + customData23?: string; + customData24?: string; + customData25?: string; + customData26?: string; + customData27?: string; + customData28?: string; + customData29?: string; + customData30?: string; + customData31?: string; + customData32?: string; + customData33?: string; + customData34?: string; + customData35?: string; + customData36?: string; + customData37?: string; + customData38?: string; + customData39?: string; + customData40?: string; + customData41?: string; + customData42?: string; + customData43?: string; + customData44?: string; + customData45?: string; + customData46?: string; + customData47?: string; + customData48?: string; + customData49?: string; + customData50?: string; +} diff --git a/bitmovin/src/api/BitmovinConnector.ts b/bitmovin/src/api/BitmovinConnector.ts new file mode 100644 index 00000000..2c6e7ec2 --- /dev/null +++ b/bitmovin/src/api/BitmovinConnector.ts @@ -0,0 +1,32 @@ +import type { THEOplayer } from 'react-native-theoplayer'; +import { BitmovinConnectorAdapter } from '../internal/BitmovinConnectorAdapter'; +import { BitmovinAnalyticsConfig } from './BitmovinAnalyticsConfig'; + +export class BitmovinConnector { + private connectorAdapter: BitmovinConnectorAdapter; + + /** + * Create BitmovinConnector + * + * @param player THEOplayer instance. + * @param config Configuration for Bitmovin Analytics. + */ + constructor(player: THEOplayer, config: BitmovinAnalyticsConfig) { + this.connectorAdapter = new BitmovinConnectorAdapter(player, config); + } + + /** + * Adds metadata which will be sent on Bitmovin requests. + * @param metadata contains the key value pairs with data. + */ + updateMetadata(metadata: { [key: string]: string }): void { + this.connectorAdapter.updateMetadata(metadata); + } + + /** + * Stops video and ad analytics and closes all sessions. + */ + destroy(): void { + this.connectorAdapter.destroy(); + } +} diff --git a/bitmovin/src/api/hooks/useBitmovin.ts b/bitmovin/src/api/hooks/useBitmovin.ts new file mode 100644 index 00000000..1f428eda --- /dev/null +++ b/bitmovin/src/api/hooks/useBitmovin.ts @@ -0,0 +1,38 @@ +import { PlayerEventType, THEOplayer } from 'react-native-theoplayer'; +import { RefObject, useEffect, useRef } from 'react'; +import { BitmovinAnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; + +export function useBitmovin(config: BitmovinAnalyticsConfig): [RefObject, (player: THEOplayer | undefined) => void] { + const connector = useRef(undefined); + const theoPlayer = useRef(undefined); + + const initialize = (player: THEOplayer | undefined) => { + // Optionally destroy existent connector + onDestroy(); + + theoPlayer.current = player; + if (player) { + connector.current = new BitmovinConnector(player, config); + player.addEventListener(PlayerEventType.DESTROY, onDestroy); + } else { + throw new Error('Invalid THEOplayer instance'); + } + }; + + const onDestroy = () => { + if (connector.current) { + if (!theoPlayer.current) { + throw new Error('Invalid THEOplayer instance'); + } + theoPlayer.current.removeEventListener(PlayerEventType.DESTROY, onDestroy); + connector.current.destroy(); + connector.current = undefined; + } + }; + + useEffect(() => { + return onDestroy; + }, []); + + return [connector, initialize]; +} diff --git a/bitmovin/src/index.ts b/bitmovin/src/index.ts new file mode 100644 index 00000000..45ac8732 --- /dev/null +++ b/bitmovin/src/index.ts @@ -0,0 +1,4 @@ +export { BitmovinConnector } from './api/BitmovinConnector'; +export type { BitmovinAnalyticsConfig } from './api/BitmovinAnalyticsConfig'; +export { useBitmovin } from './api/hooks/useBitmovin'; +export { sdkVersions } from './internal/version/Version'; diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.ts new file mode 100644 index 00000000..4e6d62dc --- /dev/null +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.ts @@ -0,0 +1,35 @@ +import type { NativeHandleType, THEOplayer } from 'react-native-theoplayer'; +import { NativeModules } from 'react-native'; +import { BitmovinAnalyticsConfig } from '../api/BitmovinAnalyticsConfig'; + +const TAG = 'BitmovinConnector'; +const ERROR_MSG = 'BitmovinConnectorAdapter Error'; + +export class BitmovinConnectorAdapter { + private readonly nativeHandle: NativeHandleType; + + constructor(player: THEOplayer, config: BitmovinAnalyticsConfig) { + try { + this.nativeHandle = player.nativeHandle || -1; + NativeModules.BitmovinModule.initialize(this.nativeHandle, config); + } catch (error: unknown) { + console.error(TAG, `${ERROR_MSG}: ${error}`); + } + } + + updateMetadata(metadata: { [key: string]: string }): void { + try { + NativeModules.BitmovinModule.updateMetadata(this.nativeHandle, metadata); + } catch (error: unknown) { + console.error(TAG, `${ERROR_MSG}: ${error}`); + } + } + + destroy(): void { + try { + NativeModules.BitmovinModule.destroy(this.nativeHandle); + } catch (error: unknown) { + console.error(TAG, `${ERROR_MSG}: ${error}`); + } + } +} diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts new file mode 100644 index 00000000..b2e2c5e3 --- /dev/null +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts @@ -0,0 +1,20 @@ +import type { THEOplayer } from 'react-native-theoplayer'; +import { TheoCollector } from '@qualabs/bitmovin-analytics-collector-theoplayer'; +import { BitmovinAnalyticsConfig } from '../api/BitmovinAnalyticsConfig'; +import { ChromelessPlayer } from 'theoplayer'; + +export class BitmovinConnectorAdapter { + private integration: TheoCollector; + + constructor(player: THEOplayer, config: BitmovinAnalyticsConfig) { + this.integration = new TheoCollector(config, player.nativeHandle as ChromelessPlayer); + } + + updateMetadata(metadata: { [key: string]: string }): void { + // this.integration.sourceMetadata(metadata); + } + + destroy() { + // this.integration.destroy(); + } +} diff --git a/bitmovin/src/internal/version/Version.ts b/bitmovin/src/internal/version/Version.ts new file mode 100644 index 00000000..b4d12fa4 --- /dev/null +++ b/bitmovin/src/internal/version/Version.ts @@ -0,0 +1,9 @@ +import type { SdkVersions } from 'react-native-theoplayer'; +import manifest from '../../manifest.json'; + +export const sdkVersions = async (): Promise => { + const rnVersionString = manifest.version ?? ''; + return { + rn: rnVersionString, + }; +}; diff --git a/bitmovin/tsconfig.build.json b/bitmovin/tsconfig.build.json new file mode 100644 index 00000000..f929194b --- /dev/null +++ b/bitmovin/tsconfig.build.json @@ -0,0 +1,5 @@ + +{ + "extends": "./tsconfig", + "exclude": ["example", "ios", "android"] +} diff --git a/bitmovin/tsconfig.json b/bitmovin/tsconfig.json new file mode 100644 index 00000000..f034a7eb --- /dev/null +++ b/bitmovin/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@theoplayer/react-native-analytics-bitmovin": [ + "./src/index" + ] + } + } +} diff --git a/bitmovin/typedoc.json b/bitmovin/typedoc.json new file mode 100644 index 00000000..fc7c12a8 --- /dev/null +++ b/bitmovin/typedoc.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "extends": [ + "../typedoc.base.json" + ], + "entryPoints": [ + "src/index.ts" + ], + "tsconfig": "tsconfig.json", + "readme": "README.md", + "name": "Bitmovin Connector" +} From b16bf3d3dc4df4b138735d43ac38eab2f1d91886 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Wed, 21 Jan 2026 13:13:42 +0100 Subject: [PATCH 02/40] Update Android collector --- apps/e2e/android/app/build.gradle | 1 + apps/e2e/android/settings.gradle | 2 + bitmovin/android/build.gradle | 10 +- bitmovin/android/src/main/AndroidManifest.xml | 4 +- .../reactnative/bitmovin/BitmovinAdapter.kt | 102 ++++++++++++++++++ .../bitmovin/ReactTHEOplayerBitmovinModule.kt | 35 ++++-- bitmovin/src/api/AnalyticsConfig.ts | 15 +++ bitmovin/src/api/BitmovinConnector.ts | 35 ++++-- ...tmovinAnalyticsConfig.ts => CustomData.ts} | 23 +--- bitmovin/src/api/SourceMetadata.ts | 7 ++ bitmovin/src/api/hooks/useBitmovin.ts | 10 +- bitmovin/src/index.ts | 4 +- .../src/internal/BitmovinConnectorAdapter.ts | 28 ++++- .../internal/BitmovinConnectorAdapter.web.ts | 22 +++- 14 files changed, 241 insertions(+), 57 deletions(-) create mode 100644 bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt create mode 100644 bitmovin/src/api/AnalyticsConfig.ts rename bitmovin/src/api/{BitmovinAnalyticsConfig.ts => CustomData.ts} (69%) create mode 100644 bitmovin/src/api/SourceMetadata.ts diff --git a/apps/e2e/android/app/build.gradle b/apps/e2e/android/app/build.gradle index b7ba82f1..30124a9c 100644 --- a/apps/e2e/android/app/build.gradle +++ b/apps/e2e/android/app/build.gradle @@ -117,6 +117,7 @@ dependencies { implementation project(path: ':react-native-theoplayer-analytics-comscore') implementation project(path: ':react-native-theoplayer-analytics-conviva') implementation project(path: ':react-native-theoplayer-analytics-nielsen') + implementation project(path: ':react-native-theoplayer-analytics-bitmovin') implementation project(path: ':react-native-theoplayer-yospace') // implementation project(path: ':react-native-theoplayer-analytics-adscript') // implementation project(path: ':react-native-theoplayer-analytics-gemius') diff --git a/apps/e2e/android/settings.gradle b/apps/e2e/android/settings.gradle index db1577a6..bf22d41e 100644 --- a/apps/e2e/android/settings.gradle +++ b/apps/e2e/android/settings.gradle @@ -16,6 +16,8 @@ include ':react-native-theoplayer-analytics-conviva' project(':react-native-theoplayer-analytics-conviva').projectDir = new File(rootProject.projectDir, '../../../conviva/android') include ':react-native-theoplayer-analytics-nielsen' project(':react-native-theoplayer-analytics-nielsen').projectDir = new File(rootProject.projectDir, '../../../nielsen/android') +include ':react-native-theoplayer-analytics-bitmovin' +project(':react-native-theoplayer-analytics-bitmovin').projectDir = new File(rootProject.projectDir, '../../../bitmovin/android') include ':react-native-theoplayer-yospace' project(':react-native-theoplayer-yospace').projectDir = new File(rootProject.projectDir, '../../../yospace/android') // include ':react-native-theoplayer-analytics-adscript' diff --git a/bitmovin/android/build.gradle b/bitmovin/android/build.gradle index 1dfe7915..67374084 100644 --- a/bitmovin/android/build.gradle +++ b/bitmovin/android/build.gradle @@ -30,6 +30,7 @@ def safeExtGet(prop, fallback) { } android { + namespace "com.theoplayer.reactnative.bitmovin" compileSdkVersion safeExtGet("THEOplayerBitmovin_compileSdkVersion", 36) defaultConfig { @@ -67,14 +68,17 @@ repositories { rootProject.allprojects { repositories { -// maven { url 'https://bitmovin-repo' } + mavenLocal() + google() + mavenCentral() + maven { url 'https://artifacts.bitmovin.com/artifactory/public-releases' } } } // The Bitmovin connector requires at least THEOplayer SDK v10.0.0. def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[10.0.0, 11.0.0)') def kotlin_version = safeExtGet("THEOplayerBitmovin_kotlinVersion", "2.2.10") -def bitmovin_version = safeExtGet("THEOplayerBitmovin_bitmovinVersion", "+") +def bitmovin_version = safeExtGet("THEOplayerBitmovin_bitmovinVersion", "3.23.0-alpha2") // By default, take the connector version that aligns with the THEOplayer SDK version. def theoplayer_bitmovin_connector_version = safeExtGet('THEOplayerBitmovin_connectorVersion', theoplayer_sdk_version) @@ -87,6 +91,8 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.lifecycle:lifecycle-process:2.5.1' + implementation "com.bitmovin.analytics:collector-theoplayer:$bitmovin_version" + // THEOplayer dependencies compileOnly "com.theoplayer.theoplayer-sdk-android:core:$theoplayer_sdk_version" compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:$theoplayer_sdk_version" diff --git a/bitmovin/android/src/main/AndroidManifest.xml b/bitmovin/android/src/main/AndroidManifest.xml index be2802c1..a2f47b60 100644 --- a/bitmovin/android/src/main/AndroidManifest.xml +++ b/bitmovin/android/src/main/AndroidManifest.xml @@ -1,4 +1,2 @@ - - + diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt new file mode 100644 index 00000000..0dba2081 --- /dev/null +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt @@ -0,0 +1,102 @@ +package com.theoplayer.reactnative.bitmovin + +import com.bitmovin.analytics.api.AnalyticsConfig +import com.bitmovin.analytics.api.CustomData +import com.bitmovin.analytics.api.LogLevel +import com.bitmovin.analytics.api.RetryPolicy +import com.bitmovin.analytics.api.SourceMetadata +import com.facebook.react.bridge.ReadableMap + +private const val PROP_LICENSE_KEY = "licenseKey" +private const val PROP_AD_TRACKING_DISABLED = "adTrackingDisabled" +private const val PROP_RANDOMIZE_USER_ID = "randomizeUserId" +private const val PROP_RETRY_POLICY = "retryPolicy" +private const val PROP_BACKEND_URL = "backendUrl" +private const val PROP_LOG_LEVEL = "logLevel" +private const val PROP_SSAI_ENGAGEMENT_TRACKING_ENABLED = "ssaiEngagementTrackingEnabled" +private const val PROP_TITLE = "title" +private const val PROP_VIDEO_ID = "videoId" +private const val PROP_CDN_PROVIDER = "cdnProvider" +private const val PROP_PATH = "path" +private const val PROP_IS_LIVE = "isLive" +private const val PROP_CUSTOM_DATA = "customData" + +object BitmovinAdapter { + + /** + * Create an AnalyticsConfig object. + * + * https://developer.bitmovin.com/playback/docs/configuration-analytics + */ + fun parseConfig(config: ReadableMap): AnalyticsConfig { + return AnalyticsConfig.Builder(licenseKey = config.getString(PROP_LICENSE_KEY) ?: "") + .apply { + if (config.hasKey(PROP_AD_TRACKING_DISABLED)) { + setAdTrackingDisabled(config.getBoolean(PROP_AD_TRACKING_DISABLED)) + } + if (config.hasKey(PROP_RANDOMIZE_USER_ID)) { + setRandomizeUserId(config.getBoolean(PROP_RANDOMIZE_USER_ID)) + } + when (config.getString(PROP_RETRY_POLICY)) { + "SHORT_TERM" -> setRetryPolicy(RetryPolicy.SHORT_TERM) + "LONG_TERM" -> setRetryPolicy(RetryPolicy.LONG_TERM) + else -> setRetryPolicy(RetryPolicy.NO_RETRY) + } + if (config.hasKey(PROP_BACKEND_URL)) { + setBackendUrl(config.getString(PROP_BACKEND_URL) ?: "") + } + when (config.getString(PROP_LOG_LEVEL)) { + "DEBUG" -> setLogLevel(LogLevel.DEBUG) + else -> setLogLevel(LogLevel.ERROR) + } + if (config.hasKey(PROP_SSAI_ENGAGEMENT_TRACKING_ENABLED)) { + setSsaiEngagementTrackingEnabled(config.getBoolean(PROP_SSAI_ENGAGEMENT_TRACKING_ENABLED)) + } + } + .build() + } + + /** + * Create a SourceMetadata object. + * + * https://developer.bitmovin.com/playback/docs/configuration-analytics + */ + fun parseSourceMetadata(metadata: ReadableMap): SourceMetadata { + return SourceMetadata.Builder() + .apply { + if (metadata.hasKey(PROP_TITLE)) { + setTitle(metadata.getString(PROP_TITLE) ?: "") + } + if (metadata.hasKey(PROP_VIDEO_ID)) { + setVideoId(metadata.getString(PROP_VIDEO_ID) ?: "") + } + if (metadata.hasKey(PROP_CDN_PROVIDER)) { + setCdnProvider(metadata.getString(PROP_CDN_PROVIDER) ?: "") + } + if (metadata.hasKey(PROP_PATH)) { + setPath(metadata.getString(PROP_PATH) ?: "") + } + if (metadata.hasKey(PROP_IS_LIVE)) { + setIsLive(metadata.getBoolean(PROP_IS_LIVE)) + } + if (metadata.hasKey(PROP_CUSTOM_DATA)) { + setCustomData(parseCustomData(metadata.getMap(PROP_CUSTOM_DATA))) + } + } + .build() + } + + /** + * Create a CustomData object. + * + * https://developer.bitmovin.com/playback/docs/configuration-analytics + */ + fun parseCustomData(data: ReadableMap?): CustomData { + return CustomData.Builder().apply { + for (i in 1..50) { + val method = CustomData.Builder::class.java.getMethod("setCustomData$i", String::class.java) + method.invoke(this, data?.getString("${PROP_CUSTOM_DATA}$i")) + } + }.build() + } +} diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt index 334412ce..2e4d4834 100644 --- a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt @@ -1,5 +1,6 @@ package com.theoplayer.reactnative.bitmovin +import com.bitmovin.analytics.theoplayer.api.ITHEOplayerCollector import com.facebook.react.bridge.* import com.theoplayer.ReactTHEOplayerView import com.theoplayer.util.ViewResolver @@ -10,31 +11,49 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) { private val viewResolver: ViewResolver = ViewResolver(context) - - //private var bitmovinConnectors: HashMap = HashMap() + private var bitmovinConnectors: HashMap = HashMap() override fun getName(): String { return TAG } @ReactMethod - fun initialize(tag: Int, config: ReadableMap) { + fun initialize(tag: Int, config: ReadableMap, sourceMetadata: ReadableMap?) { viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? -> view?.player?.let { player -> // Optionally destroy any existing connector for this player. - //bitmovinConnectors[tag]?.destroy() - //bitmovinConnectors[tag] = BitmovinConnector(view.context, debug) + bitmovinConnectors[tag]?.detachPlayer() + val connector = ITHEOplayerCollector.create( + view.context, + BitmovinAdapter.parseConfig(config) + ) + sourceMetadata?.let { + connector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(it) + } + connector.attachPlayer(player) + bitmovinConnectors[tag] = connector } } } @ReactMethod - fun updateMetadata(tag: Int, metadata: ReadableMap) { - //bitmovinConnectors[tag]?.updateMetadata(metadata.toHashMap() as HashMap) + fun updateSourceMetadata(tag: Int, metadata: ReadableMap) { + bitmovinConnectors[tag]?.sourceMetadata = BitmovinAdapter.parseSourceMetadata(metadata) + } + + + @ReactMethod + fun updateCustomData(tag: Int, customData: ReadableMap) { + bitmovinConnectors[tag]?.customData = BitmovinAdapter.parseCustomData(customData) + } + + @ReactMethod + fun sendCustomDataEvent(tag: Int, customData: ReadableMap) { + bitmovinConnectors[tag]?.sendCustomDataEvent(BitmovinAdapter.parseCustomData(customData)) } @ReactMethod fun destroy(tag: Int) { - //bitmovinConnectors[tag]?.destroy() + bitmovinConnectors[tag]?.detachPlayer() } } diff --git a/bitmovin/src/api/AnalyticsConfig.ts b/bitmovin/src/api/AnalyticsConfig.ts new file mode 100644 index 00000000..eed70796 --- /dev/null +++ b/bitmovin/src/api/AnalyticsConfig.ts @@ -0,0 +1,15 @@ +import { SourceMetadata } from './SourceMetadata'; +import { CustomData } from './CustomData'; + +export interface AnalyticsConfig extends CustomData { + licenseKey: string; + adTrackingDisabled?: boolean; + randomizeUserId?: boolean; + backendUrl?: string; + cdnProvider?: string; + customUserId?: string; + sourceMetadata?: SourceMetadata; + cookiesEnabled?: boolean; + cookiesDomain?: string; + cookiesMaxAge?: number; +} diff --git a/bitmovin/src/api/BitmovinConnector.ts b/bitmovin/src/api/BitmovinConnector.ts index 2c6e7ec2..4323d220 100644 --- a/bitmovin/src/api/BitmovinConnector.ts +++ b/bitmovin/src/api/BitmovinConnector.ts @@ -1,6 +1,8 @@ import type { THEOplayer } from 'react-native-theoplayer'; import { BitmovinConnectorAdapter } from '../internal/BitmovinConnectorAdapter'; -import { BitmovinAnalyticsConfig } from './BitmovinAnalyticsConfig'; +import { AnalyticsConfig } from './AnalyticsConfig'; +import { SourceMetadata } from './SourceMetadata'; +import { CustomData } from './CustomData'; export class BitmovinConnector { private connectorAdapter: BitmovinConnectorAdapter; @@ -8,19 +10,36 @@ export class BitmovinConnector { /** * Create BitmovinConnector * - * @param player THEOplayer instance. - * @param config Configuration for Bitmovin Analytics. + * @param player THEOplayer instance. + * @param config Configuration for Bitmovin Analytics. + * @param sourceMetadata Optional initial source metadata. */ - constructor(player: THEOplayer, config: BitmovinAnalyticsConfig) { - this.connectorAdapter = new BitmovinConnectorAdapter(player, config); + constructor(player: THEOplayer, config: AnalyticsConfig, sourceMetadata?: SourceMetadata) { + this.connectorAdapter = new BitmovinConnectorAdapter(player, config, sourceMetadata); } /** - * Adds metadata which will be sent on Bitmovin requests. + * Set or update metadata for the current source. * @param metadata contains the key value pairs with data. */ - updateMetadata(metadata: { [key: string]: string }): void { - this.connectorAdapter.updateMetadata(metadata); + updateSourceMetadata(metadata: SourceMetadata): void { + this.connectorAdapter.updateSourceMetadata(metadata); + } + + /** + * Set or update custom data for the current session. + * @param customData + */ + updateCustomData(customData: CustomData): void { + this.connectorAdapter.updateCustomData(customData); + } + + /** + * Sends a custom data event with the provided custom data. + * @param customData + */ + sendCustomDataEvent(customData: CustomData): void { + this.connectorAdapter.sendCustomDataEvent(customData); } /** diff --git a/bitmovin/src/api/BitmovinAnalyticsConfig.ts b/bitmovin/src/api/CustomData.ts similarity index 69% rename from bitmovin/src/api/BitmovinAnalyticsConfig.ts rename to bitmovin/src/api/CustomData.ts index 482e7eb1..2b95e3b8 100644 --- a/bitmovin/src/api/BitmovinAnalyticsConfig.ts +++ b/bitmovin/src/api/CustomData.ts @@ -1,25 +1,4 @@ -export interface BitmovinAnalyticsConfig extends BitmovinCustomData { - licenseKey: string; - adTrackingDisabled?: boolean; - randomizeUserId?: boolean; - backendUrl?: string; - cdnProvider?: string; - customUserId?: string; - sourceMetadata?: BitmovinSourceMetadata; - cookiesEnabled?: boolean; - cookiesDomain?: string; - cookiesMaxAge?: number; -} - -export interface BitmovinSourceMetadata { - title?: string; - videoId?: string; - cdnProvider?: string; - path?: string; - isLive?: boolean; -} - -export interface BitmovinCustomData { +export interface CustomData { customData1?: string; customData2?: string; customData3?: string; diff --git a/bitmovin/src/api/SourceMetadata.ts b/bitmovin/src/api/SourceMetadata.ts new file mode 100644 index 00000000..04a3e92f --- /dev/null +++ b/bitmovin/src/api/SourceMetadata.ts @@ -0,0 +1,7 @@ +export interface SourceMetadata { + title?: string; + videoId?: string; + cdnProvider?: string; + path?: string; + isLive?: boolean; +} diff --git a/bitmovin/src/api/hooks/useBitmovin.ts b/bitmovin/src/api/hooks/useBitmovin.ts index 1f428eda..64b19e3e 100644 --- a/bitmovin/src/api/hooks/useBitmovin.ts +++ b/bitmovin/src/api/hooks/useBitmovin.ts @@ -1,8 +1,12 @@ import { PlayerEventType, THEOplayer } from 'react-native-theoplayer'; import { RefObject, useEffect, useRef } from 'react'; -import { BitmovinAnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; +import { AnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; +import { SourceMetadata } from '../SourceMetadata'; -export function useBitmovin(config: BitmovinAnalyticsConfig): [RefObject, (player: THEOplayer | undefined) => void] { +export function useBitmovin( + config: AnalyticsConfig, + sourceMetadata?: SourceMetadata, +): [RefObject, (player: THEOplayer | undefined) => void] { const connector = useRef(undefined); const theoPlayer = useRef(undefined); @@ -12,7 +16,7 @@ export function useBitmovin(config: BitmovinAnalyticsConfig): [RefObject Date: Wed, 21 Jan 2026 15:09:30 +0100 Subject: [PATCH 03/40] Add comments --- bitmovin/src/api/AnalyticsConfig.ts | 66 ++++++++++++++++++++++++++--- bitmovin/src/api/CustomData.ts | 15 +++++++ bitmovin/src/api/SourceMetadata.ts | 40 +++++++++++++++++ bitmovin/src/index.ts | 8 ++-- 4 files changed, 118 insertions(+), 11 deletions(-) diff --git a/bitmovin/src/api/AnalyticsConfig.ts b/bitmovin/src/api/AnalyticsConfig.ts index eed70796..16d97573 100644 --- a/bitmovin/src/api/AnalyticsConfig.ts +++ b/bitmovin/src/api/AnalyticsConfig.ts @@ -1,15 +1,67 @@ import { SourceMetadata } from './SourceMetadata'; -import { CustomData } from './CustomData'; -export interface AnalyticsConfig extends CustomData { +export enum RetryPolicy { + SHORT_TERM = 'SHORT_TERM', + LONG_TERM = 'LONG_TERM', + NO_RETRY = 'NO_RETRY', +} + +export interface AnalyticsConfig { + /** + * Your Bitmovin Analytics license key. + */ licenseKey: string; + + /** + * Configuration to specify retry behaviour when samples cannot be sent to the backend. + * This also allows to enable offline tracking of analytics events. + * + * @defaultValue `NO_RETRY` + */ + retryPolicy?: RetryPolicy; + + /** + * Flag to disable ClientSide Ad tracking. It doesn't affect server side ads. + * + * @platform ios, android + * @defaultValue `false` + */ adTrackingDisabled?: boolean; + + /** + * Flag to enable ServerSide Ad Engagement tracking (quartile info). + * This is a premium feature and also needs to be requested through the account. + * SSAI Audience Info is not affected by this. + * + * @platform ios, android + * @defaultValue `false` + */ + ssaiEngagementTrackingEnabled?: boolean; + + /** + * If false we use a device specific value in our data. This value is either retrieved from the system itself and is the same all the time or + * saved as a random UUID on the system. This allows you to connect sessions happening on the same device. + * If true we use a randomly generated UUID on every session. If users of your platform don't want to be tracked we recommend to set this to true. + * + * @platform ios, android + * @defaultValue `false` + */ randomizeUserId?: boolean; + + /** + * Optional backend URL to send the analytics data to. + */ backendUrl?: string; - cdnProvider?: string; - customUserId?: string; + + /** + * Log level for the analytics SDK. + * + * @defaultValue 'ERROR' + */ + logLevel?: 'DEBUG' | 'ERROR'; + + /** + * Initial source metadata to be associated with the playback session. + */ sourceMetadata?: SourceMetadata; - cookiesEnabled?: boolean; - cookiesDomain?: string; - cookiesMaxAge?: number; } diff --git a/bitmovin/src/api/CustomData.ts b/bitmovin/src/api/CustomData.ts index 2b95e3b8..9361d569 100644 --- a/bitmovin/src/api/CustomData.ts +++ b/bitmovin/src/api/CustomData.ts @@ -1,3 +1,18 @@ +/** + * The customData fields can be freely configured. The data sent through these fields can be used as a filter or as a breakdown to segment the data + * according to your needs. + * Common use-cases for customData are sending the app version used, a cross-domain or profile ID, to track viewers across different platforms, or + * assigning a high-level content category to order content assets. But the options are more or less unlimited. + * + * In the dashboard, under the license settings, customData fields can be labeled according to your liking. + * + * Note: For customData field queries we allow a cardinality of maximum of 15,000 distinct values per customData field within the selected time-frame. + * Each customData field has a limit of 160 characters and there are 5 customData Fields available for every subscription. + * Additional customData fields can be activated, up to 50 in total. These additional fields may incur a cost depending on the type of data stored. + * Please reach out to us via the support form in the dashboard if you'd like more information. + * + * {@link https://developer.bitmovin.com/playback/docs/configuration-analytics} + */ export interface CustomData { customData1?: string; customData2?: string; diff --git a/bitmovin/src/api/SourceMetadata.ts b/bitmovin/src/api/SourceMetadata.ts index 04a3e92f..a8c128f4 100644 --- a/bitmovin/src/api/SourceMetadata.ts +++ b/bitmovin/src/api/SourceMetadata.ts @@ -1,7 +1,47 @@ +import { CustomData } from './CustomData'; + +/** + * Source Metadata. + * + * {@link https://developer.bitmovin.com/playback/docs/configuration-analytics} + */ export interface SourceMetadata { + /** + * Configuring the title will allow you to efficiently compare the performance of different content pieces in the Bitmovin Analytics Dashboard. + * You will see names and titles instead of just numbers and IDs. + */ title?: string; + + /** + * Configuring the videoId is important to ensure consistency within your data framework. We use the videoId to enable filtering and breaking down + * by videoTitle, hence setting the videoId is a pre-requisite to enable this feature. If no videoId is set, the videoTitle filter cannot be applied + * to the data. + * In case there are multiple videoTitle values with the same videoId, we assign the data to each of the different video titles. + */ videoId?: string; + + /** + * Setting the CDN provider in the configuration allows you to use CDN as a breakdown or global filter in the Bitmovin Analytics Dashboard and API. + * This will enable you to compare the performance of the different CDN providers that you’re using. + */ cdnProvider?: string; + + /** + * Breadcrumb path to show where in the app the user is. + * + * @platform ios, android + */ path?: string; + + /** + * Differentiating between Live and VOD content is important, as both are often distributed through different workflows. Auto-detection is only + * possible once stream metadata is received so explicitly providing this information is helpful in certain cases and improves the accuracy of your + * data. + */ isLive?: boolean; + + /** + * The customData fields. + */ + customData?: CustomData; } diff --git a/bitmovin/src/index.ts b/bitmovin/src/index.ts index 87c8a81d..b58311c1 100644 --- a/bitmovin/src/index.ts +++ b/bitmovin/src/index.ts @@ -1,6 +1,6 @@ -export { BitmovinConnector } from './api/BitmovinConnector'; -export type { AnalyticsConfig } from './api/AnalyticsConfig'; -export type { CustomData } from './api/CustomData'; -export type { SourceMetadata } from './api/SourceMetadata'; +export * from './api/BitmovinConnector'; +export * from './api/AnalyticsConfig'; +export * from './api/CustomData'; +export * from './api/SourceMetadata'; export { useBitmovin } from './api/hooks/useBitmovin'; export { sdkVersions } from './internal/version/Version'; From 300506180d640aa1b311a4e8dcbe5ac6f7d28a0a Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Wed, 21 Jan 2026 16:37:29 +0100 Subject: [PATCH 04/40] Add table entry --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index af8d9f06..3b3e2ea3 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ the official THEOplayer React Native video player. | Adobe Heartbeat analytics using the Media Collections API | [![%40theoplayer/react-native-analytics-adobe](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-adobe?label=%40theoplayer/react-native-analytics-adobe)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-adobe) | [`Adobe`](https://github.com/THEOplayer/react-native-connectors/tree/main/adobe) | | Adobe Media Edge analytics | [![%40theoplayer/react-native-analytics-adobe-edge](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-adobe-edge?label=%40theoplayer/react-native-analytics-adobe-edge)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-adobe) | [`Adobe Edge`](https://github.com/THEOplayer/react-native-connectors/tree/main/adobe-edge) | | Agama analytics | [![%40theoplayer/react-native-analytics-agama](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-agama?label=%40theoplayer/react-native-analytics-agama)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-agama) | [`Agama`](https://github.com/THEOplayer/react-native-connectors/tree/main/agama) | +| Bitmovin analytics | [![%40theoplayer/react-native-analytics-bitmovin](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-bitmovin?label=%40theoplayer/react-native-analytics-bitmovin)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-bitmovin) | [`Agama`](https://github.com/THEOplayer/react-native-connectors/tree/main/bitmovin) | | Comscore analytics | [![%40theoplayer/react-native-analytics-comscore](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-comscore?label=%40theoplayer/react-native-analytics-comscore)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-comscore) | [`Comscore`](https://github.com/THEOplayer/react-native-connectors/tree/main/comscore) | | Content protection (DRM) | [![%40theoplayer/react-native-drm](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-drm?label=%40theoplayer/react-native-drm)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-drm) | [`DRM`](https://github.com/THEOplayer/react-native-connectors/tree/main/drm) | | Conviva analytics | [![%40theoplayer/react-native-analytics-conviva](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-conviva?label=%40theoplayer/react-native-analytics-conviva)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-conviva) | [`Conviva`](https://github.com/THEOplayer/react-native-connectors/tree/main/conviva) | From 8deee6b7a0dc3589214a58198c576b0585cce7d1 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 22 Jan 2026 14:08:19 +0100 Subject: [PATCH 05/40] Only support Android --- bitmovin/package-lock.json | 4 ++-- bitmovin/package.json | 2 +- .../src/internal/BitmovinConnectorAdapter.ts | 22 ++++++++++++++----- .../internal/BitmovinConnectorAdapter.web.ts | 13 +++++------ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/bitmovin/package-lock.json b/bitmovin/package-lock.json index c4e482a3..a8b54ee4 100644 --- a/bitmovin/package-lock.json +++ b/bitmovin/package-lock.json @@ -1,12 +1,12 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0", + "version": "1.0.0-alpha.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0", + "version": "1.0.0-alpha.1", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" diff --git a/bitmovin/package.json b/bitmovin/package.json index 637e2e88..353383f5 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -1,6 +1,6 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0", + "version": "1.0.0-alpha.1", "description": "Bitmovin analytics connector for @theoplayer/react-native", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.ts index 356baa93..30f9ea5e 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.ts @@ -1,5 +1,5 @@ import type { NativeHandleType, THEOplayer } from 'react-native-theoplayer'; -import { NativeModules } from 'react-native'; +import { NativeModules, Platform } from 'react-native'; import { AnalyticsConfig } from '../api/AnalyticsConfig'; import { SourceMetadata } from '../api/SourceMetadata'; import { CustomData } from '../api/CustomData'; @@ -13,7 +13,9 @@ export class BitmovinConnectorAdapter { constructor(player: THEOplayer, config: AnalyticsConfig, sourceMetadata?: SourceMetadata) { try { this.nativeHandle = player.nativeHandle || -1; - NativeModules.BitmovinModule.initialize(this.nativeHandle, config, sourceMetadata); + if (Platform.OS === 'android') { + NativeModules.BitmovinModule.initialize(this.nativeHandle, config, sourceMetadata); + } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -21,7 +23,9 @@ export class BitmovinConnectorAdapter { updateSourceMetadata(metadata: SourceMetadata): void { try { - NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, metadata); + if (Platform.OS === 'android') { + NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, metadata); + } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -29,7 +33,9 @@ export class BitmovinConnectorAdapter { updateCustomData(customData: CustomData): void { try { - NativeModules.BitmovinModule.updateCustomData(this.nativeHandle, customData); + if (Platform.OS === 'android') { + NativeModules.BitmovinModule.updateCustomData(this.nativeHandle, customData); + } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -37,7 +43,9 @@ export class BitmovinConnectorAdapter { sendCustomDataEvent(customData: CustomData): void { try { - NativeModules.BitmovinModule.sendCustomDataEvent(this.nativeHandle, customData); + if (Platform.OS === 'android') { + NativeModules.BitmovinModule.sendCustomDataEvent(this.nativeHandle, customData); + } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -45,7 +53,9 @@ export class BitmovinConnectorAdapter { destroy(): void { try { - NativeModules.BitmovinModule.destroy(this.nativeHandle); + if (Platform.OS === 'android') { + NativeModules.BitmovinModule.destroy(this.nativeHandle); + } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts index 032caff3..9caceb2d 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts @@ -1,21 +1,20 @@ import type { THEOplayer } from 'react-native-theoplayer'; -import { TheoCollector } from '@qualabs/bitmovin-analytics-collector-theoplayer'; import { AnalyticsConfig } from '../api/AnalyticsConfig'; import { ChromelessPlayer } from 'theoplayer'; import { CustomData, SourceMetadata } from '@theoplayer/react-native-analytics-bitmovin'; export class BitmovinConnectorAdapter { - private integration: TheoCollector; + // private integration: TheoCollector; constructor(player: THEOplayer, config: AnalyticsConfig, metadata?: SourceMetadata) { - this.integration = new TheoCollector(config, player.nativeHandle as ChromelessPlayer); - if (metadata) { - this.integration.sourceMetadata = metadata; - } + // this.integration = new TheoCollector(config, player.nativeHandle as ChromelessPlayer); + // if (metadata) { + // this.integration.sourceMetadata = metadata; + // } } updateSourceMetadata(metadata: SourceMetadata): void { - this.integration.sourceMetadata = metadata; + // this.integration.sourceMetadata = metadata; } updateCustomData(customData: CustomData): void { From cef99f155aa4487e68c175114b7e761380dfc1a7 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 22 Jan 2026 15:26:50 +0100 Subject: [PATCH 06/40] Update hook --- bitmovin/package-lock.json | 4 ++-- bitmovin/package.json | 2 +- bitmovin/src/api/hooks/useBitmovin.ts | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bitmovin/package-lock.json b/bitmovin/package-lock.json index a8b54ee4..15e9cb64 100644 --- a/bitmovin/package-lock.json +++ b/bitmovin/package-lock.json @@ -1,12 +1,12 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.3", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" diff --git a/bitmovin/package.json b/bitmovin/package.json index 353383f5..d439bfac 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -1,6 +1,6 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.3", "description": "Bitmovin analytics connector for @theoplayer/react-native", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/bitmovin/src/api/hooks/useBitmovin.ts b/bitmovin/src/api/hooks/useBitmovin.ts index 64b19e3e..1083bb6a 100644 --- a/bitmovin/src/api/hooks/useBitmovin.ts +++ b/bitmovin/src/api/hooks/useBitmovin.ts @@ -3,14 +3,13 @@ import { RefObject, useEffect, useRef } from 'react'; import { AnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; import { SourceMetadata } from '../SourceMetadata'; -export function useBitmovin( - config: AnalyticsConfig, - sourceMetadata?: SourceMetadata, -): [RefObject, (player: THEOplayer | undefined) => void] { +type InitBitmovin = (player: THEOplayer | undefined, sourceMetadata?: SourceMetadata) => void; + +export function useBitmovin(config: AnalyticsConfig): [RefObject, InitBitmovin] { const connector = useRef(undefined); const theoPlayer = useRef(undefined); - const initialize = (player: THEOplayer | undefined) => { + const initialize: InitBitmovin = (player: THEOplayer | undefined, sourceMetadata?: SourceMetadata) => { // Optionally destroy existent connector onDestroy(); From 372c7f2ad99044cbb90720b57eff581f7d724bd5 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 23 Jan 2026 10:12:42 +0100 Subject: [PATCH 07/40] Pass defaultMetadata --- .../reactnative/bitmovin/BitmovinAdapter.kt | 24 +++++++++++++++++++ .../bitmovin/ReactTHEOplayerBitmovinModule.kt | 7 +++--- bitmovin/src/api/BitmovinConnector.ts | 13 +++++----- bitmovin/src/api/DefaultMetadata.ts | 24 +++++++++++++++++++ bitmovin/src/api/hooks/useBitmovin.ts | 8 +++---- .../src/internal/BitmovinConnectorAdapter.ts | 9 +++---- .../internal/BitmovinConnectorAdapter.web.ts | 11 +++++---- 7 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 bitmovin/src/api/DefaultMetadata.ts diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt index 0dba2081..144049b9 100644 --- a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/BitmovinAdapter.kt @@ -2,6 +2,7 @@ package com.theoplayer.reactnative.bitmovin import com.bitmovin.analytics.api.AnalyticsConfig import com.bitmovin.analytics.api.CustomData +import com.bitmovin.analytics.api.DefaultMetadata import com.bitmovin.analytics.api.LogLevel import com.bitmovin.analytics.api.RetryPolicy import com.bitmovin.analytics.api.SourceMetadata @@ -20,6 +21,7 @@ private const val PROP_CDN_PROVIDER = "cdnProvider" private const val PROP_PATH = "path" private const val PROP_IS_LIVE = "isLive" private const val PROP_CUSTOM_DATA = "customData" +private const val PROP_CUSTOM_USER_ID = "customUserId" object BitmovinAdapter { @@ -86,6 +88,28 @@ object BitmovinAdapter { .build() } + /** + * Create a DefaultMetadata object. + * DefaultMetadata can be set during player creation, and this contains source independent data. + * + * https://developer.bitmovin.com/playback/docs/setup-analytics-android-v3 + */ + fun parseDefaultMetadata(metadata: ReadableMap): DefaultMetadata { + return DefaultMetadata.Builder() + .apply { + if (metadata.hasKey(PROP_CDN_PROVIDER)) { + setCdnProvider(metadata.getString(PROP_CDN_PROVIDER) ?: "") + } + if (metadata.hasKey(PROP_CUSTOM_USER_ID)) { + setCdnProvider(metadata.getString(PROP_CUSTOM_USER_ID) ?: "") + } + if (metadata.hasKey(PROP_CUSTOM_DATA)) { + setCustomData(parseCustomData(metadata.getMap(PROP_CUSTOM_DATA))) + } + } + .build() + } + /** * Create a CustomData object. * diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt index 2e4d4834..52d85bce 100644 --- a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt @@ -18,7 +18,7 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : } @ReactMethod - fun initialize(tag: Int, config: ReadableMap, sourceMetadata: ReadableMap?) { + fun initialize(tag: Int, config: ReadableMap, defaultMetadata: ReadableMap?) { viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? -> view?.player?.let { player -> // Optionally destroy any existing connector for this player. @@ -27,8 +27,8 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : view.context, BitmovinAdapter.parseConfig(config) ) - sourceMetadata?.let { - connector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(it) + defaultMetadata?.let { + connector.defaultMetadata = BitmovinAdapter.parseDefaultMetadata(it) } connector.attachPlayer(player) bitmovinConnectors[tag] = connector @@ -41,7 +41,6 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : bitmovinConnectors[tag]?.sourceMetadata = BitmovinAdapter.parseSourceMetadata(metadata) } - @ReactMethod fun updateCustomData(tag: Int, customData: ReadableMap) { bitmovinConnectors[tag]?.customData = BitmovinAdapter.parseCustomData(customData) diff --git a/bitmovin/src/api/BitmovinConnector.ts b/bitmovin/src/api/BitmovinConnector.ts index 4323d220..633a8cdc 100644 --- a/bitmovin/src/api/BitmovinConnector.ts +++ b/bitmovin/src/api/BitmovinConnector.ts @@ -3,6 +3,7 @@ import { BitmovinConnectorAdapter } from '../internal/BitmovinConnectorAdapter'; import { AnalyticsConfig } from './AnalyticsConfig'; import { SourceMetadata } from './SourceMetadata'; import { CustomData } from './CustomData'; +import { DefaultMetadata } from './DefaultMetadata'; export class BitmovinConnector { private connectorAdapter: BitmovinConnectorAdapter; @@ -12,18 +13,18 @@ export class BitmovinConnector { * * @param player THEOplayer instance. * @param config Configuration for Bitmovin Analytics. - * @param sourceMetadata Optional initial source metadata. + * @param defaultMetadata Initial source-independent data. */ - constructor(player: THEOplayer, config: AnalyticsConfig, sourceMetadata?: SourceMetadata) { - this.connectorAdapter = new BitmovinConnectorAdapter(player, config, sourceMetadata); + constructor(player: THEOplayer, config: AnalyticsConfig, defaultMetadata?: DefaultMetadata) { + this.connectorAdapter = new BitmovinConnectorAdapter(player, config, defaultMetadata); } /** * Set or update metadata for the current source. - * @param metadata contains the key value pairs with data. + * @param sourceMetadata contains the key value pairs with data. */ - updateSourceMetadata(metadata: SourceMetadata): void { - this.connectorAdapter.updateSourceMetadata(metadata); + updateSourceMetadata(sourceMetadata: SourceMetadata): void { + this.connectorAdapter.updateSourceMetadata(sourceMetadata); } /** diff --git a/bitmovin/src/api/DefaultMetadata.ts b/bitmovin/src/api/DefaultMetadata.ts new file mode 100644 index 00000000..d14b070e --- /dev/null +++ b/bitmovin/src/api/DefaultMetadata.ts @@ -0,0 +1,24 @@ +import { CustomData } from './CustomData'; + +/** + * DefaultMetadata can be set during player creation, and this contains source independent data. + * + * {@link https://developer.bitmovin.com/playback/docs/configuration-analytics} + */ +export interface DefaultMetadata { + /** + * Setting the CDN provider in the configuration allows you to use CDN as a breakdown or global filter in the Bitmovin Analytics Dashboard and API. + * This will enable you to compare the performance of the different CDN providers that you’re using. + */ + cdnProvider?: string; + + /** + * The customUserId fields. + */ + customUserId?: string; + + /** + * The customData fields. + */ + customData?: CustomData; +} diff --git a/bitmovin/src/api/hooks/useBitmovin.ts b/bitmovin/src/api/hooks/useBitmovin.ts index 1083bb6a..9b7719c8 100644 --- a/bitmovin/src/api/hooks/useBitmovin.ts +++ b/bitmovin/src/api/hooks/useBitmovin.ts @@ -1,21 +1,21 @@ import { PlayerEventType, THEOplayer } from 'react-native-theoplayer'; import { RefObject, useEffect, useRef } from 'react'; import { AnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; -import { SourceMetadata } from '../SourceMetadata'; +import { DefaultMetadata } from '../DefaultMetadata'; -type InitBitmovin = (player: THEOplayer | undefined, sourceMetadata?: SourceMetadata) => void; +type InitBitmovin = (player: THEOplayer | undefined, defaultMetadata?: DefaultMetadata) => void; export function useBitmovin(config: AnalyticsConfig): [RefObject, InitBitmovin] { const connector = useRef(undefined); const theoPlayer = useRef(undefined); - const initialize: InitBitmovin = (player: THEOplayer | undefined, sourceMetadata?: SourceMetadata) => { + const initialize: InitBitmovin = (player: THEOplayer | undefined, defaultMetadata?: DefaultMetadata) => { // Optionally destroy existent connector onDestroy(); theoPlayer.current = player; if (player) { - connector.current = new BitmovinConnector(player, config, sourceMetadata); + connector.current = new BitmovinConnector(player, config, defaultMetadata); player.addEventListener(PlayerEventType.DESTROY, onDestroy); } else { throw new Error('Invalid THEOplayer instance'); diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.ts index 30f9ea5e..fe12221b 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.ts @@ -3,6 +3,7 @@ import { NativeModules, Platform } from 'react-native'; import { AnalyticsConfig } from '../api/AnalyticsConfig'; import { SourceMetadata } from '../api/SourceMetadata'; import { CustomData } from '../api/CustomData'; +import { DefaultMetadata } from '../api/DefaultMetadata'; const TAG = 'BitmovinConnector'; const ERROR_MSG = 'BitmovinConnectorAdapter Error'; @@ -10,21 +11,21 @@ const ERROR_MSG = 'BitmovinConnectorAdapter Error'; export class BitmovinConnectorAdapter { private readonly nativeHandle: NativeHandleType; - constructor(player: THEOplayer, config: AnalyticsConfig, sourceMetadata?: SourceMetadata) { + constructor(player: THEOplayer, config: AnalyticsConfig, defaultMetadata?: DefaultMetadata) { try { this.nativeHandle = player.nativeHandle || -1; if (Platform.OS === 'android') { - NativeModules.BitmovinModule.initialize(this.nativeHandle, config, sourceMetadata); + NativeModules.BitmovinModule.initialize(this.nativeHandle, config, defaultMetadata); } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } } - updateSourceMetadata(metadata: SourceMetadata): void { + updateSourceMetadata(sourceMetadata: SourceMetadata): void { try { if (Platform.OS === 'android') { - NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, metadata); + NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, sourceMetadata); } } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts index 9caceb2d..cf1a3d16 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts @@ -2,19 +2,20 @@ import type { THEOplayer } from 'react-native-theoplayer'; import { AnalyticsConfig } from '../api/AnalyticsConfig'; import { ChromelessPlayer } from 'theoplayer'; import { CustomData, SourceMetadata } from '@theoplayer/react-native-analytics-bitmovin'; +import { DefaultMetadata } from '../api/DefaultMetadata'; export class BitmovinConnectorAdapter { // private integration: TheoCollector; - constructor(player: THEOplayer, config: AnalyticsConfig, metadata?: SourceMetadata) { + constructor(player: THEOplayer, config: AnalyticsConfig, defaultMetadata?: DefaultMetadata) { // this.integration = new TheoCollector(config, player.nativeHandle as ChromelessPlayer); - // if (metadata) { - // this.integration.sourceMetadata = metadata; + // if (defaultMetadata) { + // this.integration.defaultMetadata = defaultMetadata; // } } - updateSourceMetadata(metadata: SourceMetadata): void { - // this.integration.sourceMetadata = metadata; + updateSourceMetadata(sourceMetadata: SourceMetadata): void { + // this.integration.sourceMetadata = sourceMetadata; } updateCustomData(customData: CustomData): void { From 1311c80f6d6c03e1e51f2c38498ba48468f38927 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 23 Jan 2026 10:19:37 +0100 Subject: [PATCH 08/40] Tag version --- bitmovin/package-lock.json | 4 ++-- bitmovin/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bitmovin/package-lock.json b/bitmovin/package-lock.json index 15e9cb64..3bb7559a 100644 --- a/bitmovin/package-lock.json +++ b/bitmovin/package-lock.json @@ -1,12 +1,12 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.4", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" diff --git a/bitmovin/package.json b/bitmovin/package.json index d439bfac..d9abd834 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -1,6 +1,6 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.6", "description": "Bitmovin analytics connector for @theoplayer/react-native", "main": "lib/commonjs/index", "module": "lib/module/index", From 473160344ab0b2f1e33701b72f02188441ca04d4 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 23 Jan 2026 10:44:26 +0100 Subject: [PATCH 09/40] Drop pod --- bitmovin/react-native-theoplayer-bitmovin.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmovin/react-native-theoplayer-bitmovin.podspec b/bitmovin/react-native-theoplayer-bitmovin.podspec index b64e0a49..53511fad 100644 --- a/bitmovin/react-native-theoplayer-bitmovin.podspec +++ b/bitmovin/react-native-theoplayer-bitmovin.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,swift}" s.dependency "react-native-theoplayer" - s.dependency "THEOplayer-Connector-Bitmovin", "~> 10.0" +# s.dependency "THEOplayer-Connector-Bitmovin", "~> 10.0" # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. From e7228d8a4c195eb1a0f0ba7d35ce3e51a3a88c15 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 23 Jan 2026 14:31:52 +0100 Subject: [PATCH 10/40] Rename API file --- ...RCTNielsenAPI.swift => THEOplayerBitmovinRCTBitmovinAPI.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bitmovin/ios/{THEOplayerBitmovinRCTNielsenAPI.swift => THEOplayerBitmovinRCTBitmovinAPI.swift} (100%) diff --git a/bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift similarity index 100% rename from bitmovin/ios/THEOplayerBitmovinRCTNielsenAPI.swift rename to bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift From 53e001bc38fcc807fb65752242e21ff8bb577998 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 23 Jan 2026 16:56:22 +0100 Subject: [PATCH 11/40] Remove native module --- bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift index dcb26693..93650a15 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift +++ b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import react_native_theoplayer -import THEOplayerConnectorBitmovin import THEOplayerSDK func log(_ text: String) { @@ -29,13 +28,13 @@ class THEOplayerBitmovinRCTBitmovinAPI: NSObject, RCTBridgeModule { func initialize(_ node: NSNumber, bitmovinConfig: NSDictionary) -> Void { log("initialize triggered.") - DispatchQueue.main.async { + /*DispatchQueue.main.async { log("\(bitmovinConfig)") let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView if let player = theView?.player, var options = bitmovinConfig as? [String:Any] { } - } + }*/ } @objc(updateMetadata:metadata:) From 9520b621b1b4ab1fc2e6ef2f0403f3006d165b3d Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:07:20 +0100 Subject: [PATCH 12/40] Add BitmovinAdapter for type conversions --- bitmovin/ios/Connector/BitmovinAdapter.swift | 135 +++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 bitmovin/ios/Connector/BitmovinAdapter.swift diff --git a/bitmovin/ios/Connector/BitmovinAdapter.swift b/bitmovin/ios/Connector/BitmovinAdapter.swift new file mode 100644 index 00000000..a8ad8a43 --- /dev/null +++ b/bitmovin/ios/Connector/BitmovinAdapter.swift @@ -0,0 +1,135 @@ +// +// BitmovinAdapter.swift +// + +import Foundation +import THEOplayerSDK +import CoreCollector + +let BTMVN_PROP_LICENSE_KEY: String = "licenseKey" +let BTMVN_PROP_RETRY_POLICY: String = "retryPolicy" +let BTMVN_PROP_RANDOMIZE_USER_ID: String = "randomizeUserId" +let BTMVN_PROP_AD_TRACKING_DISABLED: String = "adTrackingDisabled" +let BTMVN_PROP_BACKEND_URL: String = "backendUrl" +let BTMVN_PROP_SSAI_ENGAGEMENT_TRACKING_ENABLED: String = "ssaiEngagementTrackingEnabled" +let BTMVN_PROP_CDN_PROVIDER: String = "cdnProvider" +let BTMVN_PROP_CUSTOM_USER_ID: String = "customUserId" +let BTMVN_PROP_CUSTOM_DATA: String = "customData" +let BTMVN_PROP_VIDEO_ID: String = "videoId" +let BTMVN_PROP_TITLE: String = "title" +let BTMVN_PROP_PATH: String = "path" +let BTMVN_PROP_IS_LIVE: String = "isLive" + +let BTMVN_RETRY_POLICY_SHORT_TERM: String = "SHORT_TERM" +let BTMVN_RETRY_POLICY_LONG_TERM: String = "LONG_TERM" + +let BTMVN_DEFAULT_BACKEND_URL = "https://analytics-ingress-global.bitmovin.com" + +class BitmovinAdapter { + class func parseConfig(_ config: [String:Any]) -> AnalyticsConfig { + + var retryPolicy: RetryPolicy? + if let foundRetryPolicy = config[BTMVN_PROP_RETRY_POLICY] as? String, + foundRetryPolicy == BTMVN_RETRY_POLICY_LONG_TERM { + retryPolicy = .longTerm + } + + return AnalyticsConfig( + licenseKey: config[BTMVN_PROP_LICENSE_KEY] as? String ?? "", + retryPolicy: retryPolicy ?? .noRetry, + randomizeUserId: config[BTMVN_PROP_RANDOMIZE_USER_ID] as? Bool ?? false, + adTrackingDisabled: config[BTMVN_PROP_AD_TRACKING_DISABLED] as? Bool ?? false, + backendUrl: config[BTMVN_PROP_BACKEND_URL] as? String ?? BTMVN_DEFAULT_BACKEND_URL, + ssaiEngagementTrackingEnabled: config[BTMVN_PROP_SSAI_ENGAGEMENT_TRACKING_ENABLED] as? Bool ?? false, + errorTransformerCallback: nil + ) + } + + class func parseSourceMetadata(_ sourceMetadata: [String:Any]) -> SourceMetadata { + return SourceMetadata( + videoId: sourceMetadata[BTMVN_PROP_VIDEO_ID] as? String, + title: sourceMetadata[BTMVN_PROP_TITLE] as? String, + path: sourceMetadata[BTMVN_PROP_PATH] as? String, + isLive: sourceMetadata[BTMVN_PROP_IS_LIVE] as? Bool, + cdnProvider: sourceMetadata[BTMVN_PROP_CDN_PROVIDER] as? String, + customData: BitmovinAdapter.parseCustomData(sourceMetadata[BTMVN_PROP_CUSTOM_DATA] as? [String:Any]) + ) + } + + class func parseDefaultMetadata(_ defaultMetadata: [String:Any]?) -> DefaultMetadata { + guard let defaultMetadataDict = defaultMetadata else { + return DefaultMetadata(cdnProvider: nil, customUserId: nil, customData: CustomData()) + } + + return DefaultMetadata( + cdnProvider: defaultMetadataDict[BTMVN_PROP_CDN_PROVIDER] as? String, + customUserId: defaultMetadataDict[BTMVN_PROP_CUSTOM_USER_ID] as? String, + customData: BitmovinAdapter.parseCustomData(defaultMetadataDict[BTMVN_PROP_CUSTOM_DATA] as? [String:Any]) + ) + } + + class func parseCustomData(_ customData: [String:Any]?) -> CustomData { + var values = Array(repeating: nil, count: 50) + for i in 1...50 { + let key = "customData\(i)" + if let value = customData?[key] as? String { + values[i - 1] = value + } + } + + return CustomData( + customData1: values[0], + customData2: values[1], + customData3: values[2], + customData4: values[3], + customData5: values[4], + customData6: values[5], + customData7: values[6], + customData8: values[7], + customData9: values[8], + customData10: values[9], + customData11: values[10], + customData12: values[11], + customData13: values[12], + customData14: values[13], + customData15: values[14], + customData16: values[15], + customData17: values[16], + customData18: values[17], + customData19: values[18], + customData20: values[19], + customData21: values[20], + customData22: values[21], + customData23: values[22], + customData24: values[23], + customData25: values[24], + customData26: values[25], + customData27: values[26], + customData28: values[27], + customData29: values[28], + customData30: values[29], + customData31: values[30], + customData32: values[31], + customData33: values[32], + customData34: values[33], + customData35: values[34], + customData36: values[35], + customData37: values[36], + customData38: values[37], + customData39: values[38], + customData40: values[39], + customData41: values[40], + customData42: values[41], + customData43: values[42], + customData44: values[43], + customData45: values[44], + customData46: values[45], + customData47: values[46], + customData48: values[47], + customData49: values[48], + customData50: values[49] + // ¯\_(ツ)_/¯ + ) + } + +} From cc4c2cd4f5522ed0e042c339a4facdf0ccce55e3 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:07:50 +0100 Subject: [PATCH 13/40] Add BitmovinConnector to separate native logic --- .../ios/Connector/BitmovinConnector.swift | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 bitmovin/ios/Connector/BitmovinConnector.swift diff --git a/bitmovin/ios/Connector/BitmovinConnector.swift b/bitmovin/ios/Connector/BitmovinConnector.swift new file mode 100644 index 00000000..8076ff0b --- /dev/null +++ b/bitmovin/ios/Connector/BitmovinConnector.swift @@ -0,0 +1,39 @@ +// +// BitmovinConnector.swift +// + +import Foundation +import THEOplayerSDK +import CoreCollector +import THEOplayerCollector + +class BitmovinConnector { + private let theoplayerCollector: THEOplayerCollector.THEOplayerCollectorApi + + init(player: THEOplayer, bitmovinConfig: [String:Any], defaultMetadata: [String:Any]? = nil) { + let config: AnalyticsConfig = BitmovinAdapter.parseConfig(bitmovinConfig) + let metadata: DefaultMetadata = BitmovinAdapter.parseDefaultMetadata(defaultMetadata) + self.theoplayerCollector = THEOplayerCollector.THEOplayerCollectorFactory.create(config: config, defaultMetadata: metadata) + log("Initialized Bitmovin Connector with config: \(config) and default metadata: \(metadata)") + } + + func updateSourceMetadata(_ metadata: [String:Any]) -> Void { + self.theoplayerCollector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(metadata) + log("Updated source metadata: \(self.theoplayerCollector.sourceMetadata)") + } + + func updateCustomMetadata(_ customData: [String:Any]) -> Void { + self.theoplayerCollector.customData = BitmovinAdapter.parseCustomData(customData) + log("Updated custom data: \(self.theoplayerCollector.customData)") + } + + func sendCustomDataEvent(_ customData: [String:Any]) -> Void { + log("Sending custom data event is not yet implemented.") + // TODO: Implement when THEOplayerCollector supports sending custom data events + } + + func destroy() -> Void { + log("Destroying Bitmovin Connector is not yet implemented.") + // TODO: Implement when THEOplayerCollector supports detaching + } +} From c3681d9c72dcb016b3bc0bb933353b8ff2b47681 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:08:13 +0100 Subject: [PATCH 14/40] Update objc bridging code --- bitmovin/ios/THEOplayerBitmovinRCTBridge.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBridge.m b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m index 2a428845..8b81faf9 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBridge.m +++ b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m @@ -8,9 +8,14 @@ @interface RCT_EXTERN_REMAP_MODULE(BitmovinModule, THEOplayerBitmovinRCTBitmovinAPI, NSObject) RCT_EXTERN_METHOD(initialize:(nonnull NSNumber *)node - bitmovinConfig:(NSDictionary)bitmovinConfig) + bitmovinConfig:(nonnull NSDictionary *)bitmovinConfig + defaultMetadata:(nullable NSDictionary *)defaultMetadata) -RCT_EXTERN_METHOD(updateMetadata:(nonnull NSNumber *)node metadata:(nonnull NSDictionary *)metadata) +RCT_EXTERN_METHOD(updateSourceMetadata:(nonnull NSNumber *)node metadata:(nonnull NSDictionary *)metadata) + +RCT_EXTERN_METHOD(updateCustomMetadata:(nonnull NSNumber *)node customData:(nonnull NSDictionary *)customData) + +RCT_EXTERN_METHOD(sendCustomDataEvent:(nonnull NSNumber *)node customData:(nonnull NSDictionary *)customData) RCT_EXTERN_METHOD(destroy:(nonnull NSNumber *)node) From e7e3c66da4236b01d9678bc325065512d537a490 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:08:43 +0100 Subject: [PATCH 15/40] Connect bridged methods to BitmovinConnector functionality --- .../THEOplayerBitmovinRCTBitmovinAPI.swift | 79 +++++++++++++------ 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift index 93650a15..5015476f 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift +++ b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift @@ -5,48 +5,79 @@ import react_native_theoplayer import THEOplayerSDK func log(_ text: String) { - #if DEBUG - print("[react-native-theoplayer-bitmovin]", text) - #endif +#if DEBUG + print("[react-native-theoplayer-bitmovin]", text) +#endif } @objc(THEOplayerBitmovinRCTBitmovinAPI) class THEOplayerBitmovinRCTBitmovinAPI: NSObject, RCTBridgeModule { @objc var bridge: RCTBridge! - -// var connectors = [NSNumber: BitmovinConnector]() - + + var connectors = [NSNumber: BitmovinConnector]() + static func moduleName() -> String! { return "BitmovinModule" } - + static func requiresMainQueueSetup() -> Bool { return false } - - @objc(initialize:bitmovinOptions:) - func initialize(_ node: NSNumber, bitmovinConfig: NSDictionary) -> Void { + + @objc(initialize:bitmovinConfig:defaultMetadata:) + func initialize(_ node: NSNumber, bitmovinConfig: NSDictionary, defaultMetadata: NSDictionary?) -> Void { log("initialize triggered.") - - /*DispatchQueue.main.async { - log("\(bitmovinConfig)") + + DispatchQueue.main.async { let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView if let player = theView?.player, - var options = bitmovinConfig as? [String:Any] { + var config = bitmovinConfig as? [String:Any] { + let metadata = defaultMetadata as? [String:Any] + let connector = BitmovinConnector(player: player, bitmovinConfig: config, defaultMetadata: metadata) + self.connectors[node] = connector + log("added connector to view \(node)") + } else { + log("cannot find THEOPlayer for node \(node)") } - }*/ + } } - - @objc(updateMetadata:metadata:) - func updateMetadata(for node: NSNumber, metadata: NSDictionary) { - log("Warning: updating metadata not possible on iOS.") + + @objc(updateSourceMetadata:metadata:) + func updateSourceMetadata(_ node: NSNumber, metadata: NSDictionary) { + log("updateSourceMetadata triggered.") + DispatchQueue.main.async { + if let sourceMetadata = metadata as? [String:Any] { + self.connectors[node]?.updateSourceMetadata(sourceMetadata) + } + } } - + + @objc(updateCustomMetadata:customData:) + func updateCustomMetadata(_ node: NSNumber, customData: NSDictionary) { + log("updateCustomMetadata triggered.") + DispatchQueue.main.async { + if let customMetadata = customData as? [String:Any] { + self.connectors[node]?.updateCustomMetadata(customMetadata) + } + } + } + + @objc(sendCustomDataEvent:customData:) + func sendCustomDataEvent(_ node: NSNumber, customData: NSDictionary) { + log("sendCustomDataEvent triggered.") + DispatchQueue.main.async { + if let customMetadata = customData as? [String:Any] { + self.connectors[node]?.sendCustomDataEvent(customMetadata) + } + } + } + @objc(destroy:) func destroy(_ node: NSNumber) -> Void { - log("destroy triggered for \(node).") -// DispatchQueue.main.async { -// self.connectors.removeValue(forKey: node) -// } + log("destroy triggered for \(node).") + DispatchQueue.main.async { + self.connectors[node]?.destroy() + self.connectors.removeValue(forKey: node) + } } } From 3f12507de042f1915fca4e17f2ba61ee83a3f8a2 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:09:25 +0100 Subject: [PATCH 16/40] Add setup for adobe-edge and bitmovin to e2e app --- apps/e2e/ios/Podfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/e2e/ios/Podfile b/apps/e2e/ios/Podfile index 0c011f07..71e7f173 100755 --- a/apps/e2e/ios/Podfile +++ b/apps/e2e/ios/Podfile @@ -32,6 +32,8 @@ target 'ReactNativeTHEOplayer' do pod 'react-native-theoplayer-conviva', :path => '../../../conviva' pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen' pod 'react-native-theoplayer-adobe', :path => '../../../adobe' + pod 'react-native-theoplayer-adobe-edge', :path => '../../../adobe-edge' + pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin' google_cast_redirect @@ -48,6 +50,8 @@ target 'ReactNativeTHEOplayer-tvOS' do pod 'react-native-theoplayer-conviva', :path => '../../../conviva' pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen' pod 'react-native-theoplayer-adobe', :path => '../../../adobe' + pod 'react-native-theoplayer-adobe-edge', :path => '../../../adobe-edge' + pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin' end From a19d327d08cbf804d739ba78e34d688d5d1e07b3 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 15:43:55 +0100 Subject: [PATCH 17/40] Drop Android only check. --- .../src/internal/BitmovinConnectorAdapter.ts | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.ts index fe12221b..78193537 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.ts @@ -14,9 +14,7 @@ export class BitmovinConnectorAdapter { constructor(player: THEOplayer, config: AnalyticsConfig, defaultMetadata?: DefaultMetadata) { try { this.nativeHandle = player.nativeHandle || -1; - if (Platform.OS === 'android') { - NativeModules.BitmovinModule.initialize(this.nativeHandle, config, defaultMetadata); - } + NativeModules.BitmovinModule.initialize(this.nativeHandle, config, defaultMetadata); } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -24,9 +22,7 @@ export class BitmovinConnectorAdapter { updateSourceMetadata(sourceMetadata: SourceMetadata): void { try { - if (Platform.OS === 'android') { - NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, sourceMetadata); - } + NativeModules.BitmovinModule.updateSourceMetadata(this.nativeHandle, sourceMetadata); } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -34,9 +30,7 @@ export class BitmovinConnectorAdapter { updateCustomData(customData: CustomData): void { try { - if (Platform.OS === 'android') { - NativeModules.BitmovinModule.updateCustomData(this.nativeHandle, customData); - } + NativeModules.BitmovinModule.updateCustomData(this.nativeHandle, customData); } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -44,9 +38,7 @@ export class BitmovinConnectorAdapter { sendCustomDataEvent(customData: CustomData): void { try { - if (Platform.OS === 'android') { - NativeModules.BitmovinModule.sendCustomDataEvent(this.nativeHandle, customData); - } + NativeModules.BitmovinModule.sendCustomDataEvent(this.nativeHandle, customData); } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } @@ -54,9 +46,7 @@ export class BitmovinConnectorAdapter { destroy(): void { try { - if (Platform.OS === 'android') { - NativeModules.BitmovinModule.destroy(this.nativeHandle); - } + NativeModules.BitmovinModule.destroy(this.nativeHandle); } catch (error: unknown) { console.error(TAG, `${ERROR_MSG}: ${error}`); } From 5ff5f01494d095508f47328e05d10aaeace1f74a Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 16:05:11 +0100 Subject: [PATCH 18/40] make config a let --- bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift index 5015476f..a578a9f9 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift +++ b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift @@ -31,7 +31,7 @@ class THEOplayerBitmovinRCTBitmovinAPI: NSObject, RCTBridgeModule { DispatchQueue.main.async { let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView if let player = theView?.player, - var config = bitmovinConfig as? [String:Any] { + let config = bitmovinConfig as? [String:Any] { let metadata = defaultMetadata as? [String:Any] let connector = BitmovinConnector(player: player, bitmovinConfig: config, defaultMetadata: metadata) self.connectors[node] = connector From abef852f9c8722308a358dbda7fc1af26f4200b3 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 26 Jan 2026 17:20:12 +0100 Subject: [PATCH 19/40] Fix podspec to fetch BitmovinAnalyticsCollector's Core --- bitmovin/react-native-theoplayer-bitmovin.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmovin/react-native-theoplayer-bitmovin.podspec b/bitmovin/react-native-theoplayer-bitmovin.podspec index 53511fad..97f0aa24 100644 --- a/bitmovin/react-native-theoplayer-bitmovin.podspec +++ b/bitmovin/react-native-theoplayer-bitmovin.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,swift}" s.dependency "react-native-theoplayer" -# s.dependency "THEOplayer-Connector-Bitmovin", "~> 10.0" + s.dependency "BitmovinAnalyticsCollector/Core", "3.21.0-a.5" # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. From b81e0fc74c2bc33747a5473fd98037c68c22441e Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 11:16:43 +0100 Subject: [PATCH 20/40] Update api --- bitmovin/package-lock.json | 4 +- bitmovin/src/api/BitmovinConnector.ts | 8 +++ bitmovin/src/api/CustomData.ts | 51 +------------------ bitmovin/src/index.ts | 1 + .../src/internal/BitmovinConnectorAdapter.ts | 8 +++ .../internal/BitmovinConnectorAdapter.web.ts | 4 ++ 6 files changed, 24 insertions(+), 52 deletions(-) diff --git a/bitmovin/package-lock.json b/bitmovin/package-lock.json index 3bb7559a..ae9246ed 100644 --- a/bitmovin/package-lock.json +++ b/bitmovin/package-lock.json @@ -1,12 +1,12 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.4", + "version": "1.0.0-alpha.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.4", + "version": "1.0.0-alpha.6", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" diff --git a/bitmovin/src/api/BitmovinConnector.ts b/bitmovin/src/api/BitmovinConnector.ts index 633a8cdc..3c7e088e 100644 --- a/bitmovin/src/api/BitmovinConnector.ts +++ b/bitmovin/src/api/BitmovinConnector.ts @@ -35,6 +35,14 @@ export class BitmovinConnector { this.connectorAdapter.updateCustomData(customData); } + /** + * Notifies the connector about a program change in a live stream. + * @param sourceMetadata + */ + programChange(sourceMetadata: SourceMetadata): void { + this.connectorAdapter.programChange(sourceMetadata); + } + /** * Sends a custom data event with the provided custom data. * @param customData diff --git a/bitmovin/src/api/CustomData.ts b/bitmovin/src/api/CustomData.ts index 9361d569..b0918f35 100644 --- a/bitmovin/src/api/CustomData.ts +++ b/bitmovin/src/api/CustomData.ts @@ -14,54 +14,5 @@ * {@link https://developer.bitmovin.com/playback/docs/configuration-analytics} */ export interface CustomData { - customData1?: string; - customData2?: string; - customData3?: string; - customData4?: string; - customData5?: string; - customData6?: string; - customData7?: string; - customData8?: string; - customData9?: string; - customData10?: string; - customData11?: string; - customData12?: string; - customData13?: string; - customData14?: string; - customData15?: string; - customData16?: string; - customData17?: string; - customData18?: string; - customData19?: string; - customData20?: string; - customData21?: string; - customData22?: string; - customData23?: string; - customData24?: string; - customData25?: string; - customData26?: string; - customData27?: string; - customData28?: string; - customData29?: string; - customData30?: string; - customData31?: string; - customData32?: string; - customData33?: string; - customData34?: string; - customData35?: string; - customData36?: string; - customData37?: string; - customData38?: string; - customData39?: string; - customData40?: string; - customData41?: string; - customData42?: string; - customData43?: string; - customData44?: string; - customData45?: string; - customData46?: string; - customData47?: string; - customData48?: string; - customData49?: string; - customData50?: string; + [key: `customData${number}`]: string | undefined; } diff --git a/bitmovin/src/index.ts b/bitmovin/src/index.ts index b58311c1..06d4859b 100644 --- a/bitmovin/src/index.ts +++ b/bitmovin/src/index.ts @@ -2,5 +2,6 @@ export * from './api/BitmovinConnector'; export * from './api/AnalyticsConfig'; export * from './api/CustomData'; export * from './api/SourceMetadata'; +export * from './api/DefaultMetadata'; export { useBitmovin } from './api/hooks/useBitmovin'; export { sdkVersions } from './internal/version/Version'; diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.ts index 78193537..150be9a6 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.ts @@ -36,6 +36,14 @@ export class BitmovinConnectorAdapter { } } + programChange(sourceMetadata: SourceMetadata): void { + try { + NativeModules.BitmovinModule.programChange(this.nativeHandle, sourceMetadata); + } catch (error: unknown) { + console.error(TAG, `${ERROR_MSG}: ${error}`); + } + } + sendCustomDataEvent(customData: CustomData): void { try { NativeModules.BitmovinModule.sendCustomDataEvent(this.nativeHandle, customData); diff --git a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts index cf1a3d16..3f630e27 100644 --- a/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts +++ b/bitmovin/src/internal/BitmovinConnectorAdapter.web.ts @@ -22,6 +22,10 @@ export class BitmovinConnectorAdapter { // Not supported in web SDK } + programChange(sourceMetadata: SourceMetadata): void { + // NYI + } + sendCustomDataEvent(customData: CustomData): void { // Not supported in web SDK } From 058a6f908781f3dfc1c69cb2ca374d328767b256 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 11:17:13 +0100 Subject: [PATCH 21/40] Bump versions --- package-lock.json | 10 ++++++---- package.json | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 994ca668..20cedfe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "react-native": "^0.79.0", "react-native-builder-bob": "^0.39.1", "react-native-device-info": "^14.0.4", - "react-native-theoplayer": "^10", + "react-native-theoplayer": "^10.8.0", "rimraf": "^5.0.10", "theoplayer": "^10", "typedoc": "^0.25.13", @@ -53,7 +53,7 @@ }, "adobe": { "name": "@theoplayer/react-native-analytics-adobe", - "version": "1.13.0", + "version": "1.14.3", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "peerDependencies": { "react": "*", @@ -70,7 +70,7 @@ }, "adobe-edge": { "name": "@theoplayer/react-native-analytics-adobe-edge", - "version": "0.7.0", + "version": "1.0.0", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@adobe/alloy": "^2.30.0", @@ -11079,7 +11079,9 @@ } }, "node_modules/react-native-theoplayer": { - "version": "10.0.0", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/react-native-theoplayer/-/react-native-theoplayer-10.8.0.tgz", + "integrity": "sha512-OkwXb7F7gc56AeSeo47D9PzG5MaQfegDH1gQ6+XAO4Ivj5H2Vw2qLZ08Fjq3lI64DhFsW5gHzGIx4OFyRYRuxA==", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@theoplayer/cmcd-connector-web": "^1.4.0", diff --git a/package.json b/package.json index df0e7103..30b35cc2 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "react-native": "^0.79.0", "react-native-builder-bob": "^0.39.1", "react-native-device-info": "^14.0.4", - "react-native-theoplayer": "^10", + "react-native-theoplayer": "^10.8.0", "rimraf": "^5.0.10", "theoplayer": "^10", "typedoc": "^0.25.13", From ddf98b1a21c54111393fbcecccbcfab4a91d56b4 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 11:21:34 +0100 Subject: [PATCH 22/40] Update e2e test app --- .gitignore | 1 + apps/e2e/.env.example | 11 ++ apps/e2e/android/app/build.gradle | 3 + apps/e2e/babel.config.js | 14 -- apps/e2e/index.js | 5 +- apps/e2e/metro.config.js | 39 +++- apps/e2e/package-lock.json | 67 ++++--- apps/e2e/package.json | 18 +- apps/e2e/src/App.tsx | 201 +++++++++++++++++++++ apps/e2e/src/constants/bitmovin.config.ts | 12 ++ apps/e2e/src/constants/conviva.config.ts | 8 + apps/e2e/src/constants/conviva.metadata.ts | 7 + apps/e2e/tsconfig.json | 33 +--- 13 files changed, 337 insertions(+), 82 deletions(-) create mode 100644 apps/e2e/.env.example create mode 100644 apps/e2e/src/App.tsx create mode 100644 apps/e2e/src/constants/bitmovin.config.ts create mode 100644 apps/e2e/src/constants/conviva.config.ts create mode 100644 apps/e2e/src/constants/conviva.metadata.ts diff --git a/.gitignore b/.gitignore index d6562612..9b263098 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,4 @@ lib/ manifest.json apps/e2e/cavy_results.md apps/e2e/ios/Pods +apps/e2e/.env diff --git a/apps/e2e/.env.example b/apps/e2e/.env.example new file mode 100644 index 00000000..bd86f2e8 --- /dev/null +++ b/apps/e2e/.env.example @@ -0,0 +1,11 @@ +THEO_LICENSE_KEY= + +# CONVIVA +CONVIVA_CUSTOMER_KEY= +CONVIVA_DEBUG=true +CONVIVA_TOUCHSTONE_SERVICE_URL= +CONVIVA_VIEWER_ID=e2e_viewer_id + +# BITMOVIN +BITMOVIN_LICENSE_KEY= +BITMOVIN_LOG_LEVEL=DEBUG diff --git a/apps/e2e/android/app/build.gradle b/apps/e2e/android/app/build.gradle index 30124a9c..c5448f8c 100644 --- a/apps/e2e/android/app/build.gradle +++ b/apps/e2e/android/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" +apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" /** * This is the configuration block to customize your React Native Android app. @@ -82,6 +83,8 @@ android { applicationId "com.reactnativetheoplayer.e2e" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion + // Extra react-native-config resource + resValue "string", "build_config_package", "com.reactnativetheoplayer" versionCode 1 versionName "1.0" } diff --git a/apps/e2e/babel.config.js b/apps/e2e/babel.config.js index e4e400fe..565292ee 100644 --- a/apps/e2e/babel.config.js +++ b/apps/e2e/babel.config.js @@ -1,14 +1,3 @@ -const path = require('path'); - -const connectors = [ - {name: '@theoplayer/react-native-analytics-adobe', path: '../../adobe'} -]; - -const alias = connectors.reduce((acc, connector) => { - acc[connector.name] = path.join(__dirname, connector.path, 'src/index'); - return acc; -}, {}); - module.exports = { presets: ['module:@react-native/babel-preset'], plugins: [ @@ -16,9 +5,6 @@ module.exports = { 'module-resolver', { extensions: ['.tsx', '.ts', '.js', '.json'], - alias: { - ...alias - } }, ], ], diff --git a/apps/e2e/index.js b/apps/e2e/index.js index 7d53b637..826fc36d 100644 --- a/apps/e2e/index.js +++ b/apps/e2e/index.js @@ -1 +1,4 @@ -console.error('This app can only be used with cavy-cli'); +import { AppRegistry } from 'react-native'; +import App from './src/App'; + +AppRegistry.registerComponent('ReactNativeTHEOplayerE2E', () => App); diff --git a/apps/e2e/metro.config.js b/apps/e2e/metro.config.js index 9ed1c221..f3f1604b 100644 --- a/apps/e2e/metro.config.js +++ b/apps/e2e/metro.config.js @@ -2,6 +2,29 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); const path = require('path'); const root = path.resolve(__dirname, '../..'); +const packages = [ + 'react', + 'react-native', + 'react-native-theoplayer', + '@babel/runtime' +]; + +const connectors = [ + 'adobe', + 'adobe-edge', + 'adscript', + 'agama', + 'bitmovin', + 'comscore', + 'conviva', + 'drm', + 'gemius', + 'mux', + 'nielsen', + 'yospace', + 'youbora', +] + /** * Metro configuration * https://reactnative.dev/docs/metro @@ -9,7 +32,21 @@ const root = path.resolve(__dirname, '../..'); * @type {import('metro-config').MetroConfig} */ const config = { - watchFolders: [root], + projectRoot: __dirname, + watchFolders: [ + ...connectors.map(cn => path.resolve(root, cn)), + ], + resolver: { + /** + * Metro does not resolve dependencies across multiple node_modules folders by default. + * Explicitly mapping packages in extraNodeModules ensures all dependencies resolve to the correct versions, + * avoids duplication, and prevents issues like multiple React instances or module not found errors. + */ + extraNodeModules: { + ...Object.fromEntries(packages.map((pkg) => [pkg, path.join(__dirname, 'node_modules', pkg)])), + ...Object.fromEntries(connectors.map((cn) => [`@theoplayer/react-native-analytics-${cn}`, path.join(root, cn)])), + }, + }, }; module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/apps/e2e/package-lock.json b/apps/e2e/package-lock.json index b55f2d58..3c9c2e84 100644 --- a/apps/e2e/package-lock.json +++ b/apps/e2e/package-lock.json @@ -9,14 +9,16 @@ "version": "0.0.1", "hasInstallScript": true, "dependencies": { - "@theoplayer/react-native-ui": "^0.18.0", + "@theoplayer/react-native-ui": "^0.21.3", "react": "19.0.0", "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", + "react-native-config": "^1.6.1", "react-native-device-info": "^10.14.0", + "react-native-safe-area-context": "^5.6.2", "react-native-status-bar-height": "^2.6.0", "react-native-svg": "^15.11.2", - "react-native-theoplayer": "^10", + "react-native-theoplayer": "^10.8.0", "react-native-web": "^0.20.0", "react-native-web-image-loader": "^0.1.1" }, @@ -75,7 +77,6 @@ "node_modules/@babel/core": { "version": "7.28.4", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -105,7 +106,6 @@ "version": "7.28.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -4013,7 +4013,9 @@ } }, "node_modules/@theoplayer/react-native-ui": { - "version": "0.18.0", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@theoplayer/react-native-ui/-/react-native-ui-0.21.3.tgz", + "integrity": "sha512-cTffk/1vwKz/Be49Jx/Fc+SraUEfP3PP/Scv4T28FH/Rp6gArbfXSGc7Y7UDzrTP0SsYxiZIInuZyWh+Imuk6Q==", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "dependencies": { "@miblanchard/react-native-slider": "^2.6.0", @@ -4237,7 +4239,6 @@ "version": "19.1.13", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -4322,7 +4323,6 @@ "version": "7.18.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -4355,7 +4355,6 @@ "version": "7.18.0", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -4740,7 +4739,6 @@ "node_modules/acorn": { "version": "8.15.0", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4777,7 +4775,6 @@ "node_modules/ajv": { "version": "6.12.6", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5506,7 +5503,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.2", "caniuse-lite": "^1.0.30001741", @@ -6081,7 +6077,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6825,7 +6820,6 @@ "version": "8.57.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11658,7 +11652,6 @@ "version": "15.8.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -11764,7 +11757,6 @@ "node_modules/react": { "version": "19.0.0", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -11780,7 +11772,6 @@ "node_modules/react-dom": { "version": "19.0.0", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.25.0" }, @@ -11799,7 +11790,6 @@ "resolved": "https://registry.npmjs.org/react-native-tvos/-/react-native-tvos-0.79.0-0.tgz", "integrity": "sha512-KBZfFTIyyLTCj2Fbb73xD0RWZAqN2o3J++2ve3nmsGopVLOeF3HJ43Z3lKjpUReDGgLrkGhdf2hYk8otRr4g7g==", "license": "MIT", - "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native-tvos/virtualized-lists": "0.79.0-0", @@ -11854,6 +11844,22 @@ } } }, + "node_modules/react-native-config": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/react-native-config/-/react-native-config-1.6.1.tgz", + "integrity": "sha512-HvKtxr6/Tq3iMdFx5REYZsjCtPi0RxQOMCs15+DqrUPTNFtWHuEuh+zw7fJp+dmuO79YMfdtlsPWIGTHtaXwjg==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-windows": ">=0.61" + }, + "peerDependenciesMeta": { + "react-native-windows": { + "optional": true + } + } + }, "node_modules/react-native-device-info": { "version": "10.14.0", "license": "MIT", @@ -11870,6 +11876,16 @@ "react-native": "*" } }, + "node_modules/react-native-safe-area-context": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", + "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-status-bar-height": { "version": "2.6.0", "license": "MIT" @@ -11877,7 +11893,6 @@ "node_modules/react-native-svg": { "version": "15.13.0", "license": "MIT", - "peer": true, "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", @@ -11899,9 +11914,10 @@ } }, "node_modules/react-native-theoplayer": { - "version": "10.0.0", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/react-native-theoplayer/-/react-native-theoplayer-10.8.0.tgz", + "integrity": "sha512-OkwXb7F7gc56AeSeo47D9PzG5MaQfegDH1gQ6+XAO4Ivj5H2Vw2qLZ08Fjq3lI64DhFsW5gHzGIx4OFyRYRuxA==", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", - "peer": true, "dependencies": { "@theoplayer/cmcd-connector-web": "^1.4.0", "buffer": "^6.0.3" @@ -13318,7 +13334,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -13498,7 +13513,6 @@ "version": "4.0.3", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13570,8 +13584,7 @@ "node_modules/tslib": { "version": "2.8.1", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", @@ -13707,7 +13720,6 @@ "version": "5.1.6", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13937,7 +13949,6 @@ "version": "5.101.3", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -13985,7 +13996,6 @@ "version": "6.0.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.6.1", "@webpack-cli/configtest": "^3.0.1", @@ -14068,7 +14078,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -14209,7 +14218,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -14322,7 +14330,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", diff --git a/apps/e2e/package.json b/apps/e2e/package.json index 46418b1c..6a4beb4c 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -14,14 +14,16 @@ "postinstall": "patch-package" }, "dependencies": { - "@theoplayer/react-native-ui": "^0.18.0", + "@theoplayer/react-native-ui": "^0.21.3", "react": "19.0.0", "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", + "react-native-config": "^1.6.1", "react-native-device-info": "^10.14.0", + "react-native-safe-area-context": "^5.6.2", "react-native-status-bar-height": "^2.6.0", "react-native-svg": "^15.11.2", - "react-native-theoplayer": "^10", + "react-native-theoplayer": "^10.8.0", "react-native-web": "^0.20.0", "react-native-web-image-loader": "^0.1.1" }, @@ -55,16 +57,8 @@ "webpack-dev-server": "^5.2.1" }, "overrides": { - "react-native-google-cast": { - "react-native": "$react-native" - }, - "@miblanchard/react-native-slider": { - "react-native": "$react-native" - }, - "cavy": { - "react": "$react", - "react-native": "$react-native" - } + "react": "$react", + "react-native": "$react-native" }, "engines": { "node": ">=18" diff --git a/apps/e2e/src/App.tsx b/apps/e2e/src/App.tsx new file mode 100644 index 00000000..e1d09aa7 --- /dev/null +++ b/apps/e2e/src/App.tsx @@ -0,0 +1,201 @@ +import * as React from 'react'; +import { useState } from 'react'; +import { + AdClickThroughButton, + AdCountdown, + AdDisplay, + AdSkipButton, + AutoFocusGuide, + CenteredControlBar, + CenteredDelayedActivityIndicator, + ControlBar, + DEFAULT_THEOPLAYER_THEME, + FullscreenButton, + LanguageMenuButton, + MuteButton, + PipButton, + PlaybackRateSubMenu, + PlayButton, + QualitySubMenu, + SeekBar, + SettingsMenuButton, + SkipButton, + Spacer, + TimeLabel, + UiContainer, +} from '@theoplayer/react-native-ui'; +import { PlayerConfiguration, PlayerEventType, THEOplayer, THEOplayerView } from 'react-native-theoplayer'; +import { Platform, StatusBar, StyleSheet, useColorScheme, View } from 'react-native'; +import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; +import Config from 'react-native-config'; +import {useConviva} from "@theoplayer/react-native-analytics-conviva"; +import {convivaConfig} from "./constants/conviva.config"; +import {convivaMetadata} from "./constants/conviva.metadata"; +import { useBitmovin } from '@theoplayer/react-native-analytics-bitmovin'; +import { bitmovinConfig, bitmovinDefaultMetadata } from './constants/bitmovin.config'; + +const playerConfig: PlayerConfiguration = { + // Get your THEOplayer license from https://portal.theoplayer.com/ + // Without a license, only demo sources hosted on '*.theoplayer.com' domains can be played. + license: Config.THEO_LICENSE_KEY, + libraryLocation: 'theoplayer', + mediaControl: { + mediaSessionEnabled: true, + }, + mutedAutoplay: 'all', +}; + +/** + * The example app demonstrates the use of the THEOplayerView with a custom UI using the provided UI components. + * If you don't want to create a custom UI, you can just use the THEOplayerDefaultUi component instead. + */ +export default function App() { + const [player, setPlayer] = useState(undefined); + const isDarkMode = useColorScheme() === 'dark'; + + const [, initConviva] = useConviva(convivaMetadata, convivaConfig); + const [, initBitmovin] = useBitmovin(bitmovinConfig); + + const onPlayerReady = (player: THEOplayer) => { + setPlayer(player); + + initConviva(player); + initBitmovin(player, bitmovinDefaultMetadata); + + // optional debug logs + player.addEventListener(PlayerEventType.SOURCE_CHANGE, console.log); + player.addEventListener(PlayerEventType.LOADED_DATA, console.log); + player.addEventListener(PlayerEventType.LOADED_METADATA, console.log); + player.addEventListener(PlayerEventType.READYSTATE_CHANGE, console.log); + player.addEventListener(PlayerEventType.PLAY, console.log); + player.addEventListener(PlayerEventType.PLAYING, console.log); + player.addEventListener(PlayerEventType.PAUSE, console.log); + player.addEventListener(PlayerEventType.SEEKING, console.log); + player.addEventListener(PlayerEventType.SEEKED, console.log); + player.addEventListener(PlayerEventType.ENDED, console.log); + player.muted = true; + player.autoplay = true; + + player.source = { + sources: [ + { + src: 'https://cdn.theoplayer.com/video/sintel/nosubs.m3u8', + type: 'application/x-mpegurl', + }, + ], + metadata: { + title: 'Sintel', + subtitle: 'HLS - Sideloaded Chapters', + album: 'React-Native THEOplayer demos', + mediaUri: 'https://theoplayer.com', + displayIconUri: 'https://cdn.theoplayer.com/video/sintel_old/poster.jpg', + artist: 'THEOplayer', + } + }; + + player.backgroundAudioConfiguration = { enabled: true }; + player.pipConfiguration = { startsAutomatically: true }; + }; + + return ( + /** + * The SafeAreaProvider component is a View from where insets provided by consumers are relative to. + * This means that if this view overlaps with any system elements (status bar, notches, etc.) these values will be provided to + * descendent consumers such as SafeAreaView. + * {@link https://appandflow.github.io/react-native-safe-area-context/api/safe-area-provider} + */ + + + + + + {player !== undefined && ( + } + top={ + + + + + + {/*Note: quality selection is not available on iOS */} + + + + + + } + center={ + + } + middle={} + right={} + /> + + } + bottom={ + + + + + + + + + + + + + } + adTop={ + + + + + + } + adCenter={ + + } /> + + } + adBottom={ + + + + + + + + + + + + + } + /> + )} + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'black', + }, + playerContainer: { + flex: 1, + // on iOS, we cannot stretch an inline playerView to cover the whole screen, otherwise it assumes fullscreen presentationMode. + marginHorizontal: Platform.select({ ios: 2, default: 0 }), + alignItems: 'center', + justifyContent: 'center', + }, +}); diff --git a/apps/e2e/src/constants/bitmovin.config.ts b/apps/e2e/src/constants/bitmovin.config.ts new file mode 100644 index 00000000..0b9636e7 --- /dev/null +++ b/apps/e2e/src/constants/bitmovin.config.ts @@ -0,0 +1,12 @@ +import { AnalyticsConfig, DefaultMetadata } from '@theoplayer/react-native-analytics-bitmovin'; +import Config from 'react-native-config'; + +export const bitmovinConfig: AnalyticsConfig = { + licenseKey: Config.BITMOVIN_LICENSE_KEY, + logLevel: Config.BITMOVIN_LOG_LEVEL as 'DEBUG' | 'ERROR', +}; + +export const bitmovinDefaultMetadata: DefaultMetadata = { + cdnProvider: Config.BITMOVIN_CDN_PROVIDER, + customUserId: Config.BITMOVIN_CUSTOM_USER_ID, +}; diff --git a/apps/e2e/src/constants/conviva.config.ts b/apps/e2e/src/constants/conviva.config.ts new file mode 100644 index 00000000..3c39bf3f --- /dev/null +++ b/apps/e2e/src/constants/conviva.config.ts @@ -0,0 +1,8 @@ +import { ConvivaConfiguration } from "@theoplayer/react-native-analytics-conviva"; +import Config from 'react-native-config'; + +export const convivaConfig: ConvivaConfiguration = { + customerKey: Config.CONVIVA_CUSTOMER_KEY, + debug: Config.CONVIVA_DEBUG === 'true', + gatewayUrl: Config.CONVIVA_TOUCHSTONE_SERVICE_URL, +}; diff --git a/apps/e2e/src/constants/conviva.metadata.ts b/apps/e2e/src/constants/conviva.metadata.ts new file mode 100644 index 00000000..8e4b40a7 --- /dev/null +++ b/apps/e2e/src/constants/conviva.metadata.ts @@ -0,0 +1,7 @@ +import { ConvivaMetadata } from "@theoplayer/react-native-analytics-conviva"; +import Config from 'react-native-config'; + +export const convivaMetadata: ConvivaMetadata = { + ['Conviva.applicationName']: 'THEOplayer', + ['Conviva.viewerId']: Config.CONVIVA_VIEWER_ID, +}; diff --git a/apps/e2e/tsconfig.json b/apps/e2e/tsconfig.json index 3c3509a0..f32c8b9f 100644 --- a/apps/e2e/tsconfig.json +++ b/apps/e2e/tsconfig.json @@ -3,30 +3,15 @@ "compilerOptions": { "baseUrl": "./", "paths": { - "@theoplayer/react-native-analytics-adobe": [ - "../../adobe/src/index" - ], - "@theoplayer/react-native-analytics-adobe-edge": [ - "../../adobe-edge/src/index" - ], - "@theoplayer/react-native-analytics-comscore": [ - "../../comscore/src/index" - ], - "@theoplayer/react-native-analytics-conviva": [ - "../../conviva/src/index" - ], - "@theoplayer/react-native-analytics-nielsen": [ - "../../nielsen/src/index" - ], - "@theoplayer/react-native-yospace": [ - "../../yospace/src/index" - ], - "@theoplayer/react-native-adscript": [ - "../../adscript/src/index" - ], - "@theoplayer/react-native-gemius": [ - "../../gemius/src/index" - ] + "@theoplayer/react-native-analytics-adobe": ["../../adobe/src/index"], + "@theoplayer/react-native-analytics-adobe-edge": ["../../adobe-edge/src/index"], + "@theoplayer/react-native-analytics-bitmovin": ["../../bitmovin/src/index"], + "@theoplayer/react-native-analytics-comscore": ["../../comscore/src/index"], + "@theoplayer/react-native-analytics-conviva": ["../../conviva/src/index"], + "@theoplayer/react-native-analytics-nielsen": ["../../nielsen/src/index"], + "@theoplayer/react-native-yospace": ["../../yospace/src/index"], + "@theoplayer/react-native-adscript": ["../../adscript/src/index"], + "@theoplayer/react-native-gemius": ["../../gemius/src/index"] } } } From 308e66fcae1eccb93d4555a14b3649bdf85cd2d5 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 11:41:12 +0100 Subject: [PATCH 23/40] Fix workspace --- bitmovin/package.json | 8 -------- package-lock.json | 21 +++++++++++++++++++++ package.json | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/bitmovin/package.json b/bitmovin/package.json index d9abd834..4509a1ec 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -52,9 +52,6 @@ "publishConfig": { "registry": "https://registry.npmjs.org/" }, - "dependencies": { - "@qualabs/bitmovin-analytics-collector-theoplayer": "^1.0.4" - }, "peerDependencies": { "react": "*", "react-native": "*", @@ -66,11 +63,6 @@ "optional": true } }, - "overrides": { - "@qualabs/bitmovin-analytics-collector-theoplayer": { - "theoplayer": "^10" - } - }, "eslintIgnore": [ "node_modules/", "lib/" diff --git a/package-lock.json b/package-lock.json index 20cedfe8..589c4572 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "adobe", "adobe-edge", "adscript", + "bitmovin", "comscore", "conviva", "drm", @@ -131,6 +132,22 @@ } } }, + "bitmovin": { + "name": "@theoplayer/react-native-analytics-bitmovin", + "version": "1.0.0-alpha.6", + "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-theoplayer": "^7 || ^8 || ^9 || ^10", + "theoplayer": "^7 || ^8 || ^9 || ^10" + }, + "peerDependenciesMeta": { + "theoplayer": { + "optional": true + } + } + }, "comscore": { "name": "@theoplayer/react-native-analytics-comscore", "version": "1.12.0", @@ -4119,6 +4136,10 @@ "resolved": "agama", "link": true }, + "node_modules/@theoplayer/react-native-analytics-bitmovin": { + "resolved": "bitmovin", + "link": true + }, "node_modules/@theoplayer/react-native-analytics-comscore": { "resolved": "comscore", "link": true diff --git a/package.json b/package.json index 30b35cc2..f7515317 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "adobe", "adobe-edge", "adscript", + "bitmovin", "comscore", "conviva", "drm", From d16458ea9b24ee4d6635a4d2e0a86b4588efcb84 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 12:00:53 +0100 Subject: [PATCH 24/40] Disable yospace test --- apps/e2e/android/app/build.gradle | 172 +++++++++--------- .../reactnativetheoplayer/MainApplication.kt | 6 +- apps/e2e/android/settings.gradle | 4 +- apps/e2e/src/tests/index.ts | 5 - 4 files changed, 92 insertions(+), 95 deletions(-) diff --git a/apps/e2e/android/app/build.gradle b/apps/e2e/android/app/build.gradle index c5448f8c..63b5703c 100644 --- a/apps/e2e/android/app/build.gradle +++ b/apps/e2e/android/app/build.gradle @@ -8,51 +8,51 @@ apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.grad * By default you don't need to apply any configuration, just uncomment the lines you need. */ react { - /* Folders */ - // The root of your project, i.e. where "package.json" lives. Default is '..' - // root = file("../") - // The folder where the react-native NPM package is. Default is ../node_modules/react-native - // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen - // codegenDir = file("../node_modules/@react-native/codegen") - // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js - // cliFile = file("../node_modules/react-native/cli.js") + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") - /* Variants */ - // The list of variants to that are debuggable. For those we're going to - // skip the bundling of the JS bundle and the assets. By default is just 'debug'. - // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. - // debuggableVariants = ["liteDebug", "prodDebug"] + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] - /* Bundling */ - // A list containing the node command and its flags. Default is just 'node'. - // nodeExecutableAndArgs = ["node"] - // - // The command to run when bundling. By default is 'bundle' - // bundleCommand = "ram-bundle" - // - // The path to the CLI configuration file. Default is empty. - // bundleConfig = file(../rn-cli.config.js) - // - // The name of the generated asset file containing your JS bundle - // bundleAssetName = "MyApplication.android.bundle" - // - // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' - entryFile = file("../../index.js") - // - // A list of extra flags to pass to the 'bundle' commands. - // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle - // extraPackagerArgs = [] + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + entryFile = file("../../index.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] - /* Hermes Commands */ - // The hermes compiler command to run. By default it is 'hermesc' - // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" - // - // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" - // hermesFlags = ["-O", "-output-source-map"] + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] - /* Autolinking */ - autolinkLibrariesWithApp() + /* Autolinking */ + autolinkLibrariesWithApp() } /** @@ -74,40 +74,40 @@ def enableProguardInReleaseBuilds = true def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' android { - ndkVersion rootProject.ext.ndkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - compileSdk rootProject.ext.compileSdkVersion + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion - namespace "com.reactnativetheoplayer" - defaultConfig { - applicationId "com.reactnativetheoplayer.e2e" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - // Extra react-native-config resource - resValue "string", "build_config_package", "com.reactnativetheoplayer" - versionCode 1 - versionName "1.0" + namespace "com.reactnativetheoplayer" + defaultConfig { + applicationId "com.reactnativetheoplayer.e2e" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + // Extra react-native-config resource + resValue "string", "build_config_package", "com.reactnativetheoplayer" + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' } - signingConfigs { - debug { - storeFile file('debug.keystore') - storePassword 'android' - keyAlias 'androiddebugkey' - keyPassword 'android' - } + } + buildTypes { + debug { + signingConfig signingConfigs.debug } - buildTypes { - debug { - signingConfig signingConfigs.debug - } - release { - // Caution! In production, you need to generate your own keystore file. - // see https://reactnative.dev/docs/signed-apk-android. - signingConfig signingConfigs.debug - minifyEnabled enableProguardInReleaseBuilds - proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" - } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } + } } def safeExtGet(prop, fallback) { @@ -115,24 +115,24 @@ def safeExtGet(prop, fallback) { } dependencies { - implementation project(path: ':react-native-theoplayer-analytics-adobe') - implementation project(path: ':react-native-theoplayer-analytics-adobe-edge') - implementation project(path: ':react-native-theoplayer-analytics-comscore') - implementation project(path: ':react-native-theoplayer-analytics-conviva') - implementation project(path: ':react-native-theoplayer-analytics-nielsen') - implementation project(path: ':react-native-theoplayer-analytics-bitmovin') - implementation project(path: ':react-native-theoplayer-yospace') + implementation project(path: ':react-native-theoplayer-analytics-adobe') + implementation project(path: ':react-native-theoplayer-analytics-adobe-edge') + implementation project(path: ':react-native-theoplayer-analytics-comscore') + implementation project(path: ':react-native-theoplayer-analytics-conviva') + implementation project(path: ':react-native-theoplayer-analytics-nielsen') + implementation project(path: ':react-native-theoplayer-analytics-bitmovin') +// implementation project(path: ':react-native-theoplayer-yospace') // implementation project(path: ':react-native-theoplayer-analytics-adscript') // implementation project(path: ':react-native-theoplayer-analytics-gemius') - implementation "com.google.android.gms:play-services-cast-framework:${safeExtGet('castFrameworkVersion', '+')}" + implementation "com.google.android.gms:play-services-cast-framework:${safeExtGet('castFrameworkVersion', '+')}" - // The version of react-native is set by the React Native Gradle Plugin - implementation("com.facebook.react:react-android") + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") - if (hermesEnabled.toBoolean()) { - implementation("com.facebook.react:hermes-android") - } else { - implementation jscFlavor - } + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } } diff --git a/apps/e2e/android/app/src/main/java/com/reactnativetheoplayer/MainApplication.kt b/apps/e2e/android/app/src/main/java/com/reactnativetheoplayer/MainApplication.kt index f40d556a..c69d924c 100644 --- a/apps/e2e/android/app/src/main/java/com/reactnativetheoplayer/MainApplication.kt +++ b/apps/e2e/android/app/src/main/java/com/reactnativetheoplayer/MainApplication.kt @@ -11,10 +11,11 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.react.soloader.OpenSourceMergedSoMapping import com.facebook.soloader.SoLoader +import com.theoplayer.reactnative.bitmovin.ReactTHEOplayerBitmovinPackage import com.theoplayercomscore.ReactTHEOplayerComscorePackage import com.theoplayerconviva.ReactTHEOplayerConvivaPackage import com.theoplayernielsen.ReactTHEOplayerNielsenPackage -import com.theoplayeryospace.ReactTHEOplayerYospacePackage +//import com.theoplayeryospace.ReactTHEOplayerYospacePackage class MainApplication : Application(), ReactApplication { override val reactNativeHost: ReactNativeHost = @@ -22,10 +23,11 @@ class MainApplication : Application(), ReactApplication { override fun getPackages(): List = PackageList(this).packages.apply { // Packages that cannot be autolinked yet can be added manually here, for example: + add(ReactTHEOplayerBitmovinPackage()) add(ReactTHEOplayerComscorePackage()) add(ReactTHEOplayerConvivaPackage()) add(ReactTHEOplayerNielsenPackage()) - add(ReactTHEOplayerYospacePackage()) +// add(ReactTHEOplayerYospacePackage()) } override fun getJSMainModuleName(): String = "index" diff --git a/apps/e2e/android/settings.gradle b/apps/e2e/android/settings.gradle index bf22d41e..26521142 100644 --- a/apps/e2e/android/settings.gradle +++ b/apps/e2e/android/settings.gradle @@ -18,8 +18,8 @@ include ':react-native-theoplayer-analytics-nielsen' project(':react-native-theoplayer-analytics-nielsen').projectDir = new File(rootProject.projectDir, '../../../nielsen/android') include ':react-native-theoplayer-analytics-bitmovin' project(':react-native-theoplayer-analytics-bitmovin').projectDir = new File(rootProject.projectDir, '../../../bitmovin/android') -include ':react-native-theoplayer-yospace' -project(':react-native-theoplayer-yospace').projectDir = new File(rootProject.projectDir, '../../../yospace/android') +//include ':react-native-theoplayer-yospace' +//project(':react-native-theoplayer-yospace').projectDir = new File(rootProject.projectDir, '../../../yospace/android') // include ':react-native-theoplayer-analytics-adscript' // project(':react-native-theoplayer-analytics-adscript').projectDir = new File(rootProject.projectDir, '../../../adscript/android') // include ':react-native-theoplayer-analytics-gemius' diff --git a/apps/e2e/src/tests/index.ts b/apps/e2e/src/tests/index.ts index 56a5931e..acbff5bc 100644 --- a/apps/e2e/src/tests/index.ts +++ b/apps/e2e/src/tests/index.ts @@ -4,14 +4,9 @@ import AdobeEdge from './AdobeEdge.spec'; import Comscore from './Comscore.spec'; import Conviva from './Conviva.spec'; import Nielsen from './Nielsen.spec'; -import Yospace from './Yospace.spec'; import { Platform } from 'react-native'; const tests = Platform.OS === 'ios' ? [Adobe, AdobeNative, Comscore, Conviva, Nielsen] : [Adobe, AdobeNative, AdobeEdge, Comscore, Conviva, Nielsen]; -if (Platform.OS === 'android') { - tests.push(Yospace); -} - export default tests; From 729036419007d9e54bb4d12bf1ed0bd66f795638 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 13:16:19 +0100 Subject: [PATCH 25/40] Add custom menu --- apps/e2e/src/App.tsx | 49 +- .../src/components/menu/AutoPlaySubMenu.tsx | 32 + .../menu/BackgroundAudioSubMenu.tsx | 50 ++ .../e2e/src/components/menu/ConnectorMenu.tsx | 31 + .../src/components/menu/ConnectorSubMenu.tsx | 25 + .../e2e/src/components/menu/CustomSubMenu.tsx | 87 +++ apps/e2e/src/components/menu/PipSubMenu.tsx | 47 ++ .../menu/RenderingTargetSubMenu.tsx | 36 ++ apps/e2e/src/components/menu/Source.ts | 7 + .../src/components/menu/SourceMenuButton.tsx | 40 ++ apps/e2e/src/components/menu/sources.json | 590 ++++++++++++++++++ apps/e2e/src/res/ConnectorSvg.tsx | 18 + .../bitmovin/ReactTHEOplayerBitmovinModule.kt | 6 + 13 files changed, 1001 insertions(+), 17 deletions(-) create mode 100644 apps/e2e/src/components/menu/AutoPlaySubMenu.tsx create mode 100644 apps/e2e/src/components/menu/BackgroundAudioSubMenu.tsx create mode 100644 apps/e2e/src/components/menu/ConnectorMenu.tsx create mode 100644 apps/e2e/src/components/menu/ConnectorSubMenu.tsx create mode 100644 apps/e2e/src/components/menu/CustomSubMenu.tsx create mode 100644 apps/e2e/src/components/menu/PipSubMenu.tsx create mode 100644 apps/e2e/src/components/menu/RenderingTargetSubMenu.tsx create mode 100644 apps/e2e/src/components/menu/Source.ts create mode 100644 apps/e2e/src/components/menu/SourceMenuButton.tsx create mode 100644 apps/e2e/src/components/menu/sources.json create mode 100644 apps/e2e/src/res/ConnectorSvg.tsx diff --git a/apps/e2e/src/App.tsx b/apps/e2e/src/App.tsx index e1d09aa7..6a8934e8 100644 --- a/apps/e2e/src/App.tsx +++ b/apps/e2e/src/App.tsx @@ -33,6 +33,14 @@ import {convivaConfig} from "./constants/conviva.config"; import {convivaMetadata} from "./constants/conviva.metadata"; import { useBitmovin } from '@theoplayer/react-native-analytics-bitmovin'; import { bitmovinConfig, bitmovinDefaultMetadata } from './constants/bitmovin.config'; +import { BackgroundAudioSubMenu } from './components/menu/BackgroundAudioSubMenu'; +import { PiPSubMenu } from './components/menu/PipSubMenu'; +import { AutoPlaySubMenu } from './components/menu/AutoPlaySubMenu'; +import { RenderingTargetSubMenu } from './components/menu/RenderingTargetSubMenu'; +import { SourceMenuButton, SOURCES } from './components/menu/SourceMenuButton'; +import { ConnectorSvg } from './res/ConnectorSvg'; +import { ConnectorSubMenu } from './components/menu/ConnectorSubMenu'; +import { ConnectorsMenuButton } from './components/menu/ConnectorMenu'; const playerConfig: PlayerConfiguration = { // Get your THEOplayer license from https://portal.theoplayer.com/ @@ -54,7 +62,20 @@ export default function App() { const isDarkMode = useColorScheme() === 'dark'; const [, initConviva] = useConviva(convivaMetadata, convivaConfig); - const [, initBitmovin] = useBitmovin(bitmovinConfig); + const [bitmovin, initBitmovin] = useBitmovin(bitmovinConfig); + + const onBitmovinProgramChange = () => { + bitmovin.current?.programChange({ + title: 'New title', + }); + }; + + const onBitmovinUpdateCustomData = () => { + bitmovin.current?.updateCustomData({ + customData0: 'customData0 value', + customData1: 'customData1 value', + }); + }; const onPlayerReady = (player: THEOplayer) => { setPlayer(player); @@ -76,22 +97,7 @@ export default function App() { player.muted = true; player.autoplay = true; - player.source = { - sources: [ - { - src: 'https://cdn.theoplayer.com/video/sintel/nosubs.m3u8', - type: 'application/x-mpegurl', - }, - ], - metadata: { - title: 'Sintel', - subtitle: 'HLS - Sideloaded Chapters', - album: 'React-Native THEOplayer demos', - mediaUri: 'https://theoplayer.com', - displayIconUri: 'https://cdn.theoplayer.com/video/sintel_old/poster.jpg', - artist: 'THEOplayer', - } - }; + player.source = SOURCES[0].source; player.backgroundAudioConfiguration = { enabled: true }; player.pipConfiguration = { startsAutomatically: true }; @@ -118,11 +124,20 @@ export default function App() { + + + + + {/*Note: quality selection is not available on iOS */} + + + + {Platform.OS === 'android' && } diff --git a/apps/e2e/src/components/menu/AutoPlaySubMenu.tsx b/apps/e2e/src/components/menu/AutoPlaySubMenu.tsx new file mode 100644 index 00000000..7144f8cd --- /dev/null +++ b/apps/e2e/src/components/menu/AutoPlaySubMenu.tsx @@ -0,0 +1,32 @@ +import { CustomSubMenu, Option } from './CustomSubMenu'; +import * as React from 'react'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { useContext } from 'react'; +import { PlayerContext } from '@theoplayer/react-native-ui'; + +export interface PipSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; +} + +export function AutoPlaySubMenu(props?: PipSubMenuProps) { + const { player } = useContext(PlayerContext); + + return ( + ) => { + player.autoplay = option.value; + }} + currentOption={() => player.autoplay ?? false} + /> + ); +} diff --git a/apps/e2e/src/components/menu/BackgroundAudioSubMenu.tsx b/apps/e2e/src/components/menu/BackgroundAudioSubMenu.tsx new file mode 100644 index 00000000..8c742ad0 --- /dev/null +++ b/apps/e2e/src/components/menu/BackgroundAudioSubMenu.tsx @@ -0,0 +1,50 @@ +import { CustomSubMenu, Option } from './CustomSubMenu'; +import * as React from 'react'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { useContext } from 'react'; +import { PlayerContext } from '@theoplayer/react-native-ui'; + +export interface BackgroundAudioSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; +} + +/** + * A button component that opens a backgroundAudio selection menu for the `react-native-theoplayer` UI. + */ +export const BackgroundAudioSubMenu = (props?: BackgroundAudioSubMenuProps) => { + const { player } = useContext(PlayerContext); + + return ( + <> + ) => { + player.backgroundAudioConfiguration = { ...player.backgroundAudioConfiguration, enabled: option.value }; + }} + currentOption={() => player.backgroundAudioConfiguration.enabled ?? false} + /> + ) => { + player.backgroundAudioConfiguration = { ...player.backgroundAudioConfiguration, shouldResumeAfterInterruption: option.value }; + }} + currentOption={() => player.backgroundAudioConfiguration.shouldResumeAfterInterruption ?? false} + /> + + ); +}; diff --git a/apps/e2e/src/components/menu/ConnectorMenu.tsx b/apps/e2e/src/components/menu/ConnectorMenu.tsx new file mode 100644 index 00000000..78fc213b --- /dev/null +++ b/apps/e2e/src/components/menu/ConnectorMenu.tsx @@ -0,0 +1,31 @@ +import { MenuButton, MenuView, ScrollableMenu } from '@theoplayer/react-native-ui'; +import React, { type ReactNode } from 'react'; +import { StyleProp, ViewStyle } from 'react-native'; +import { ConnectorSvg } from '../../res/ConnectorSvg'; + +export interface ConnectorMenuButtonProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; + + /** + * The icon component used in the button. + */ + icon?: ReactNode; +} + +export const ConnectorsMenuButton = (props: React.PropsWithChildren) => { + const { children, menuStyle, icon } = props; + + // Do not render an empty menu + if (React.Children.toArray(children).length === 0) { + return <>; + } + + const createMenu = () => { + return } />; + }; + + return } menuConstructor={createMenu} />; +}; diff --git a/apps/e2e/src/components/menu/ConnectorSubMenu.tsx b/apps/e2e/src/components/menu/ConnectorSubMenu.tsx new file mode 100644 index 00000000..e43b549d --- /dev/null +++ b/apps/e2e/src/components/menu/ConnectorSubMenu.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import { StyleProp, ViewStyle } from 'react-native'; +import { MenuRadioButton } from '@theoplayer/react-native-ui'; + +export interface ConnectorSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; + + title: string; + + onPress: () => void; +} + +export function ConnectorSubMenu(props?: ConnectorSubMenuProps) { + return ( + + ); +} diff --git a/apps/e2e/src/components/menu/CustomSubMenu.tsx b/apps/e2e/src/components/menu/CustomSubMenu.tsx new file mode 100644 index 00000000..b61f5374 --- /dev/null +++ b/apps/e2e/src/components/menu/CustomSubMenu.tsx @@ -0,0 +1,87 @@ +import React, { useState } from 'react'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { MenuRadioButton, MenuView, ScrollableMenu, SubMenuWithButton } from '@theoplayer/react-native-ui'; + +export interface Option { + label: string; + value: T; +} + +export interface CustomSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; + + /** + * The label displayed in the menu. + */ + label: string; + + /** + * The title displayed when opening the menu. + */ + title: string; + + /** + * List of available options. + */ + options: Option[]; + + /** + * Get the current active option. + */ + currentOption: () => T; + + /** + * Called when a new option was selected. + */ + onOptionSelected?: (option: Option) => void; +} + +/** + * A button component that opens a custom selection menu for the `react-native-theoplayer` UI. + */ +export function CustomSubMenu(props: CustomSubMenuProps) { + const { options, label } = props; + const currentLabel = options.find((v) => v.value == props.currentOption())?.label ?? ''; + const createMenu = () => { + return ; + }; + return ; +} + +function CustomSelectionView(props: CustomSubMenuProps) { + const { menuStyle, options } = props; + const currentOption = options.find((v) => v.value == props.currentOption()); + const [selectedOption, setSelectedOption] = useState | undefined>(currentOption); + + const onSelectOption = (id: number | undefined): void => { + if (id !== undefined) { + const newSelection = id < options.length ? options[id] : undefined; + if (newSelection) { + setSelectedOption(newSelection); + props.onOptionSelected?.(newSelection); + } + } + }; + + return ( + ( + + ))} + /> + } + /> + ); +} diff --git a/apps/e2e/src/components/menu/PipSubMenu.tsx b/apps/e2e/src/components/menu/PipSubMenu.tsx new file mode 100644 index 00000000..e1f3c6f2 --- /dev/null +++ b/apps/e2e/src/components/menu/PipSubMenu.tsx @@ -0,0 +1,47 @@ +import { CustomSubMenu, Option } from './CustomSubMenu'; +import * as React from 'react'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { useContext } from 'react'; +import { PlayerContext } from '@theoplayer/react-native-ui'; + +export interface PipSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; +} + +export function PiPSubMenu(props?: PipSubMenuProps) { + const { player } = useContext(PlayerContext); + + return ( + <> + ) => { + player.pipConfiguration = { ...player.pipConfiguration, startsAutomatically: option.value }; + }} + currentOption={() => player.pipConfiguration.startsAutomatically ?? false} + /> + ) => { + player.pipConfiguration = { ...player.pipConfiguration, retainPipOnSourceChange: option.value }; + }} + currentOption={() => player.pipConfiguration.retainPipOnSourceChange ?? false} + /> + + ); +} diff --git a/apps/e2e/src/components/menu/RenderingTargetSubMenu.tsx b/apps/e2e/src/components/menu/RenderingTargetSubMenu.tsx new file mode 100644 index 00000000..cdb5e28c --- /dev/null +++ b/apps/e2e/src/components/menu/RenderingTargetSubMenu.tsx @@ -0,0 +1,36 @@ +import { CustomSubMenu, Option } from './CustomSubMenu'; +import { RenderingTarget } from 'react-native-theoplayer'; +import * as React from 'react'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { useContext } from 'react'; +import { PlayerContext } from '@theoplayer/react-native-ui'; + +export interface RenderingTargetSubMenuProps { + /** + * Overrides for the style of the menu. + */ + menuStyle?: StyleProp; +} + +export function RenderingTargetSubMenu(props?: RenderingTargetSubMenuProps) { + const { player } = useContext(PlayerContext); + + return ( + ) => { + player.renderingTarget = option.value; + }} + currentOption={() => player.renderingTarget ?? RenderingTarget.SURFACE_VIEW} + /> + ); +} diff --git a/apps/e2e/src/components/menu/Source.ts b/apps/e2e/src/components/menu/Source.ts new file mode 100644 index 00000000..19ddd16e --- /dev/null +++ b/apps/e2e/src/components/menu/Source.ts @@ -0,0 +1,7 @@ +import type { SourceDescription } from 'react-native-theoplayer'; + +export interface Source { + name: string; + os: string[]; + source: SourceDescription; +} diff --git a/apps/e2e/src/components/menu/SourceMenuButton.tsx b/apps/e2e/src/components/menu/SourceMenuButton.tsx new file mode 100644 index 00000000..e6a4cd09 --- /dev/null +++ b/apps/e2e/src/components/menu/SourceMenuButton.tsx @@ -0,0 +1,40 @@ +import React, { useContext, useState } from 'react'; +import { Platform } from 'react-native'; +import { ListSvg, MenuButton, MenuRadioButton, MenuView, PlayerContext, ScrollableMenu } from '@theoplayer/react-native-ui'; +import type { Source } from './Source'; +import ALL_SOURCES from './sources.json'; + +export const SOURCES = ALL_SOURCES.filter((source) => source.os.indexOf(Platform.OS) >= 0) as Source[]; + +export const SourceMenuButton = () => { + if (!(SOURCES && SOURCES.length > 0)) { + return <>; + } + const createMenu = () => { + return ; + }; + return } menuConstructor={createMenu} />; +}; + +export const SourceMenuView = () => { + const { player } = useContext(PlayerContext); + const selectedSource = SOURCES.find((source) => source.source === player.source); + const [localSourceId, setLocalSourceId] = useState(selectedSource ? SOURCES.indexOf(selectedSource) : undefined); + + const selectSource = (id: number | undefined) => { + setLocalSourceId(id); + player.source = id !== undefined ? SOURCES[id].source : undefined; + }; + return ( + ( + + ))} + /> + } + /> + ); +}; diff --git a/apps/e2e/src/components/menu/sources.json b/apps/e2e/src/components/menu/sources.json new file mode 100644 index 00000000..c0448af1 --- /dev/null +++ b/apps/e2e/src/components/menu/sources.json @@ -0,0 +1,590 @@ +[ + { + "name": "HLS - Sideloaded Chapters", + "os": ["ios", "android", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/sintel/nosubs.m3u8", + "type": "application/x-mpegurl" + } + ], + "metadata": { + "title": "Sintel", + "subtitle": "HLS - Sideloaded Chapters", + "album": "React-Native THEOplayer demos", + "mediaUri": "https://theoplayer.com", + "displayIconUri": "https://cdn.theoplayer.com/video/sintel_old/poster.jpg", + "artist": "THEOplayer" + }, + "textTracks": [{ + "kind": "chapters", + "src": "https://cdn.theoplayer.com/video/sintel/chapters.vtt", + "format": "webvtt", + "srclang": "en", + "label": "Chapters", + "default": true + }] + } + }, + { + "name": "DASH - Thumbnails in manifest", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/dash/bbb_30fps/bbb_with_multiple_tiled_thumbnails.mpd", + "type": "application/dash+xml" + } + ], + "poster": "https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg", + "metadata": { + "title": "Big Buck Bunny", + "subtitle": "DASH - Thumbnails in manifest", + "album": "React-Native THEOplayer demos", + "mediaUri": "https://theoplayer.com", + "displayIconUri": "https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg", + "artist": "THEOplayer" + } + } + }, + { + "name": "DASH - Thumbnails Side-loaded", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/dash/big_buck_bunny/BigBuckBunny_10s_simple_2014_05_09.mpd", + "type": "application/dash+xml" + } + ], + "textTracks": [ + { + "default": true, + "src": "https://cdn.theoplayer.com/dash/theoplayer/thumbnails/big_buck_bunny_thumbnails.vtt", + "label": "thumbnails", + "kind": "metadata" + } + ] + } + }, + { + "name": "DASH - VOD - Clear", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/dash/webvtt-embedded-in-isobmff/Manifest.mpd", + "type": "application/dash+xml" + } + ] + } + }, + { + "name": "DASH - VOD - ezDRM (Widevine)", + "os": ["android", "web"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/dash/tos-dash-widevine/tos_h264_main.mpd", + "type": "application/dash+xml", + "contentProtection": { + "widevine": { + "licenseAcquisitionURL": "https://widevine-dash.ezdrm.com/proxy?pX=62448C" + } + } + } + } + }, + { + "name": "DASH - VOD - keyOS (Widevine)", + "os": ["android", "web"], + "source": { + "sources": { + "src": "https://d2jl6e4h8300i8.cloudfront.net/netflix_meridian/4k-18.5!9/keyos-logo/g180-avc_a2.0-vbr-aac-128k/r30/dash-wv-pr/stream.mpd", + "type": "application/dash+xml", + "contentProtection": { + "integration": "keyos_buydrm", + "integrationParameters": { + "x-keyos-authorization": "PEtleU9TQXV0aGVudGljYXRpb25YTUw+PERhdGE+PEdlbmVyYXRpb25UaW1lPjIwMTYtMTEtMTkgMDk6MzQ6MDEuOTkyPC9HZW5lcmF0aW9uVGltZT48RXhwaXJhdGlvblRpbWU+MjAyNi0xMS0xOSAwOTozNDowMS45OTI8L0V4cGlyYXRpb25UaW1lPjxVbmlxdWVJZD4wZmZmMTk3YWQzMzQ0ZTMyOWU0MTA0OTIwMmQ5M2VlYzwvVW5pcXVlSWQ+PFJTQVB1YktleUlkPjdlMTE0MDBjN2RjY2QyOWQwMTc0YzY3NDM5N2Q5OWRkPC9SU0FQdWJLZXlJZD48V2lkZXZpbmVQb2xpY3kgZmxfQ2FuUGxheT0idHJ1ZSIgZmxfQ2FuUGVyc2lzdD0iZmFsc2UiIC8+PFdpZGV2aW5lQ29udGVudEtleVNwZWMgVHJhY2tUeXBlPSJIRCI+PFNlY3VyaXR5TGV2ZWw+MTwvU2VjdXJpdHlMZXZlbD48L1dpZGV2aW5lQ29udGVudEtleVNwZWM+PEZhaXJQbGF5UG9saWN5IC8+PExpY2Vuc2UgdHlwZT0ic2ltcGxlIiAvPjwvRGF0YT48U2lnbmF0dXJlPk1sNnhkcU5xc1VNalNuMDdicU8wME15bHhVZUZpeERXSHB5WjhLWElBYlAwOE9nN3dnRUFvMTlYK1c3MDJOdytRdmEzNFR0eDQydTlDUlJPU1NnREQzZTM4aXE1RHREcW9HelcwS2w2a0JLTWxHejhZZGRZOWhNWmpPTGJkNFVkRnJUbmxxU21raC9CWnNjSFljSmdaUm5DcUZIbGI1Y0p0cDU1QjN4QmtxMUREZUEydnJUNEVVcVJiM3YyV1NueUhGeVZqWDhCR3o0ZWFwZmVFeDlxSitKbWI3dUt3VjNqVXN2Y0Fab1ozSHh4QzU3WTlySzRqdk9Wc1I0QUd6UDlCc3pYSXhKd1ZSZEk3RXRoMjhZNXVEQUVZVi9hZXRxdWZiSXIrNVZOaE9yQ2JIVjhrR2praDhHRE43dC9nYWh6OWhVeUdOaXRqY2NCekJvZHRnaXdSUT09PC9TaWduYXR1cmU+PC9LZXlPU0F1dGhlbnRpY2F0aW9uWE1MPg==" + }, + "widevine": { + "licenseAcquisitionURL": "https://widevine.keyos.com/api/v4/getLicense" + } + } + } + } + }, + { + "name": "DASH - Live - Clear", + "os": ["android", "web"], + "source": { + "sources": { + "src": "https://livesim.dashif.org/livesim/chunkdur_1/ato_7/testpic4_8s/Manifest.mpd" + } + } + }, + { + "name": "DASH - CSAI - Google IMA pre-roll", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/dash/webvtt-embedded-in-isobmff/Manifest.mpd", + "type": "application/dash+xml" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": { + "src": "https://cdn.theoplayer.com/demos/ads/vast/dfp-preroll-no-skip.xml" + } + } + ] + } + }, + { + "name": "DASH - CSAI - Google IMA mid-roll VAST", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://contentserver.prudentgiraffe.com/videos/dash/webvtt-embedded-in-isobmff/Manifest.mpd", + "type": "application/dash+xml" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": { + "src": "https://contentserver.prudentgiraffe.com/ads/vast-skippable.xml" + }, + "timeOffset": 10 + } + ] + } + }, + { + "name": "DASH - CSAI - Google IMA mid-roll VMAP", + "os": ["android", "web"], + "source": { + "sources": [ + { + "src": "https://contentserver.prudentgiraffe.com/videos/dash/webvtt-embedded-in-isobmff/Manifest.mpd", + "type": "application/dash+xml" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": { + "src": "https://contentserver.prudentgiraffe.com/ads/double-midroll-mergeable-adbreak.xml" + } + } + ] + } + }, + { + "name": "HLS - VOD - Clear - The Venture Bros", + "os": ["ios", "android", "web"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/adultswim/clip.m3u8", + "type": "application/x-mpegurl" + }, + "poster": "https://cdn.theoplayer.com/video/adultswim/poster.png", + "metadata": { + "title": "The Venture Bros", + "subtitle": "Adult Swim", + "album": "React-Native THEOplayer demos", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "THEOplayer", + "type": "tv-show", + "releaseDate": "november 29th", + "releaseYear": 1997 + } + } + }, + { + "name": "THEOlive test", + "os": ["web", "ios", "android"], + "source": { + "sources": [ + { + "src": "9lwkudxeyjwwm132pukwwhhtk", + "type": "theolive", + "contentProtection": { + "queryParameters": { + "param1": "value1" + } + } + } + ], + "metadata": { + "title": "THEOlive NFL demo - test", + "mediaUri": "https://theoplayer.com", + "artist": "THEOplayer" + } + } + }, + { + "name": "HLS - VOD - Clear - DateRange Metadata", + "os": ["ios", "web", "android"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/star_wars_episode_vii-the_force_awakens_official_comic-con_2015_reel_(2015)/index-daterange.m3u8", + "type": "application/x-mpegurl" + }, + "metadata": { + "title": "Star Wars Episode VII - The Force Awakens Official Comic-Con 2015 Reel", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png" + } + } + }, + { + "name": "HLS - LIVE - Clear", + "os": ["ios", "android", "web"], + "source": { + "sources": { + "src": "https://ireplay.tv/test/blender.m3u8", + "type": "application/x-mpegurl" + }, + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-640x640.png", + "metadata": { + "title": "Blender", + "subtitle": "Test stream", + "album": "React-Native demos", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "THEOplayer", + "type": "tv-show", + "releaseDate": "november 30th", + "releaseYear": 1997 + } + } + }, + { + "name": "HLS - VOD - Clear - bipbop (id3 meta)", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8", + "type": "application/x-mpegurl" + }, + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-1200x675.png", + "metadata": { + "title": "Bipbop", + "subtitle": "Bipbop Subtitle", + "album": "Bipbop Album", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "Apple" + } + } + }, + { + "name": "HLS - VOD - Clear - elephants-dream (id3 meta)", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/elephants-dream/playlist-single-audio.m3u8", + "type": "application/x-mpegurl" + }, + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-1200x675.png", + "metadata": { + "title": "Elephants Dream", + "subtitle": "Elephants Dream Subtitle", + "album": "Elephants Dream Album", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "The elephant" + } + } + }, + { + "name": "HLS - CSAI - Google IMA pre-roll", + "os": ["ios", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/elephants-dream/playlistCorrectionENG.m3u8", + "type": "application/x-mpegurl" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": "https://cdn.theoplayer.com/demos/ads/vast/dfp-preroll-no-skip.xml" + } + ], + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-1200x675.png", + "metadata": { + "title": "Elephants Dream with Preroll", + "subtitle": "Elephants Dream with Preroll Subtitle", + "album": "Elephants Album", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "The Dream" + } + } + }, + { + "name": "HLS - SGAI (THEOads)", + "os": ["web"], + "source": { + "sources": { + "src": "https://cluster.dev.theostream.live/nfl-unified-channel/hls/k8s/live/scte35.isml/.m3u8", + "type": "application/x-mpegurl", + "hlsDateRange": true + }, + "ads": [ + { + "integration": "theoads", + "networkCode": "51636543", + "customAssetKey": "nfl-sgai-demo", + "backdropDoubleBox": "https://demo.theoads.live/img/THEOads_double_box.svg", + "backdropLShape": "https://demo.theoads.live/img/THEOads_L_Shape.svg" + } + ] + } + }, + { + "name": "HLS - CSAI - Google IMA mid-roll VAST", + "os": ["ios", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/elephants-dream/playlistCorrectionENG.m3u8", + "type": "application/x-mpegurl" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": { + "src": "https://contentserver.prudentgiraffe.com/ads/vast-skippable.xml" + }, + "timeOffset": 10 + } + ], + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-1200x675.png", + "metadata": { + "title": "Elephants Dream with Midroll", + "subtitle": "Elephants Dream with Midroll Subtitle", + "album": "Ellies Album", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "Ellie" + } + } + }, + { + "name": "HLS - CSAI - Google IMA VMAP", + "os": ["ios", "web"], + "source": { + "sources": [ + { + "src": "https://cdn.theoplayer.com/video/elephants-dream/playlistCorrectionENG.m3u8", + "type": "application/x-mpegurl" + } + ], + "ads": [ + { + "integration": "google-ima", + "sources": { + "src": "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpodbumper&cmsid=496&vid=short_onecue&correlator=" + } + } + ], + "poster": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-1200x675.png", + "metadata": { + "title": "Elephants Dream with VMAP", + "subtitle": "Elephants Dream with VMAP Subtitle", + "album": "Ellies Album", + "displayIconUri": "https://cdn.theoplayer.com/react-native-theoplayer/temp/THEOPlayer-200x200.png", + "artist": "Ellie" + } + } + }, + { + "name": "DASH - SSAI - Google DAI", + "os": ["android", "web"], + "source": { + "sources": { + "type": "application/dash+xml", + "ssai": { + "integration": "google-dai", + "availabilityType": "vod", + "contentSourceID": "2474148", + "videoID": "bbb-clear" + } + } + } + }, + { + "name": "HLS - SSAI - Google DAI - VOD", + "os": ["ios", "web"], + "source": { + "sources": { + "ssai": { + "integration": "google-dai", + "availabilityType": "vod", + "contentSourceID": "2548831", + "videoID": "tears-of-steel" + } + } + } + }, + { + "name": "HLS - SSAI - Google DAI - LIVE", + "os": ["ios", "web"], + "source": { + "sources": { + "ssai": { + "integration": "google-dai", + "availabilityType": "live", + "assetKey": "sN_IYUG8STe1ZzhIIE_ksA" + } + } + } + }, + { + "name": "HLS - VOD/Thumbnails - Clear - Big Buck Bunny", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny.m3u8", + "type": "application/x-mpegurl" + }, + "poster": "https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg", + "metadata": { + "title": "The Title", + "subtitle": "The Subtitle", + "album": "Album", + "displayIconUri": "https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg", + "artist": "Artist" + }, + "textTracks": [ + { + "default": true, + "src": "https://cdn.theoplayer.com/dash/theoplayer/thumbnails/big_buck_bunny_thumbnails.vtt", + "label": "thumbnails", + "kind": "metadata", + "format": "webvtt", + "srclang": "en" + } + ] + } + }, + { + "name": "HLS - VOD - ezDRM (FairPlay)", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://fps.ezdrm.com/demo/video/ezdrm.m3u8", + "type": "application/x-mpegurl", + "contentProtection": { + "integration": "customEzdrm", + "fairplay": { + "certificateURL": "https://fps.ezdrm.com/demo/video/eleisure.cer", + "licenseAcquisitionURL": "https://fps.ezdrm.com/api/licenses/09cc0377-6dd4-40cb-b09d-b582236e70fe" + } + } + } + } + }, + { + "name": "HLS - VOD - keyOS (FairPlay)", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://d2jl6e4h8300i8.cloudfront.net/netflix_meridian/4k-19.5!9/keyos-logo/g180-avc_a2.0-vbr-aac-128k/r30/hls-fp/master.m3u8", + "type": "application/x-mpegurl", + "contentProtection": { + "integration": "keyos_buydrm", + "integrationParameters": { + "x-keyos-authorization": "PEtleU9TQXV0aGVudGljYXRpb25YTUw+PERhdGE+PEdlbmVyYXRpb25UaW1lPjIwMTYtMTEtMTkgMDk6MzQ6MDEuOTkyPC9HZW5lcmF0aW9uVGltZT48RXhwaXJhdGlvblRpbWU+MjAyNi0xMS0xOSAwOTozNDowMS45OTI8L0V4cGlyYXRpb25UaW1lPjxVbmlxdWVJZD4wZmZmMTk3YWQzMzQ0ZTMyOWU0MTA0OTIwMmQ5M2VlYzwvVW5pcXVlSWQ+PFJTQVB1YktleUlkPjdlMTE0MDBjN2RjY2QyOWQwMTc0YzY3NDM5N2Q5OWRkPC9SU0FQdWJLZXlJZD48V2lkZXZpbmVQb2xpY3kgZmxfQ2FuUGxheT0idHJ1ZSIgZmxfQ2FuUGVyc2lzdD0iZmFsc2UiIC8+PFdpZGV2aW5lQ29udGVudEtleVNwZWMgVHJhY2tUeXBlPSJIRCI+PFNlY3VyaXR5TGV2ZWw+MTwvU2VjdXJpdHlMZXZlbD48L1dpZGV2aW5lQ29udGVudEtleVNwZWM+PEZhaXJQbGF5UG9saWN5IC8+PExpY2Vuc2UgdHlwZT0ic2ltcGxlIiAvPjwvRGF0YT48U2lnbmF0dXJlPk1sNnhkcU5xc1VNalNuMDdicU8wME15bHhVZUZpeERXSHB5WjhLWElBYlAwOE9nN3dnRUFvMTlYK1c3MDJOdytRdmEzNFR0eDQydTlDUlJPU1NnREQzZTM4aXE1RHREcW9HelcwS2w2a0JLTWxHejhZZGRZOWhNWmpPTGJkNFVkRnJUbmxxU21raC9CWnNjSFljSmdaUm5DcUZIbGI1Y0p0cDU1QjN4QmtxMUREZUEydnJUNEVVcVJiM3YyV1NueUhGeVZqWDhCR3o0ZWFwZmVFeDlxSitKbWI3dUt3VjNqVXN2Y0Fab1ozSHh4QzU3WTlySzRqdk9Wc1I0QUd6UDlCc3pYSXhKd1ZSZEk3RXRoMjhZNXVEQUVZVi9hZXRxdWZiSXIrNVZOaE9yQ2JIVjhrR2praDhHRE43dC9nYWh6OWhVeUdOaXRqY2NCekJvZHRnaXdSUT09PC9TaWduYXR1cmU+PC9LZXlPU0F1dGhlbnRpY2F0aW9uWE1MPg==" + }, + "fairplay": { + "licenseAcquisitionURL": "https://fp-keyos.licensekeyserver.com/getkey/", + "certificateURL": "https://fp-keyos.licensekeyserver.com/cert/7e11400c7dccd29d0174c674397d99dd.der" + } + } + } + } + }, + { + "name": "MP4 - Elephants Dream", + "os": ["ios", "web", "android"], + "source": { + "sources": { + "src": "https://cdn.theoplayer.com/video/elephants-dream.mp4" + } + } + }, + { + "name": "MP3 - SoundHelix Song1", + "os": ["ios", "web"], + "source": { + "sources": { + "src": "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3" + } + } + }, + { + "name": "HLS - THEOads", + "os": ["ios", "web", "android"], + "source": { + "sources": { + "src": "https://cluster.dev.theostream.live/nfl-unified-channel/hls/k8s/live/scte35.isml/.m3u8", + "type": "application/x-mpegurl", + "hlsDateRange": true + }, + "ads": [ + { + "integration": "theoads", + "networkCode": "51636543", + "customAssetKey": "nfl-sgai-demo", + "backdropDoubleBox": "https://demo.theoads.live/img/THEOads_double_box.svg", + "backdropLShape": "https://demo.theoads.live/img/THEOads_L_Shape.svg" + } + ] + } + }, + { + "name": "Millicast", + "os": ["ios", "web"], + "source": { + "sources": [ + { + "type": "millicast", + "src": "multiview", + "streamAccountId": "k9Mwad" + } + ], + "metadata": { + "title": "Millicast", + "subtitle": "Millicast demo", + "album": "React-Native THEOplayer demos", + "mediaUri": "https://theoplayer.com", + "artist": "THEOplayer" + } + } + }, + { + "name": "Millicast", + "os": ["android"], + "source": { + "sources": [ + { + "type": "millicast", + "src": "multiview", + "streamAccountId": "k9Mwad", + "apiUrl": "https://director.millicast.com/api/director/subscribe" + } + ], + "metadata": { + "title": "Millicast", + "subtitle": "Millicast demo", + "album": "React-Native THEOplayer demos", + "mediaUri": "https://theoplayer.com", + "artist": "THEOplayer" + } + } + } +] diff --git a/apps/e2e/src/res/ConnectorSvg.tsx b/apps/e2e/src/res/ConnectorSvg.tsx new file mode 100644 index 00000000..81d004e0 --- /dev/null +++ b/apps/e2e/src/res/ConnectorSvg.tsx @@ -0,0 +1,18 @@ +import type { SvgProps } from 'react-native-svg'; +import Svg, { Path } from 'react-native-svg'; +import React from 'react'; +import { SvgContext } from '@theoplayer/react-native-ui'; + +export const ConnectorSvg = (props: SvgProps) => { + return ( + + {(context) => ( + <> + + + + + )} + + ); +}; diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt index 52d85bce..09268dec 100644 --- a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt @@ -46,6 +46,12 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : bitmovinConnectors[tag]?.customData = BitmovinAdapter.parseCustomData(customData) } + @ReactMethod + fun programChange(tag: Int, sourceMetadata: ReadableMap) { + val t = "NYI" +// bitmovinConnectors[tag]?.programChange(BitmovinAdapter.parseSourceMetadata(sourceMetadata)) + } + @ReactMethod fun sendCustomDataEvent(tag: Int, customData: ReadableMap) { bitmovinConnectors[tag]?.sendCustomDataEvent(BitmovinAdapter.parseCustomData(customData)) From 0a7d2fc53017bfd2664bc3b9cf9d94f599282247 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 13:34:43 +0100 Subject: [PATCH 26/40] Update readme --- bitmovin/README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/bitmovin/README.md b/bitmovin/README.md index 3b8ddee3..c14a6b9f 100644 --- a/bitmovin/README.md +++ b/bitmovin/README.md @@ -14,4 +14,85 @@ npm install @theoplayer/react-native-analytics-bitmovin ### Configuring the connector -# TODO: Add usage instructions +Create the connector using the `useBitmovin` hook with the initial configuration. + +Once the player is ready, initialize the connector by calling the `initBitmovin` function with the `THEOplayer` +instance and the **default metadata**, which contains properties that do not change during the session. + +Finally, when the player source is set, update the **source metadata** by calling the `updateSourceMetadata` function. + +```tsx +import { + useBitmovin, + AnalyticsConfig, + DefaultMetadata, + SourceMetadata +} from '@theoplayer/react-native-analytics-bitmovin'; + +const bitmovinConfig: AnalyticsConfig = { + licenseKey: 'license-key-here', + logLevel: 'DEBUG' +} + +const defaultMetadata: DefaultMetadata = { + cdnProvider: 'akamai', + customUserId: 'custom-user-id-1234', + customData: { + customData0: 'value0', + customData1: 'value1' + } +}; + +const sourceMetadata: SourceMetadata = { + title: 'Sample Video', + videoId: 'video-1234', + cdnProvider: 'akamai', + path: '/home/videos/sample-video', + isLive: false, + customData: { + customData10: 'value10', + customData11: 'value11' + } +} + +const App = () => { + const [bitmovin, initBitmovin] = useBitmovin(bitmovinConfig); + + const onPlayerReady = (player: THEOplayer) => { + // Initialize connector with player & default metadata. + initBitmovin(player, defaultMetadata); + player.source = {/*...*/} + + // Update source metadata. + bitmovin.updateSourceMetadata(sourceMetadata); + } + + return (); +} +``` + +### Dynamically updating custom data + +The connector allows updating the **custom data** at any time during the playback session: + +```tsx +bitmovin.updateCustomData({ + customData0: 'newValue0', + customData1: 'newValue1' +}); +``` + +### Updating source metadata during a live stream + +The connector allows dynamically updating the **source metadata**, for example during a live stream when +the program changes: + +```tsx +bitmovin.programChange({ + title: 'New Live Program', + videoId: 'live-program-5678', + customData: { + customData10: 'newValue10' + } +}); +``` From e89f7cef0f89af42919ae56c92d60da4b088f443 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 14:59:09 +0100 Subject: [PATCH 27/40] Add support for web --- apps/e2e/index.web.tsx | 9 + apps/e2e/package-lock.json | 957 ++++- apps/e2e/package.json | 7 + apps/e2e/src/App.tsx | 1 - apps/e2e/web/public/index.html | 21 + apps/e2e/web/public/style.css | 17 + apps/e2e/web/public/ui.css | 5123 ++++++++++++++++++++++++++ apps/e2e/web/stub/CastButtonStub.tsx | 7 + apps/e2e/web/stub/Config.ts | 3 + apps/e2e/web/stub/global.d.ts | 5 + apps/e2e/web/webpack.config.js | 142 + 11 files changed, 6290 insertions(+), 2 deletions(-) create mode 100644 apps/e2e/index.web.tsx create mode 100644 apps/e2e/web/public/index.html create mode 100644 apps/e2e/web/public/style.css create mode 100644 apps/e2e/web/public/ui.css create mode 100644 apps/e2e/web/stub/CastButtonStub.tsx create mode 100644 apps/e2e/web/stub/Config.ts create mode 100644 apps/e2e/web/stub/global.d.ts create mode 100644 apps/e2e/web/webpack.config.js diff --git a/apps/e2e/index.web.tsx b/apps/e2e/index.web.tsx new file mode 100644 index 00000000..c0191c41 --- /dev/null +++ b/apps/e2e/index.web.tsx @@ -0,0 +1,9 @@ +import React, { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './src/App'; + +createRoot(document.getElementById('app') as HTMLElement).render( + + + , +); diff --git a/apps/e2e/package-lock.json b/apps/e2e/package-lock.json index 3c9c2e84..428f270b 100644 --- a/apps/e2e/package-lock.json +++ b/apps/e2e/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "dependencies": { "@theoplayer/react-native-ui": "^0.21.3", + "dotenv": "^17.2.3", "react": "19.0.0", "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", @@ -44,6 +45,7 @@ "copy-webpack-plugin": "^13.0.0", "eslint": "^8.57.1", "html-webpack-plugin": "^5.6.3", + "node-polyfill-webpack-plugin": "^4.1.0", "patch-package": "^8.0.1", "react-native-svg-web": "^1.0.9", "typescript": "5.1.6", @@ -5053,6 +5055,39 @@ "version": "2.0.6", "license": "MIT" }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/astral-regex": { "version": "1.0.0", "devOptional": true, @@ -5408,6 +5443,13 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bn.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "dev": true, + "license": "MIT" + }, "node_modules/body-parser": { "version": "1.20.3", "devOptional": true, @@ -5486,6 +5528,156 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { "version": "4.26.0", "funding": [ @@ -5550,6 +5742,20 @@ "version": "1.1.2", "license": "MIT" }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bundle-name": { "version": "4.1.0", "dev": true, @@ -5830,6 +6036,21 @@ "version": "2.0.0", "license": "MIT" }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/clean-css": { "version": "5.3.3", "dev": true, @@ -6015,6 +6236,19 @@ "version": "2.0.0", "license": "MIT" }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/content-disposition": { "version": "0.5.4", "dev": true, @@ -6166,6 +6400,60 @@ } } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-fetch": { "version": "3.2.0", "license": "MIT", @@ -6186,6 +6474,33 @@ "node": ">= 8" } }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/css-in-js-utils": { "version": "3.1.0", "license": "MIT", @@ -6411,6 +6726,17 @@ "node": ">= 0.8" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destroy": { "version": "1.2.0", "license": "MIT", @@ -6424,6 +6750,25 @@ "dev": true, "license": "MIT" }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/dir-glob": { "version": "3.0.1", "dev": true, @@ -6477,6 +6822,19 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/domelementtype": { "version": "2.3.0", "funding": [ @@ -6521,6 +6879,18 @@ "tslib": "^2.0.3" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "devOptional": true, @@ -6542,6 +6912,29 @@ "version": "1.5.218", "license": "ISC" }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "8.0.0", "license": "MIT" @@ -7413,6 +7806,17 @@ "node": ">=0.8.x" } }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "node_modules/execa": { "version": "5.1.1", "devOptional": true, @@ -8221,6 +8625,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "devOptional": true, @@ -8251,6 +8680,18 @@ "hermes-estree": "0.25.1" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "dev": true, @@ -8494,6 +8935,13 @@ } } }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "license": "MIT", @@ -8670,6 +9118,23 @@ "node": ">= 10" } }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "dev": true, @@ -8932,6 +9397,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "dev": true, @@ -9180,7 +9662,17 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-coverage": { @@ -10127,6 +10619,18 @@ "node": ">= 0.4" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/mdn-data": { "version": "2.0.14", "license": "CC0-1.0" @@ -10606,6 +11110,27 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/mime": { "version": "2.6.0", "devOptional": true, @@ -10647,6 +11172,13 @@ "dev": true, "license": "ISC" }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" + }, "node_modules/minimatch": { "version": "9.0.5", "dev": true, @@ -10771,10 +11303,99 @@ "version": "0.4.0", "license": "MIT" }, + "node_modules/node-polyfill-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-b4ei444EKkOagG/yFqojrD3QTYM5IOU1f8tn9o6uwrG4qL+brI7oVhjPVd0ZL2xy+Z6CP5bu9w8XTvlWgiXHcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-stdlib-browser": "^1.3.0", + "type-fest": "^4.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "webpack": ">=5" + } + }, + "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/node-releases": { "version": "2.0.21", "license": "MIT" }, + "node_modules/node-stdlib-browser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz", + "integrity": "sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.12.1", + "domain-browser": "4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-stream-zip": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", @@ -10849,6 +11470,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "dev": true, @@ -11084,6 +11722,13 @@ "node": ">=8" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, "node_modules/own-keys": { "version": "1.0.1", "dev": true, @@ -11151,6 +11796,13 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/param-case": { "version": "3.0.4", "dev": true, @@ -11171,6 +11823,23 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -11333,6 +12002,13 @@ "node": ">=8" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "license": "MIT", @@ -11401,6 +12077,24 @@ "node": ">=8" } }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/picocolors": { "version": "1.1.1", "license": "ISC" @@ -11624,6 +12318,16 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "dev": true, @@ -11678,6 +12382,28 @@ "node": ">= 0.10" } }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "license": "MIT", @@ -11699,6 +12425,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue": { "version": "6.0.2", "license": "MIT", @@ -11733,6 +12468,17 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "license": "MIT", @@ -12464,6 +13210,83 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/run-applescript": { "version": "7.1.0", "dev": true, @@ -12832,6 +13655,27 @@ "version": "1.2.0", "license": "ISC" }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/shallow-clone": { "version": "3.0.1", "dev": true, @@ -13083,6 +13927,30 @@ "node": ">= 0.4" } }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "devOptional": true, @@ -13478,6 +14346,19 @@ "dev": true, "license": "MIT" }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "dev": true, @@ -13534,6 +14415,21 @@ "version": "1.0.5", "license": "BSD-3-Clause" }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "license": "MIT", @@ -13605,6 +14501,13 @@ "dev": true, "license": "0BSD" }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "license": "MIT" + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, @@ -13861,10 +14764,45 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/url-polyfill": { "version": "1.1.14", "license": "MIT" }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "devOptional": true, @@ -13902,6 +14840,13 @@ "version": "1.0.1", "license": "MIT" }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/walker": { "version": "1.0.8", "license": "Apache-2.0", @@ -14664,6 +15609,16 @@ "node": ">=4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "license": "ISC", diff --git a/apps/e2e/package.json b/apps/e2e/package.json index 6a4beb4c..a005dda4 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -8,6 +8,11 @@ "test:e2e:android": "npx cavy run-android --terminal bash --mode release", "test:e2e:ios": "npx cavy run-ios --terminal bash --scheme ReactNativeTHEOplayer", "test:e2e:tvos": "npx cavy run-ios --terminal bash --scheme ReactNativeTHEOplayer-tvOS", + "android": "npx react-native run-android", + "android-release": "npx react-native run-android --mode release", + "ios": "npx react-native run-ios", + "web": "webpack-dev-server --config ./web/webpack.config.js --mode development", + "web-release": "webpack --config ./web/webpack.config.js --mode production", "lint": "eslint \"**/*.{ts,tsx}\"", "pod-install": "cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install", "pod-update": "cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod update", @@ -15,6 +20,7 @@ }, "dependencies": { "@theoplayer/react-native-ui": "^0.21.3", + "dotenv": "^17.2.3", "react": "19.0.0", "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", @@ -49,6 +55,7 @@ "copy-webpack-plugin": "^13.0.0", "eslint": "^8.57.1", "html-webpack-plugin": "^5.6.3", + "node-polyfill-webpack-plugin": "^4.1.0", "patch-package": "^8.0.1", "react-native-svg-web": "^1.0.9", "typescript": "5.1.6", diff --git a/apps/e2e/src/App.tsx b/apps/e2e/src/App.tsx index 6a8934e8..6bb5dd2b 100644 --- a/apps/e2e/src/App.tsx +++ b/apps/e2e/src/App.tsx @@ -38,7 +38,6 @@ import { PiPSubMenu } from './components/menu/PipSubMenu'; import { AutoPlaySubMenu } from './components/menu/AutoPlaySubMenu'; import { RenderingTargetSubMenu } from './components/menu/RenderingTargetSubMenu'; import { SourceMenuButton, SOURCES } from './components/menu/SourceMenuButton'; -import { ConnectorSvg } from './res/ConnectorSvg'; import { ConnectorSubMenu } from './components/menu/ConnectorSubMenu'; import { ConnectorsMenuButton } from './components/menu/ConnectorMenu'; diff --git a/apps/e2e/web/public/index.html b/apps/e2e/web/public/index.html new file mode 100644 index 00000000..4a6d88a2 --- /dev/null +++ b/apps/e2e/web/public/index.html @@ -0,0 +1,21 @@ + + + + + + + react-native-theoplayer + + + + + + + + + + + +
+ + diff --git a/apps/e2e/web/public/style.css b/apps/e2e/web/public/style.css new file mode 100644 index 00000000..73d1768e --- /dev/null +++ b/apps/e2e/web/public/style.css @@ -0,0 +1,17 @@ +h1, +h5, +span { + color: #ffffff; +} + +body { + background-color: #373a3c; +} + +.container { + flex: 1; +} + +.theoplayer-container { + z-index: 0; +} diff --git a/apps/e2e/web/public/ui.css b/apps/e2e/web/public/ui.css new file mode 100644 index 00000000..dbeaaf74 --- /dev/null +++ b/apps/e2e/web/public/ui.css @@ -0,0 +1,5123 @@ +@charset "UTF-8"; +@font-face { + font-family: THEOplayer; + src: + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'), + url(data:application/x-font-ttf;charset=utf-8;base64,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AHUAbABhAHIAVABIAEUATwBwAGwAYQB5AGUAcgBUAEgARQBPAHAAbABhAHkAZQByAFYAZQByAHMAaQBvAG4AIAAxAC4AMABUAEgARQBPAHAAbABhAHkAZQByAEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAAcwB2AGcAMgB0AHQAZgAgAGYAcgBvAG0AIABGAG8AbgB0AGUAbABsAG8AIABwAHIAbwBqAGUAYwB0AC4AaAB0AHQAcAA6AC8ALwBmAG8AbgB0AGUAbABsAG8ALgBjAG8AbQAAAAIAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAARwbGF5C3BsYXktY2lyY2xlBXBhdXNlC3ZvbHVtZS1tdXRlCnZvbHVtZS1sb3cKdm9sdW1lLW1pZAt2b2x1bWUtaGlnaBBmdWxsc2NyZWVuLWVudGVyD2Z1bGxzY3JlZW4tZXhpdAZzcXVhcmUHc3Bpbm5lcglzdWJ0aXRsZXMIY2FwdGlvbnMIY2hhcHRlcnMFc2hhcmUDY29nBmNpcmNsZQ5jaXJjbGUtb3V0bGluZRNjaXJjbGUtaW5uZXItY2lyY2xlAmhkBmNhbmNlbAZyZXBsYXkIZmFjZWJvb2sFZ3BsdXMIbGlua2VkaW4HdHdpdHRlcgZ0dW1ibHIJcGludGVyZXN0EWF1ZGlvLWRlc2NyaXB0aW9uBWF1ZGlvCW5leHQtaXRlbQ1wcmV2aW91cy1pdGVtEnBpY3R1cmUtaW4tcGljdHVyZRhwaWN0dXJlLWluLXBpY3R1cmUtZW50ZXIXcGljdHVyZS1pbi1waWN0dXJlLWV4aXQLdmlldy1tb2R1bGUFY2xvc2UJY2FyZGJvYXJkCXZpZXctZ3JpZAptdWx0aS12aWV3C2V4cGFuZC1sZXNzC2V4cGFuZC1tb3JlAAAA) + format('truetype'); + font-weight: normal; + font-style: normal; +} +.vjs-icon-play, +.video-js .vjs-play-control, +.video-js .vjs-big-play-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-play:before, +.video-js .vjs-play-control:before, +.video-js .vjs-big-play-button:before { + content: '\f101'; +} + +.vjs-icon-play-circle { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-play-circle:before { + content: '\f102'; +} + +.vjs-icon-pause, +.video-js .vjs-play-control.vjs-playing { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-pause:before, +.video-js .vjs-play-control.vjs-playing:before { + content: '\f103'; +} + +.vjs-icon-volume-mute, +.video-js .vjs-mute-control.vjs-vol-0, +.video-js .vjs-volume-menu-button.vjs-vol-0 { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-volume-mute:before, +.video-js .vjs-mute-control.vjs-vol-0:before, +.video-js .vjs-volume-menu-button.vjs-vol-0:before { + content: '\f104'; +} + +.vjs-icon-volume-low, +.video-js .vjs-mute-control.vjs-vol-1, +.video-js .vjs-volume-menu-button.vjs-vol-1 { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-volume-low:before, +.video-js .vjs-mute-control.vjs-vol-1:before, +.video-js .vjs-volume-menu-button.vjs-vol-1:before { + content: '\f105'; +} + +.vjs-icon-volume-mid, +.video-js .vjs-mute-control.vjs-vol-2, +.video-js .vjs-volume-menu-button.vjs-vol-2 { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-volume-mid:before, +.video-js .vjs-mute-control.vjs-vol-2:before, +.video-js .vjs-volume-menu-button.vjs-vol-2:before { + content: '\f106'; +} + +.vjs-icon-volume-high, +.video-js .vjs-mute-control, +.video-js .vjs-volume-menu-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-volume-high:before, +.video-js .vjs-mute-control:before, +.video-js .vjs-volume-menu-button:before { + content: '\f107'; +} + +.vjs-icon-fullscreen-enter, +.video-js .vjs-fullscreen-control { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-fullscreen-enter:before, +.video-js .vjs-fullscreen-control:before { + content: '\f108'; +} + +.vjs-icon-fullscreen-exit, +.video-js.vjs-fullscreen .vjs-fullscreen-control { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-fullscreen-exit:before, +.video-js.vjs-fullscreen .vjs-fullscreen-control:before { + content: '\f109'; +} + +.vjs-icon-square { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-square:before { + content: '\f10a'; +} + +.vjs-icon-spinner { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-spinner:before { + content: '\f10b'; +} + +.vjs-icon-subtitles, +.video-js .vjs-subtitles-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-subtitles:before, +.video-js .vjs-subtitles-button:before { + content: '\f10c'; +} + +.vjs-icon-captions, +.video-js .vjs-captions-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-captions:before, +.video-js .vjs-captions-button:before { + content: '\f10d'; +} + +.vjs-icon-chapters, +.video-js .vjs-chapters-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-chapters:before, +.video-js .vjs-chapters-button:before { + content: '\f10e'; +} + +.vjs-icon-share { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-share:before { + content: '\f10f'; +} + +.vjs-icon-cog { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-cog:before { + content: '\f110'; +} + +.vjs-icon-circle, +.theoplayer-skin .theo-live-control-indicator, +.video-js .vjs-volume-level, +.video-js .vjs-play-progress, +.video-js .vjs-mouse-display { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-circle:before, +.theoplayer-skin .theo-live-control-indicator:before, +.video-js .vjs-volume-level:before, +.video-js .vjs-play-progress:before, +.video-js .vjs-mouse-display:before { + content: '\f111'; +} + +.vjs-icon-circle-outline { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-circle-outline:before { + content: '\f112'; +} + +.vjs-icon-circle-inner-circle { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-circle-inner-circle:before { + content: '\f113'; +} + +.vjs-icon-hd { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-hd:before { + content: '\f114'; +} + +.vjs-icon-cancel, +.video-js .vjs-control.vjs-close-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-cancel:before, +.video-js .vjs-control.vjs-close-button:before { + content: '\f115'; +} + +.vjs-icon-replay, +.theoplayer-skin.vjs-ended .vjs-play-control { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-replay:before, +.theoplayer-skin.vjs-ended .vjs-play-control:before { + content: '\f116'; +} + +.vjs-icon-facebook { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-facebook:before { + content: '\f117'; +} + +.vjs-icon-gplus { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-gplus:before { + content: '\f118'; +} + +.vjs-icon-linkedin { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-linkedin:before { + content: '\f119'; +} + +.vjs-icon-twitter { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-twitter:before { + content: '\f11a'; +} + +.vjs-icon-tumblr { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-tumblr:before { + content: '\f11b'; +} + +.vjs-icon-pinterest { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-pinterest:before { + content: '\f11c'; +} + +.vjs-icon-audio-description, +.video-js .vjs-descriptions-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-audio-description:before, +.video-js .vjs-descriptions-button:before { + content: '\f11d'; +} + +.vjs-icon-audio, +.video-js .vjs-audio-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-audio:before, +.video-js .vjs-audio-button:before { + content: '\f11e'; +} + +.vjs-icon-next-item { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-next-item:before { + content: '\f11f'; +} + +.vjs-icon-previous-item { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-previous-item:before { + content: '\f120'; +} + +.vjs-icon-picture-in-picture { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-picture-in-picture:before { + content: '\f121'; +} + +.vjs-icon-picture-in-picture-enter { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-picture-in-picture-enter:before { + content: '\f122'; +} + +.vjs-icon-picture-in-picture-exit { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-picture-in-picture-exit:before { + content: '\f123'; +} + +.vjs-icon-view-module { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-view-module:before { + content: '\f124'; +} + +.vjs-icon-close, +.theoplayer-skin .theo-close-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-close:before, +.theoplayer-skin .theo-close-button:before { + content: '\f125'; +} + +.vjs-icon-cardboard, +.theoplayer-skin .theo-vr-button { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-cardboard:before, +.theoplayer-skin .theo-vr-button:before { + content: '\f126'; +} + +.vjs-icon-view-grid { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-view-grid:before { + content: '\f127'; +} + +.vjs-icon-multi-view { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-multi-view:before { + content: '\f128'; +} + +.vjs-icon-expand-less { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-expand-less:before { + content: '\f129'; +} + +.vjs-icon-expand-more { + font-family: THEOplayer; + font-weight: normal; + font-style: normal; +} +.vjs-icon-expand-more:before { + content: '\f12a'; +} + +.vjs-modal-dialog .vjs-modal-dialog-content, +.video-js .vjs-modal-dialog, +.video-js .vjs-control:before, +.video-js .vjs-big-play-button:before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.video-js .vjs-control:before, +.video-js .vjs-big-play-button:before { + text-align: center; +} + +.video-js { + display: block; + vertical-align: top; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #fff; + background-color: #000; + position: relative; + padding: 0; + font-size: 10px; + line-height: 1; + font-weight: normal; + font-style: normal; + font-family: Arial, Helvetica, sans-serif; +} +.video-js:-moz-full-screen { + position: absolute; +} +.video-js:-webkit-full-screen { + width: 100% !important; + height: 100% !important; +} + +.video-js *, +.video-js *:before, +.video-js *:after { + -webkit-box-sizing: inherit; + -moz-box-sizing: inherit; + box-sizing: inherit; +} + +.video-js ul { + font-family: inherit; + font-size: inherit; + line-height: inherit; + list-style-position: outside; + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; +} + +.video-js.vjs-fluid, +.video-js.vjs-16-9, +.video-js.vjs-4-3 { + width: 100%; + max-width: 100%; + height: 0; +} + +.video-js.vjs-16-9 { + padding-top: 56.25%; +} + +.video-js.vjs-4-3 { + padding-top: 75%; +} + +.video-js.vjs-fill { + width: 100%; + height: 100%; +} + +.video-js .vjs-tech { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +body.vjs-full-window { + padding: 0; + margin: 0; + height: 100%; + overflow-y: auto; +} + +.vjs-full-window .video-js.vjs-fullscreen { + position: fixed; + overflow: hidden; + z-index: 1000; + left: 0; + top: 0; + bottom: 0; + right: 0; +} + +.video-js.vjs-fullscreen { + width: 100% !important; + height: 100% !important; + padding-top: 0 !important; +} + +.video-js.vjs-fullscreen.vjs-user-inactive { + cursor: none; +} + +.vjs-hidden { + display: none !important; +} + +.vjs-disabled { + opacity: 0.5; + cursor: default; +} + +.video-js .vjs-offscreen { + height: 1px; + left: -9999px; + position: absolute; + top: 0; + width: 1px; +} + +.vjs-lock-showing { + display: block !important; + opacity: 1; + visibility: visible; +} + +.vjs-no-js { + padding: 20px; + color: #fff; + background-color: #000; + font-size: 18px; + font-family: Arial, Helvetica, sans-serif; + text-align: center; + width: 300px; + height: 150px; + margin: 0px auto; +} + +.vjs-no-js a, +.vjs-no-js a:visited { + color: #66a8cc; +} + +.video-js .vjs-big-play-button { + font-size: 3em; + line-height: 1.5em; + height: 1.5em; + width: 3em; + display: block; + position: absolute; + top: 10px; + left: 10px; + padding: 0; + cursor: pointer; + opacity: 1; + border: 0.06666em solid #fff; + background-color: #2b333f; + background-color: rgba(43, 51, 63, 0.7); + border-radius: 0.3em; + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + transition: all 0.4s; +} +.vjs-big-play-centered .vjs-big-play-button { + top: 50%; + left: 50%; + margin-top: -0.75em; + margin-left: -1.5em; +} + +.video-js:hover .vjs-big-play-button, +.video-js .vjs-big-play-button:focus { + outline: 0; + border-color: #fff; + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); + -webkit-transition: all 0s; + -moz-transition: all 0s; + transition: all 0s; +} + +.vjs-controls-disabled .vjs-big-play-button, +.vjs-has-started .vjs-big-play-button, +.vjs-using-native-controls .vjs-big-play-button, +.vjs-error .vjs-big-play-button { + display: none; +} + +.vjs-has-started.vjs-paused.vjs-show-big-play-button-on-pause .vjs-big-play-button { + display: block; +} + +.video-js button { + background: none; + border: none; + color: inherit; + display: inline-block; + overflow: visible; + font-size: inherit; + line-height: inherit; + text-transform: none; + text-decoration: none; + -webkit-transition: none; + -moz-transition: none; + transition: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.video-js .vjs-control.vjs-close-button { + cursor: pointer; + height: 3em; + position: absolute; + right: 0; + top: 0.5em; + z-index: 2; +} + +.vjs-menu-button { + cursor: pointer; +} + +.vjs-menu-button.vjs-disabled { + cursor: default; +} + +.vjs-workinghover .vjs-menu-button.vjs-disabled:hover .vjs-menu { + display: none; +} + +.vjs-menu .vjs-menu-content { + display: block; + padding: 0; + margin: 0; + overflow: auto; + font-family: Arial, Helvetica, sans-serif; +} + +.vjs-scrubbing .vjs-menu-button:hover .vjs-menu { + display: none; +} + +.vjs-menu li { + list-style: none; + margin: 0; + padding: 0.2em 0; + line-height: 1.4em; + font-size: 1.2em; + text-align: center; + text-transform: lowercase; +} + +.vjs-menu li.vjs-menu-item:focus, +.vjs-menu li.vjs-menu-item:hover { + outline: 0; + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); +} + +.vjs-menu li.vjs-selected, +.vjs-menu li.vjs-selected:focus, +.vjs-menu li.vjs-selected:hover { + background-color: #fff; + color: #2b333f; +} + +.vjs-menu li.vjs-menu-title { + text-align: center; + text-transform: uppercase; + font-size: 1em; + line-height: 2em; + padding: 0; + margin: 0 0 0.3em 0; + font-weight: bold; + cursor: default; +} + +.vjs-menu-button-popup .vjs-menu { + display: none; + position: absolute; + bottom: 0; + width: 10em; + left: -3em; + height: 0em; + margin-bottom: 1.5em; + border-top-color: rgba(43, 51, 63, 0.7); +} + +.vjs-menu-button-popup .vjs-menu .vjs-menu-content { + background-color: #2b333f; + background-color: rgba(43, 51, 63, 0.7); + position: absolute; + width: 100%; + bottom: 1.5em; + max-height: 15em; +} + +.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu, +.vjs-menu-button-popup .vjs-menu.vjs-lock-showing { + display: block; +} + +.video-js .vjs-menu-button-inline { + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + transition: all 0.4s; + overflow: hidden; +} + +.video-js .vjs-menu-button-inline:before { + width: 2.222222222em; +} + +.video-js .vjs-menu-button-inline:hover, +.video-js .vjs-menu-button-inline:focus, +.video-js .vjs-menu-button-inline.vjs-slider-active, +.video-js.vjs-no-flex .vjs-menu-button-inline { + width: 12em; +} + +.video-js .vjs-menu-button-inline.vjs-slider-active { + -webkit-transition: none; + -moz-transition: none; + transition: none; +} + +.vjs-menu-button-inline .vjs-menu { + opacity: 0; + height: 100%; + width: auto; + position: absolute; + left: 4em; + top: 0; + padding: 0; + margin: 0; + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + transition: all 0.4s; +} + +.vjs-menu-button-inline:hover .vjs-menu, +.vjs-menu-button-inline:focus .vjs-menu, +.vjs-menu-button-inline.vjs-slider-active .vjs-menu { + display: block; + opacity: 1; +} + +.vjs-no-flex .vjs-menu-button-inline .vjs-menu { + display: block; + opacity: 1; + position: relative; + width: auto; +} + +.vjs-no-flex .vjs-menu-button-inline:hover .vjs-menu, +.vjs-no-flex .vjs-menu-button-inline:focus .vjs-menu, +.vjs-no-flex .vjs-menu-button-inline.vjs-slider-active .vjs-menu { + width: auto; +} + +.vjs-menu-button-inline .vjs-menu-content { + width: auto; + height: 100%; + margin: 0; + overflow: hidden; +} + +.video-js .vjs-control-bar { + display: none; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 3em; + background-color: #2b333f; + background-color: rgba(43, 51, 63, 0.7); +} + +.vjs-has-started .vjs-control-bar { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: -moz-box; + display: flex; + visibility: visible; + opacity: 1; + -webkit-transition: + visibility 0.1s, + opacity 0.1s; + -moz-transition: + visibility 0.1s, + opacity 0.1s; + transition: + visibility 0.1s, + opacity 0.1s; +} + +.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { + visibility: visible; + opacity: 0; + -webkit-transition: + visibility 1s, + opacity 1s; + -moz-transition: + visibility 1s, + opacity 1s; + transition: + visibility 1s, + opacity 1s; +} + +.vjs-controls-disabled .vjs-control-bar, +.vjs-using-native-controls .vjs-control-bar, +.vjs-error .vjs-control-bar { + display: none !important; +} + +.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { + opacity: 1; + visibility: visible; +} + +.vjs-has-started.vjs-no-flex .vjs-control-bar { + display: table; +} + +.video-js .vjs-control { + outline: none; + position: relative; + text-align: center; + margin: 0; + padding: 0; + height: 100%; + width: 4em; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} +.video-js .vjs-control:before { + font-size: 1.8em; + line-height: 1.67; +} + +.video-js .vjs-control:focus:before, +.video-js .vjs-control:hover:before, +.video-js .vjs-control:focus { + text-shadow: 0em 0em 1em white; +} + +.video-js .vjs-control-text { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.vjs-no-flex .vjs-control { + display: table-cell; + vertical-align: middle; +} + +.video-js .vjs-custom-control-spacer { + display: none; +} + +.video-js .vjs-progress-control { + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: -moz-box; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + -moz-box-align: center; + align-items: center; + min-width: 4em; +} + +.vjs-live .vjs-progress-control { + display: none; +} + +.video-js .vjs-progress-holder { + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + transition: all 0.2s; + height: 0.3em; +} + +.video-js .vjs-progress-control:hover .vjs-progress-holder { + font-size: 1.6666666667em; +} + +/* If we let the font size grow as much as everything else, the current time tooltip ends up + ginormous. If you'd like to enable the current time tooltip all the time, this should be disabled + to avoid a weird hitch when you roll off the hover. */ +.video-js .vjs-progress-control:hover .vjs-time-tooltip, +.video-js .vjs-progress-control:hover .vjs-mouse-display:after, +.video-js .vjs-progress-control:hover .vjs-play-progress:after { + font-family: Arial, Helvetica, sans-serif; + visibility: visible; + font-size: 0.6em; +} + +.video-js .vjs-progress-holder .vjs-play-progress, +.video-js .vjs-progress-holder .vjs-load-progress, +.video-js .vjs-progress-holder .vjs-tooltip-progress-bar, +.video-js .vjs-progress-holder .vjs-load-progress div { + position: absolute; + display: block; + height: 100%; + margin: 0; + padding: 0; + width: 0; + left: 0; + top: 0; +} + +.video-js .vjs-mouse-display:before { + display: none; +} + +.video-js .vjs-play-progress { + background-color: #fff; +} +.video-js .vjs-play-progress:before { + position: absolute; + top: -0.3333333333em; + right: -0.5em; + font-size: 0.9em; +} + +.video-js .vjs-time-tooltip, +.video-js .vjs-mouse-display:after, +.video-js .vjs-play-progress:after { + visibility: hidden; + pointer-events: none; + position: absolute; + top: -3.4em; + right: -1.9em; + font-size: 0.9em; + color: #000; + content: attr(data-current-time); + padding: 6px 8px 8px 8px; + background-color: #fff; + background-color: rgba(255, 255, 255, 0.8); + border-radius: 0.3em; +} + +.video-js .vjs-time-tooltip, +.video-js .vjs-play-progress:before, +.video-js .vjs-play-progress:after { + z-index: 1; +} + +.video-js .vjs-progress-control .vjs-keep-tooltips-inside:after { + display: none; +} + +.video-js .vjs-load-progress { + background: #bfc7d3; + background: rgba(115, 133, 159, 0.5); +} + +.video-js .vjs-load-progress div { + background: white; + background: rgba(115, 133, 159, 0.75); +} + +.video-js.vjs-no-flex .vjs-progress-control { + width: auto; +} + +.video-js .vjs-time-tooltip { + display: inline-block; + height: 2.4em; + position: relative; + float: right; + right: -1.9em; +} + +.vjs-tooltip-progress-bar { + visibility: hidden; +} + +.video-js .vjs-progress-control .vjs-mouse-display { + display: none; + position: absolute; + width: 1px; + height: 100%; + background-color: #000; + z-index: 1; +} + +.vjs-no-flex .vjs-progress-control .vjs-mouse-display { + z-index: 0; +} + +.video-js .vjs-progress-control:hover .vjs-mouse-display { + display: block; +} + +.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display, +.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display:after { + visibility: hidden; + opacity: 0; + -webkit-transition: + visibility 1s, + opacity 1s; + -moz-transition: + visibility 1s, + opacity 1s; + transition: + visibility 1s, + opacity 1s; +} + +.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display, +.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display:after { + display: none; +} + +.vjs-mouse-display .vjs-time-tooltip, +.video-js .vjs-progress-control .vjs-mouse-display:after { + color: #fff; + background-color: #000; + background-color: rgba(0, 0, 0, 0.8); +} + +.video-js .vjs-slider { + outline: 0; + position: relative; + cursor: pointer; + padding: 0; + margin: 0 0.45em 0 0.45em; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); +} + +.video-js .vjs-slider:focus { + text-shadow: 0em 0em 1em white; + -webkit-box-shadow: 0 0 1em #fff; + box-shadow: 0 0 1em #fff; +} + +.video-js .vjs-mute-control, +.video-js .vjs-volume-menu-button { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.video-js .vjs-volume-control { + width: 5em; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: -moz-box; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + -moz-box-align: center; + align-items: center; +} + +.video-js .vjs-volume-bar { + margin: 1.35em 0.45em; +} + +.vjs-volume-bar.vjs-slider-horizontal { + width: 5em; + height: 0.3em; +} + +.vjs-volume-bar.vjs-slider-vertical { + width: 0.3em; + height: 5em; + margin: 1.35em auto; +} + +.video-js .vjs-volume-level { + position: absolute; + bottom: 0; + left: 0; + background-color: #fff; +} +.video-js .vjs-volume-level:before { + position: absolute; + font-size: 0.9em; +} + +.vjs-slider-vertical .vjs-volume-level { + width: 0.3em; +} +.vjs-slider-vertical .vjs-volume-level:before { + top: -0.5em; + left: -0.3em; +} + +.vjs-slider-horizontal .vjs-volume-level { + height: 0.3em; +} +.vjs-slider-horizontal .vjs-volume-level:before { + top: -0.3em; + right: -0.5em; +} + +.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level { + height: 100%; +} + +.vjs-volume-bar.vjs-slider-horizontal .vjs-volume-level { + width: 100%; +} + +.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu { + display: block; + width: 0; + height: 0; + border-top-color: transparent; +} + +.vjs-menu-button-popup.vjs-volume-menu-button-vertical .vjs-menu { + left: 0.5em; + height: 8em; +} + +.vjs-menu-button-popup.vjs-volume-menu-button-horizontal .vjs-menu { + left: -2em; +} + +.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu-content { + height: 0; + width: 0; + overflow-x: hidden; + overflow-y: hidden; +} + +.vjs-volume-menu-button-vertical:hover .vjs-menu-content, +.vjs-volume-menu-button-vertical:focus .vjs-menu-content, +.vjs-volume-menu-button-vertical.vjs-slider-active .vjs-menu-content, +.vjs-volume-menu-button-vertical .vjs-lock-showing .vjs-menu-content { + height: 8em; + width: 2.9em; +} + +.vjs-volume-menu-button-horizontal:hover .vjs-menu-content, +.vjs-volume-menu-button-horizontal:focus .vjs-menu-content, +.vjs-volume-menu-button-horizontal .vjs-slider-active .vjs-menu-content, +.vjs-volume-menu-button-horizontal .vjs-lock-showing .vjs-menu-content { + height: 2.9em; + width: 8em; +} + +.vjs-volume-menu-button.vjs-menu-button-inline .vjs-menu-content { + background-color: transparent !important; +} + +.vjs-poster { + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + background-color: #000000; + cursor: pointer; + margin: 0; + padding: 0; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; +} + +.vjs-poster img { + display: block; + vertical-align: middle; + margin: 0 auto; + max-height: 100%; + padding: 0; + width: 100%; +} + +.vjs-has-started .vjs-poster { + display: none; +} + +.vjs-audio.vjs-has-started .vjs-poster { + display: block; +} + +.vjs-using-native-controls .vjs-poster { + display: none; +} + +.video-js .vjs-live-control { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: -moz-box; + display: flex; + -webkit-box-align: flex-start; + -webkit-align-items: flex-start; + -ms-flex-align: flex-start; + -moz-box-align: start; + align-items: flex-start; + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + font-size: 1em; + line-height: 3em; +} + +.vjs-no-flex .vjs-live-control { + display: table-cell; + width: auto; + text-align: left; +} + +.video-js .vjs-time-control { + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; + font-size: 1em; + line-height: 3em; + min-width: 2em; + width: auto; + padding-left: 1em; + padding-right: 1em; +} + +.vjs-live .vjs-time-control { + display: none; +} + +.video-js .vjs-current-time, +.vjs-no-flex .vjs-current-time { + display: none; +} + +.video-js .vjs-duration, +.vjs-no-flex .vjs-duration { + display: none; +} + +.vjs-time-divider { + display: none; + line-height: 3em; +} + +.vjs-live .vjs-time-divider { + display: none; +} + +.video-js .vjs-play-control { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.vjs-text-track-display { + position: absolute; + bottom: 3em; + left: 0; + right: 0; + top: 0; + pointer-events: none; +} + +.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display { + bottom: 1em; +} + +.video-js .vjs-text-track { + font-size: 1.4em; + text-align: center; + margin-bottom: 0.1em; + background-color: #000; + background-color: rgba(0, 0, 0, 0.5); +} + +.vjs-subtitles { + color: #fff; +} + +.vjs-captions { + color: #fc6; +} + +.vjs-tt-cue { + display: block; +} + +video::-webkit-media-text-track-display { + -moz-transform: translateY(-3em); + -webkit-transform: translateY(-3em); + transform: translateY(-3em); +} + +.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display { + -moz-transform: translateY(-1.5em); + -webkit-transform: translateY(-1.5em); + transform: translateY(-1.5em); +} + +.video-js .vjs-fullscreen-control { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.vjs-playback-rate .vjs-playback-rate-value { + font-size: 1.5em; + line-height: 2; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; +} + +.vjs-playback-rate .vjs-menu { + width: 4em; + left: 0em; +} + +.vjs-error .vjs-error-display .vjs-modal-dialog-content { + font-size: 1.4em; + text-align: center; +} + +.vjs-error .vjs-error-display:before { + color: #fff; + content: 'X'; + font-family: Arial, Helvetica, sans-serif; + font-size: 4em; + left: 0; + line-height: 1; + margin-top: -0.5em; + position: absolute; + text-shadow: 0.05em 0.05em 0.1em #000; + text-align: center; + top: 50%; + vertical-align: middle; + width: 100%; +} + +.vjs-loading-spinner { + display: none; + position: absolute; + top: 50%; + left: 50%; + margin: -25px 0 0 -25px; + opacity: 0.85; + text-align: left; + border: 6px solid rgba(43, 51, 63, 0.7); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + background-clip: padding-box; + width: 50px; + height: 50px; + border-radius: 25px; +} + +.vjs-seeking .vjs-loading-spinner, +.vjs-waiting .vjs-loading-spinner { + display: block; +} + +.vjs-loading-spinner:before, +.vjs-loading-spinner:after { + content: ''; + position: absolute; + margin: -6px; + -webkit-box-sizing: inherit; + -moz-box-sizing: inherit; + box-sizing: inherit; + width: inherit; + height: inherit; + border-radius: inherit; + opacity: 1; + border: inherit; + border-color: transparent; + border-top-color: white; +} + +.vjs-seeking .vjs-loading-spinner:before, +.vjs-seeking .vjs-loading-spinner:after, +.vjs-waiting .vjs-loading-spinner:before, +.vjs-waiting .vjs-loading-spinner:after { + -webkit-animation: + vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, + vjs-spinner-fade 1.1s linear infinite; + -moz-animation: + vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, + vjs-spinner-fade 1.1s linear infinite; + animation: + vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, + vjs-spinner-fade 1.1s linear infinite; +} + +.vjs-seeking .vjs-loading-spinner:before, +.vjs-waiting .vjs-loading-spinner:before { + border-top-color: white; +} + +.vjs-seeking .vjs-loading-spinner:after, +.vjs-waiting .vjs-loading-spinner:after { + border-top-color: white; + -webkit-animation-delay: 0.44s; + -moz-animation-delay: 0.44s; + animation-delay: 0.44s; +} + +@-moz-keyframes vjs-spinner-spin { + 100% { + -moz-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes vjs-spinner-spin { + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@-webkit-keyframes vjs-spinner-spin { + 100% { + -webkit-transform: rotate(360deg); + } +} +@-moz-keyframes vjs-spinner-fade { + 0% { + border-top-color: #73859f; + } + 20% { + border-top-color: #73859f; + } + 35% { + border-top-color: white; + } + 60% { + border-top-color: #73859f; + } + 100% { + border-top-color: #73859f; + } +} +@keyframes vjs-spinner-fade { + 0% { + border-top-color: #73859f; + } + 20% { + border-top-color: #73859f; + } + 35% { + border-top-color: white; + } + 60% { + border-top-color: #73859f; + } + 100% { + border-top-color: #73859f; + } +} +@-webkit-keyframes vjs-spinner-fade { + 0% { + border-top-color: #73859f; + } + 20% { + border-top-color: #73859f; + } + 35% { + border-top-color: white; + } + 60% { + border-top-color: #73859f; + } + 100% { + border-top-color: #73859f; + } +} +.vjs-chapters-button .vjs-menu ul { + width: 24em; +} + +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-custom-control-spacer { + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; +} +.video-js.vjs-layout-tiny:not(.vjs-fullscreen).vjs-no-flex .vjs-custom-control-spacer { + width: auto; +} +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-current-time, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-time-divider, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-duration, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-playback-rate, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-progress-control, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-mute-control, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-menu-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-chapters-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-descriptions-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-subtitles-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-audio-button { + display: none; +} + +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-current-time, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-time-divider, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-duration, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-playback-rate, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-mute-control, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-menu-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-chapters-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-descriptions-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-subtitles-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-audio-button { + display: none; +} + +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-current-time, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-time-divider, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-duration, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-playback-rate, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-mute-control, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-chapters-button, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-descriptions-button, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-subtitles-button .vjs-audio-button { + display: none; +} + +.vjs-caption-settings { + position: relative; + top: 1em; + background-color: #2b333f; + background-color: rgba(43, 51, 63, 0.75); + color: #fff; + margin: 0 auto; + padding: 0.5em; + height: 16em; + font-size: 12px; + width: 40em; +} + +.vjs-caption-settings .vjs-tracksettings { + top: 0; + bottom: 1em; + left: 0; + right: 0; + position: absolute; + overflow: auto; +} + +.vjs-caption-settings .vjs-tracksettings-colors, +.vjs-caption-settings .vjs-tracksettings-font { + float: left; +} + +.vjs-caption-settings .vjs-tracksettings-colors:after, +.vjs-caption-settings .vjs-tracksettings-font:after, +.vjs-caption-settings .vjs-tracksettings-controls:after { + clear: both; +} + +.vjs-caption-settings .vjs-tracksettings-controls { + position: absolute; + bottom: 1em; + right: 1em; +} + +.vjs-caption-settings .vjs-tracksetting { + margin: 5px; + padding: 3px; + min-height: 40px; + border: none; +} + +.vjs-caption-settings .vjs-tracksetting label, +.vjs-caption-settings .vjs-tracksetting legend { + display: block; + width: 100px; + margin-bottom: 5px; +} + +.vjs-caption-settings .vjs-tracksetting span { + display: inline; + margin-left: 5px; + vertical-align: top; + float: right; +} + +.vjs-caption-settings .vjs-tracksetting > div { + margin-bottom: 5px; + min-height: 20px; +} + +.vjs-caption-settings .vjs-tracksetting > div:last-child { + margin-bottom: 0; + padding-bottom: 0; + min-height: 0; +} + +.vjs-caption-settings label > input { + margin-right: 10px; +} + +.vjs-caption-settings fieldset { + margin-top: 1em; + margin-left: 0.5em; +} + +.vjs-caption-settings fieldset .vjs-label { + position: absolute; + clip: rect(1px 1px 1px 1px); + /* for Internet Explorer */ + clip: rect(1px, 1px, 1px, 1px); + padding: 0; + border: 0; + height: 1px; + width: 1px; + overflow: hidden; +} + +.vjs-caption-settings input[type='button'] { + width: 40px; + height: 40px; +} + +.video-js .vjs-modal-dialog { + background: rgba(0, 0, 0, 0.8); + background: -webkit-linear-gradient(-90deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); + background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.8)), to(rgba(255, 255, 255, 0))); + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); + background: -moz-linear-gradient(top, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); + background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); +} + +.vjs-modal-dialog .vjs-modal-dialog-content { + font-size: 1.2em; + line-height: 1.5; + padding: 20px 24px; + z-index: 1; +} + +@media print { + .video-js > *:not(.vjs-tech):not(.vjs-poster) { + visibility: hidden; + } +} +/* Video.js tweaks */ +.video-js .theo-player-wrapper { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: black; +} + +.video-js .vjs-tech { + position: absolute; + z-index: 0; +} + +.theo-related-showing .vjs-control-bar, +.theo-related-showing .theo-upnext-bar, +.theo-related-showing .theo-upnext-panel, +.theo-related-showing .theo-chromecast-overlay, +.theo-related-showing .theo-upcoming-ad-notification, +.theo-related-showing .theo-menu-container, +.theo-related-showing .vjs-big-play-button, +.theo-related-showing .theo-verizonmedia-content-notification-bar, +.theo-related-showing .theo-context-menu, +.theo-related-showing .theoplayer-chaptertitle, +.theo-social-showing .vjs-control-bar, +.theo-social-showing .theo-upnext-bar, +.theo-social-showing .theo-upnext-panel, +.theo-social-showing .theo-chromecast-overlay, +.theo-social-showing .theo-upcoming-ad-notification, +.theo-social-showing .theo-menu-container, +.theo-social-showing .vjs-big-play-button, +.theo-social-showing .theo-verizonmedia-content-notification-bar, +.theo-social-showing .theo-context-menu, +.theo-social-showing .theoplayer-chaptertitle { + display: none; +} + +/* THEOplayer skin */ +.theo-primary-color, +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-autoplay, +.theoplayer-skin .theo-settings-control-menu-item-hd-label, +.theoplayer-skin .theo-settings-control-menu-item-value, +.theoplayer-skin .vjs-volume-level, +.theoplayer-skin .vjs-play-progress, +.theoplayer-skin .vjs-slider-bar, +.theoplayer-skin .vjs-big-play-button { + color: #ffc50f; +} + +.theo-primary-background, +.theo-social .theo-social-container .theo-social-label, +.theoplayer-skin .theo-menu-header, +.theoplayer-skin .theo-settings-control-label-hd { + color: black; + background-color: #ffc50f; +} + +.theo-primary-border, +.theo-related-grid .theo-related-grid-tile:hover .theo-related-grid-tile-content .theo-related-grid-tile-title { + border-color: #ffc50f; +} + +.theo-secondary-color, +.theoplayer-skin .vjs-loading-spinner, +.theoplayer-skin .vjs-time-tooltip, +.theoplayer-skin .vjs-control-bar, +.theoplayer-skin { + color: white; +} + +.theo-secondary-background, +.theoplayer-skin .theo-overlay-panel .theo-close-button { + color: black; + background-color: white; +} + +.theo-tertiary-color, +.theoplayer-skin .theo-control-bar-shadow { + color: black; +} + +.theo-tertiary-background, +.theo-social .theo-social-container .theo-social-text-container .theo-social-content-container, +.theo-related-grid .theo-related-grid-tile:hover .theo-related-grid-tile-content .theo-related-grid-tile-title, +.theoplayer-skin .theo-menu.theo-menu-animatable .theo-menu-animation-container { + color: white; + background-color: rgba(28, 28, 28, 0.9); +} + +.theoplayer-skin, +.theoplayer-skin * { + outline: none; +} + +.theoplayer-skin { + font-size: 12px; +} +.theoplayer-skin .vjs-control-bar { + background: none; + z-index: 0; +} +.theoplayer-skin .theo-control-bar-shadow { + display: block; + position: absolute; + z-index: -1; + left: 0; + right: 0; + bottom: 0; + height: 125%; + pointer-events: none; + background: currentColor; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), to(currentColor)); + background: -webkit-linear-gradient(top, transparent, currentColor); + background: -moz-linear-gradient(top, transparent, currentColor); + background: linear-gradient(to bottom, transparent, currentColor); +} +.theoplayer-skin .vjs-big-play-button { + font-size: 3em; + border-radius: 100%; + background: none; + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; + width: 20%; + height: 0; + padding-bottom: 20%; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.theoplayer-skin .vjs-big-play-button:before { + display: none; +} +.theoplayer-skin .vjs-big-play-button:after { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + content: ''; + border-radius: 100%; + -webkit-box-shadow: 0 0 2em currentColor; + box-shadow: 0 0 2em currentColor; + opacity: 0; + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +} +.theoplayer-skin .vjs-big-play-button svg { + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; +} +.theoplayer-skin .vjs-big-play-button, +.theoplayer-skin:hover .vjs-big-play-button, +.theoplayer-skin .vjs-big-play-button:focus { + border: none; +} +.theoplayer-skin:hover .vjs-big-play-button, +.theoplayer-skin .vjs-big-play-button:focus { + background: rgba(0, 0, 0, 0.4); + -webkit-transition-duration: 0.2s; + -moz-transition-duration: 0.2s; + transition-duration: 0.2s; +} +.theoplayer-skin:hover .vjs-big-play-button:after, +.theoplayer-skin .vjs-big-play-button:focus:after { + opacity: 0.6; + -webkit-transition-duration: 0.2s; + -moz-transition-duration: 0.2s; + transition-duration: 0.2s; +} +.theoplayer-skin .theo-button-tooltip { + font-family: Arial, Helvetica, sans-serif; + font-weight: 600; + border-radius: 2px; + background-color: #161719; + display: block; + position: absolute; + bottom: 100%; + padding: 0.5em 1em; + text-transform: none; + white-space: nowrap; + text-align: center; + z-index: 1; + opacity: 0; + -webkit-transition: opacity 0.2s; + -moz-transition: opacity 0.2s; + transition: opacity 0.2s; + text-shadow: none; +} +.theoplayer-skin .vjs-button:hover .theo-button-tooltip { + opacity: 1; +} +.theoplayer-skin .vjs-volume-level, +.theoplayer-skin .vjs-play-progress, +.theoplayer-skin .vjs-slider-bar { + background: currentColor; +} +.theoplayer-skin .vjs-slider { + background: rgba(255, 255, 255, 0.2); +} +.theoplayer-skin .vjs-load-progress { + background: rgba(255, 255, 255, 0.4); +} +.theoplayer-skin .vjs-load-progress div { + background: rgba(255, 255, 255, 0.6); +} +.theoplayer-skin .vjs-slider-vertical .vjs-volume-level:before { + top: -0.5em; + left: -0.25em; +} +.theoplayer-skin .vjs-slider-horizontal .vjs-volume-level:before { + top: -0.25em; + right: -0.5em; +} +.theoplayer-skin .vjs-time-control { + display: none; + padding: 0 0.25em; +} +.theoplayer-skin .vjs-current-time, +.theoplayer-skin .vjs-time-divider, +.theoplayer-skin .vjs-duration { + display: block; +} +.theoplayer-skin .vjs-time-divider { + min-width: 0; +} +.theoplayer-skin.vjs-live .vjs-time-control { + display: none; +} +.theoplayer-skin.vjs-live .vjs-remaining-time { + display: block; +} +.theoplayer-skin .theo-live-control { + cursor: pointer; + min-width: 4em; + width: auto; + text-transform: uppercase; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; +} +.theoplayer-skin .theo-live-control-indicator { + color: #888; +} +.theoplayer-skin.theo-at-live .theo-live-control-indicator { + color: #f00; +} +.theoplayer-skin .theo-live-control-text { + margin-left: 0.5em; +} +.theoplayer-skin .vjs-progress-control { + margin: 0 0.45em; +} +.theoplayer-skin .vjs-progress-holder { + margin: 0; +} +.theoplayer-skin.vjs-fullscreen { + font-size: 18px; +} +.theoplayer-skin.theo-dvr .vjs-progress-control { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; +} +.theoplayer-skin .vjs-progress-control .vjs-progress-holder { + height: 0.3em; +} +.theoplayer-skin .vjs-progress-control:hover .vjs-progress-holder { + font-size: inherit; + height: 0.5em; +} +.theoplayer-skin .vjs-control-bar { + height: 3em; + padding: 0 0.5em; +} +.theoplayer-skin .vjs-control-bar .vjs-control.vjs-button { + width: 3em; +} +@supports (padding: max(0px)) { + .theoplayer-skin.vjs-fullscreen .vjs-control-bar { + height: -webkit-calc(3em + env(safe-area-inset-bottom)); + height: -moz-calc(3em + env(safe-area-inset-bottom)); + height: calc(3em + env(safe-area-inset-bottom)); + padding-left: max(0.5em, env(safe-area-inset-left)); + padding-right: max(0.5em, env(safe-area-inset-right)); + } + .theoplayer-skin.vjs-fullscreen .vjs-progress-control { + height: -webkit-calc(3em + env(safe-area-inset-bottom)); + height: -moz-calc(3em + env(safe-area-inset-bottom)); + height: calc(3em + env(safe-area-inset-bottom)); + padding-left: max(0.5em, env(safe-area-inset-left)); + padding-right: max(0.5em, env(safe-area-inset-right)); + } + .theoplayer-skin.vjs-fullscreen .vjs-duration { + padding-right: max(0.5em, env(safe-area-inset-right)); + } + .theoplayer-skin.vjs-fullscreen .vjs-button .theo-button-icon-blur { + bottom: 2em; + } + .theoplayer-skin.vjs-fullscreen .theo-cast-button .theo-cast-svg-container { + position: absolute; + top: 0; + } + .theoplayer-skin.vjs-fullscreen .theoplayer-ima { + margin-left: env(safe-area-inset-left); + margin-right: env(safe-area-inset-right); + } +} +.theoplayer-skin .theo-controlbar-button { + cursor: pointer; + position: relative; + text-transform: uppercase; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; +} +.theoplayer-skin .theo-settings-control-label-hd { + display: none; + font-weight: bold; + font-size: 0.7em; + padding: 0.1em 0.15em 0.05em 0.15em; + font-family: Arial, Helvetica, sans-serif; + position: absolute; + right: 0.3em; + top: 0.95em; + -webkit-box-shadow: black 0px 0px 1px; + box-shadow: black 0px 0px 1px; + border-radius: 0.125em; +} +.theoplayer-skin.theo-hd .theo-settings-control-label-hd { + display: block; +} +.theoplayer-skin .theo-no-transition { + -webkit-transition: none !important; + -moz-transition: none !important; + transition: none !important; +} +.theoplayer-skin .vjs-progress-control .vjs-time-tooltip, +.theoplayer-skin .vjs-progress-control .vjs-mouse-display:after, +.theoplayer-skin .vjs-progress-control .vjs-play-progress:after { + font-family: Arial, Helvetica, sans-serif; + font-size: 1em; +} +.theoplayer-skin .vjs-progress-control:hover .vjs-time-tooltip, +.theoplayer-skin .vjs-progress-control:hover .vjs-mouse-display:after, +.theoplayer-skin .vjs-progress-control:hover .vjs-play-progress:after { + font-size: inherit; +} +.theoplayer-skin .vjs-play-progress:before { + font-size: 1.5em; + top: 50%; + right: 0; + -webkit-transform: translate(50%, -50%) scale(0); + -moz-transform: translate(50%, -50%) scale(0); + transform: translate(50%, -50%) scale(0); + -webkit-transition: -webkit-transform 0.2s; + transition: -webkit-transform 0.2s; + -moz-transition: + transform 0.2s, + -moz-transform 0.2s; + transition: transform 0.2s; + transition: + transform 0.2s, + -webkit-transform 0.2s, + -moz-transform 0.2s; + pointer-events: none; +} +.theoplayer-skin .vjs-progress-control:hover .vjs-play-progress:before { + -webkit-transform: translate(50%, -50%) scale(1); + -moz-transform: translate(50%, -50%) scale(1); + transform: translate(50%, -50%) scale(1); +} +.theoplayer-skin .vjs-time-tooltip { + height: auto; + top: 100%; + -webkit-transform: translateY(-100%) translateY(-1em); + -moz-transform: translateY(-100%) translateY(-1em); + transform: translateY(-100%) translateY(-1em); +} +.theoplayer-skin .vjs-progress-control .vjs-mouse-display { + z-index: 2; + pointer-events: none; +} +.theoplayer-skin .vjs-tooltip-progress-bar .vjs-time-tooltip, +.theoplayer-skin .vjs-play-progress:after { + display: none; +} +.theoplayer-skin .theo-time-tooltip-thumbnail { + display: none; + background: #000; +} +.theoplayer-skin .theo-time-tooltip-has-thumbnail .vjs-time-tooltip { + padding: 0; + border-radius: 0; + -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.8); + box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.8); +} +.theoplayer-skin .theo-time-tooltip-has-thumbnail .theo-time-tooltip-thumbnail { + display: block; + width: 10em; +} +.theoplayer-skin .theo-time-tooltip-has-thumbnail .theo-time-tooltip-text { + position: absolute; + bottom: 0; + left: 50%; + -webkit-transform: translateX(-50%); + -moz-transform: translateX(-50%); + transform: translateX(-50%); + padding: 3px 4px; + border-radius: 0.3em; + color: #fff; + background-color: #000; + background-color: rgba(0, 0, 0, 0.6); +} +.theoplayer-skin .vjs-play-control { + -webkit-box-ordinal-group: -99; + -webkit-order: -100; + -moz-box-ordinal-group: -99; + -ms-flex-order: -100; + order: -100; +} +.theoplayer-skin .vjs-volume-menu-button { + -webkit-box-ordinal-group: -89; + -webkit-order: -90; + -moz-box-ordinal-group: -89; + -ms-flex-order: -90; + order: -90; +} +.theoplayer-skin .theo-live-control { + -webkit-box-ordinal-group: -79; + -webkit-order: -80; + -moz-box-ordinal-group: -79; + -ms-flex-order: -80; + order: -80; +} +.theoplayer-skin .vjs-mute-control { + -webkit-box-ordinal-group: -98; + -webkit-order: -99; + -moz-box-ordinal-group: -98; + -ms-flex-order: -99; + order: -99; + width: 3em; +} +.theoplayer-skin .vjs-volume-control { + -webkit-box-ordinal-group: -97; + -webkit-order: -98; + -moz-box-ordinal-group: -97; + -ms-flex-order: -98; + order: -98; + width: auto; + margin: 0; +} +.theoplayer-skin .vjs-volume-control .vjs-volume-bar { + margin-right: 1em; + opacity: 1; + width: 5em; + -webkit-transition: + margin 0.4s ease-in-out, + opacity 0.4s ease-in-out, + width 0.4s ease-in-out; + -moz-transition: + margin 0.4s ease-in-out, + opacity 0.4s ease-in-out, + width 0.4s ease-in-out; + transition: + margin 0.4s ease-in-out, + opacity 0.4s ease-in-out, + width 0.4s ease-in-out; +} +.theoplayer-skin .vjs-volume-control .vjs-volume-bar:focus { + -webkit-transition: + margin 0.1s ease-in-out, + opacity 0.1s ease-in-out, + width 0.1s ease-in-out; + -moz-transition: + margin 0.1s ease-in-out, + opacity 0.1s ease-in-out, + width 0.1s ease-in-out; + transition: + margin 0.1s ease-in-out, + opacity 0.1s ease-in-out, + width 0.1s ease-in-out; +} +.theoplayer-skin .vjs-mute-control:not(:hover) + .vjs-volume-control:not(:hover) .vjs-volume-bar:not(:hover):not(:focus) { + margin-right: 0; + opacity: 0; + width: 0; +} +.theoplayer-skin .theo-settings-control-button { + -webkit-box-ordinal-group: 96; + -webkit-order: 95; + -moz-box-ordinal-group: 96; + -ms-flex-order: 95; + order: 95; +} +.theoplayer-skin .theo-audio-track-control-button { + -webkit-box-ordinal-group: 95; + -webkit-order: 94; + -moz-box-ordinal-group: 95; + -ms-flex-order: 94; + order: 94; +} +.theoplayer-skin .theo-text-track-control-button { + -webkit-box-ordinal-group: 94; + -webkit-order: 93; + -moz-box-ordinal-group: 94; + -ms-flex-order: 93; + order: 93; +} +.theoplayer-skin .vjs-fullscreen-control { + -webkit-box-ordinal-group: 101; + -webkit-order: 100; + -moz-box-ordinal-group: 101; + -ms-flex-order: 100; + order: 100; +} +.theoplayer-skin:not(.theo-seekbar-inside-controls) .theo-control-bar-shadow { + height: 150%; +} +.theoplayer-skin:not(.theo-seekbar-inside-controls) .vjs-progress-control { + position: absolute; + margin: 0; + left: 1em; + right: 1em; + bottom: 100%; + width: auto; + height: 0.5em; + -webkit-box-align: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + align-items: flex-end; +} +.theoplayer-skin:not(.theo-seekbar-inside-controls) .vjs-custom-control-spacer { + display: block; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; +} +.theoplayer-skin:not(.theo-seekbar-inside-controls) .theo-button-tooltip { + margin-bottom: 1em; +} +.theoplayer-skin.vjs-live.theo-at-live .vjs-remaining-time { + visibility: hidden; +} + +.theoplayer-skin.vjs-error .vjs-error-display:before, +.theoplayer-skin.vjs-error .vjs-error-display:after { + display: none; +} +.theoplayer-skin.vjs-error .vjs-modal-dialog-content { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + font-size: 2em; +} +.theoplayer-skin.vjs-error .vjs-modal-dialog { + background: #000 + url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAQAAAC0NkA6AAAACXBIWXMAAAsTAAALEwEAmpwYAAADG2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaY2BgnuDo4uTKJMDAUFBUUuQe5BgZERmlwH6egY2BmYGBgYGBITG5uMAxIMCHgYGBIS8/L5UBFTAyMHy7xsDIwMDAcFnX0cXJlYE0wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ3p5SUEJAwNjDAMDg0hSdkEJAwNjAQMDg0h2SJAzAwNjCwMDE09JakUJAwMDg3N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ15yflFBflFiSWoKAwMD1A4GBgYGXpf8EgX3xMw8BUNTVQYqg4jIKAUICxE+CDEESC4tKoMHJQODAIMWgx9DJcMqhgeM0oxRjPMYnzIZMjUwXWLWYG5kvstiwzKPlZk1m/UqmxPbJnYV9pkcAhydnKyczVzMXG3c3NwTeaR4lvIa8x7iC+Z7xl8tICSwWtBN8JFQo7Ci8GGRdFFe0a1iceKc4lslUiSFJY9KVUjrSj+RmSMbKicod1a+R8FHkVfxgtIU5SgVJZXXqlvVGtX9NGQ13mru05qonapjrSuk+0rviP58gxrDKCNLY0nj3yb3TA+brTDvt6iwTLTysbawUbUVsWOx+2r/3OG24wWnY857Xba6rndb6b7UY5HnQq8F3gt9Fvsu81vlvz5ga+DeoGPB50NuhT4L+xLBFCkYpRRtHOMWGxWXF9+SMDtxc9LZ5OepTGly6TYZUZlVWbOy9+Tcy2PKVy/wKSwuml18uORtmUS5S0Vh5byqs9V/a/Xq4usnNRxr/N1s0JLeOq/teodgp3dXe/fhXoY++/66Cfsm/p/sOKV16onpvDOCZ86a9WiO1tySefsWcC0MW7R48celDssmLH+40nhV6+qba3XXNa2/udFgU8fmB1uttk3d/mGn765Vezj2pu87fkD9YOeh10f8jm4+Ln6i9uST095ntpyTPd9+4dOluMunrlpcW3ZD9Gbrra930u/evO/z4MAj08ernyo+m/lC8GXXa+Y3dW9/vi/98OlTwed3X/O+vfuR//PD7+I/3/5V/f8PAC4MHYugPAkxAAA6L2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMwMTQgNzkuMTU2Nzk3LCAyMDE0LzA4LzIwLTA5OjUzOjAyICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTYtMDgtMDRUMTY6MTA6MTYrMDI6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDE2LTA4LTA0VDE2OjEwOjE2KzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNi0wOC0wNFQxNjoxMDoxNiswMjowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6MDQ2NTM1NjctOWJkNy03YTRhLWJiZWYtZWUzNGFkMmExZDRmPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6MWQ1ZTdlMjQtNWE0ZC0xMWU2LWI1NjItZDZkNTk2NDhiNmUyPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6NjkyYjdkODktNDgxNC03MjQ1LTgwZjktNTZlM2YyZWFjYjRiPC94bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpIaXN0b3J5PgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y3JlYXRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjY5MmI3ZDg5LTQ4MTQtNzI0NS04MGY5LTU2ZTNmMmVhY2I0Yjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNi0wOC0wNFQxNjoxMDoxNiswMjowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowNDY1MzU2Ny05YmQ3LTdhNGEtYmJlZi1lZTM0YWQyYTFkNGY8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTYtMDgtMDRUMTY6MTA6MTYrMDI6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4xPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOklDQ1Byb2ZpbGU+RG90IEdhaW4gMTUlPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+NjU1MzU8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz7EkfbeAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAmsSURBVHjahNhLdxtJcobhh5VgFaqIO0BQoEQNpW66Ty99vPSGW/8r/8tZdKvFISXeBBD3AqqAAr1onvaMN97nyROR8cUbX+TRf/13bqVho2Np4M6lqdJCXSp4MfIstvGL36XOfJFa++zeVgsdS8HcUKZQ8yQo0bCR4lSUqCmtnKmwMHSvpePKhcSLGJdKB7dSHYWDps/GhiJB04mpTGXii4l7pQqpSqXmxa1o6tFPzu09yszlgieVsRszQ1uJXNtn52JMnJgJgtxB07PfnVj6xdZIEIx8VEoEwV7budC9Hvomd6xuJ9U3Vlmoa6rj2NpG371jT/bWRg4e1BWGFk40DDBVqTuWyB3ZaZo60bI2Fl2YaAsozVUIRkYyS7HCOxvcK2WunKlLbFyaO7cEsd9UMiNNM4VK7kxNamPhTCx0ri8EHDT1rDX0fZF4EpxY2fjoSFff1JO2XK60k/ruyNrBxJVvWMv1vThW2Zuh7YedSLRx95bFUo6lH04QaZg5N1eA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'); + -webkit-animation: theo-noise-animation 0.2s linear infinite; + -moz-animation: theo-noise-animation 0.2s linear infinite; + animation: theo-noise-animation 0.2s linear infinite; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: inset 0 0 10em rgba(0, 0, 0, 0.3); + box-shadow: inset 0 0 10em rgba(0, 0, 0, 0.3); + pointer-events: none; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +/* Keyframes */ +/* TODO: investigate to minify the code */ +@-webkit-keyframes theo-noise-animation { + 0% { + background-position: 0 0; + } + 0.1% { + background-position: -7px -7px; + } + 25% { + background-position: -7px -7px; + } + 25.1% { + background-position: 7px -1px; + } + 50% { + background-position: 7px -7px; + } + 50.1% { + background-position: 5px 5px; + } + 75% { + background-position: 3px 2px; + } + 75.1% { + background-position: -3px 4px; + } + 100% { + background-position: -3px 3px; + } +} +@-moz-keyframes theo-noise-animation { + 0% { + background-position: 0 0; + } + 0.1% { + background-position: -7px -7px; + } + 25% { + background-position: -7px -7px; + } + 25.1% { + background-position: 7px -1px; + } + 50% { + background-position: 7px -7px; + } + 50.1% { + background-position: 5px 5px; + } + 75% { + background-position: 3px 2px; + } + 75.1% { + background-position: -3px 4px; + } + 100% { + background-position: -3px 3px; + } +} +@keyframes theo-noise-animation { + 0% { + background-position: 0 0; + } + 0.1% { + background-position: -7px -7px; + } + 25% { + background-position: -7px -7px; + } + 25.1% { + background-position: 7px -1px; + } + 50% { + background-position: 7px -7px; + } + 50.1% { + background-position: 5px 5px; + } + 75% { + background-position: 3px 2px; + } + 75.1% { + background-position: -3px 4px; + } + 100% { + background-position: -3px 3px; + } +} +.theoplayer-skin.vjs-error.vjs-fullscreen .vjs-control-bar { + display: -webkit-box !important; + display: -webkit-flex !important; + display: -moz-box !important; + display: -ms-flexbox !important; + display: flex !important; +} +.theoplayer-skin.vjs-error.vjs-fullscreen .vjs-control { + display: block; +} +.theoplayer-skin.vjs-error.vjs-fullscreen .vjs-control, +.theoplayer-skin.vjs-error.vjs-fullscreen .vjs-time-control { + visibility: hidden; +} +.theoplayer-skin.vjs-error.vjs-fullscreen .vjs-control.vjs-fullscreen-control { + visibility: visible; +} + +.theoplayer-skin.vjs-user-inactive.vjs-fullscreen { + cursor: inherit; +} +.theoplayer-skin.vjs-user-inactive.vjs-playing:not(.theo-menu-opened) { + cursor: none; +} + +.theoplayer-skin.vjs-user-inactive.vjs-playing .vjs-control-bar .vjs-control { + pointer-events: none; +} + +.theoplayer-skin .vjs-loading-spinner { + border: none; + border-radius: 0; + opacity: 0.7; + pointer-events: none; + width: 50px; + height: 50px; + margin: -25px 0 0 -25px; +} +.theoplayer-skin .vjs-loading-spinner:before, +.theoplayer-skin .vjs-loading-spinner:after { + display: none; +} +.theoplayer-skin .theo-loading-spinner-rotator { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} +.theoplayer-skin .theo-loading-spinner-circle-left, +.theoplayer-skin .theo-loading-spinner-circle-right { + position: absolute; + top: 0; + bottom: 0; + overflow: hidden; +} +.theoplayer-skin .theo-loading-spinner-circle-left { + left: 0; + right: 49%; +} +.theoplayer-skin .theo-loading-spinner-circle-right { + left: 49%; + right: 0; +} +.theoplayer-skin .theo-loading-spinner-circle-left:before, +.theoplayer-skin .theo-loading-spinner-circle-right:before { + content: ''; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + position: absolute; + width: 200%; + height: 100%; + border-radius: 50%; + border: 5px solid currentColor; + border-bottom-color: transparent; +} +.theoplayer-skin .theo-loading-spinner-circle-left:before { + left: 0; + right: -100%; + border-right-color: transparent; +} +.theoplayer-skin .theo-loading-spinner-circle-right:before { + left: -100%; + right: 0; + border-left-color: transparent; +} +.theoplayer-skin.vjs-seeking .vjs-loading-spinner, +.theoplayer-skin.vjs-waiting .vjs-loading-spinner { + -webkit-animation: theo-spinner-linspin 1568.23529647ms linear infinite; + -moz-animation: theo-spinner-linspin 1568.23529647ms linear infinite; + animation: theo-spinner-linspin 1568.23529647ms linear infinite; +} +.theoplayer-skin.vjs-seeking .theo-loading-spinner-rotator, +.theoplayer-skin.vjs-waiting .theo-loading-spinner-rotator { + -webkit-animation: theo-spinner-easespin 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + -moz-animation: theo-spinner-easespin 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: theo-spinner-easespin 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; +} +.theoplayer-skin.vjs-seeking .theo-loading-spinner-circle-left:before, +.theoplayer-skin.vjs-waiting .theo-loading-spinner-circle-left:before { + -webkit-animation: theo-spinner-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + -moz-animation: theo-spinner-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: theo-spinner-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; +} +.theoplayer-skin.vjs-seeking .theo-loading-spinner-circle-right:before, +.theoplayer-skin.vjs-waiting .theo-loading-spinner-circle-right:before { + -webkit-animation: theo-spinner-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + -moz-animation: theo-spinner-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: theo-spinner-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; +} + +.theoplayer-skin.vjs-error .vjs-loading-spinner, +.theoplayer-skin:not(.vjs-has-started) .vjs-loading-spinner { + display: none; +} + +@-webkit-keyframes theo-spinner-linspin { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-moz-keyframes theo-spinner-linspin { + to { + -moz-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes theo-spinner-linspin { + to { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@-webkit-keyframes theo-spinner-easespin { + 12.5% { + -webkit-transform: rotate(135deg); + transform: rotate(135deg); + } + 25% { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); + } + 37.5% { + -webkit-transform: rotate(405deg); + transform: rotate(405deg); + } + 50% { + -webkit-transform: rotate(540deg); + transform: rotate(540deg); + } + 62.5% { + -webkit-transform: rotate(675deg); + transform: rotate(675deg); + } + 75% { + -webkit-transform: rotate(810deg); + transform: rotate(810deg); + } + 87.5% { + -webkit-transform: rotate(945deg); + transform: rotate(945deg); + } + to { + -webkit-transform: rotate(1080deg); + transform: rotate(1080deg); + } +} +@-moz-keyframes theo-spinner-easespin { + 12.5% { + -moz-transform: rotate(135deg); + transform: rotate(135deg); + } + 25% { + -moz-transform: rotate(270deg); + transform: rotate(270deg); + } + 37.5% { + -moz-transform: rotate(405deg); + transform: rotate(405deg); + } + 50% { + -moz-transform: rotate(540deg); + transform: rotate(540deg); + } + 62.5% { + -moz-transform: rotate(675deg); + transform: rotate(675deg); + } + 75% { + -moz-transform: rotate(810deg); + transform: rotate(810deg); + } + 87.5% { + -moz-transform: rotate(945deg); + transform: rotate(945deg); + } + to { + -moz-transform: rotate(1080deg); + transform: rotate(1080deg); + } +} +@keyframes theo-spinner-easespin { + 12.5% { + -webkit-transform: rotate(135deg); + -moz-transform: rotate(135deg); + transform: rotate(135deg); + } + 25% { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + transform: rotate(270deg); + } + 37.5% { + -webkit-transform: rotate(405deg); + -moz-transform: rotate(405deg); + transform: rotate(405deg); + } + 50% { + -webkit-transform: rotate(540deg); + -moz-transform: rotate(540deg); + transform: rotate(540deg); + } + 62.5% { + -webkit-transform: rotate(675deg); + -moz-transform: rotate(675deg); + transform: rotate(675deg); + } + 75% { + -webkit-transform: rotate(810deg); + -moz-transform: rotate(810deg); + transform: rotate(810deg); + } + 87.5% { + -webkit-transform: rotate(945deg); + -moz-transform: rotate(945deg); + transform: rotate(945deg); + } + to { + -webkit-transform: rotate(1080deg); + -moz-transform: rotate(1080deg); + transform: rotate(1080deg); + } +} +@-webkit-keyframes theo-spinner-left-spin { + 0%, + to { + -webkit-transform: rotate(130deg); + transform: rotate(130deg); + } + 50% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg); + } +} +@-moz-keyframes theo-spinner-left-spin { + 0%, + to { + -moz-transform: rotate(130deg); + transform: rotate(130deg); + } + 50% { + -moz-transform: rotate(-5deg); + transform: rotate(-5deg); + } +} +@keyframes theo-spinner-left-spin { + 0%, + to { + -webkit-transform: rotate(130deg); + -moz-transform: rotate(130deg); + transform: rotate(130deg); + } + 50% { + -webkit-transform: rotate(-5deg); + -moz-transform: rotate(-5deg); + transform: rotate(-5deg); + } +} +@-webkit-keyframes theo-spinner-right-spin { + 0%, + to { + -webkit-transform: rotate(-130deg); + transform: rotate(-130deg); + } + 50% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg); + } +} +@-moz-keyframes theo-spinner-right-spin { + 0%, + to { + -moz-transform: rotate(-130deg); + transform: rotate(-130deg); + } + 50% { + -moz-transform: rotate(5deg); + transform: rotate(5deg); + } +} +@keyframes theo-spinner-right-spin { + 0%, + to { + -webkit-transform: rotate(-130deg); + -moz-transform: rotate(-130deg); + transform: rotate(-130deg); + } + 50% { + -webkit-transform: rotate(5deg); + -moz-transform: rotate(5deg); + transform: rotate(5deg); + } +} +.theoplayer-skin.vjs-has-started.vjs-user-inactive.vjs-playing:not(.theo-menu-opened) .vjs-control-bar { + opacity: 0; +} +.theoplayer-skin.vjs-has-started.vjs-user-inactive.vjs-playing.theo-menu-opened .vjs-control-bar { + opacity: 1; +} +.theoplayer-skin.theo-menu-opened .theo-button-tooltip { + visibility: hidden; +} +.theoplayer-skin .theo-menu { + position: absolute; + bottom: 4em; + min-width: 10em; + max-width: 22em; + max-height: 21em; + overflow-y: auto; + text-shadow: none; + cursor: pointer; + background-color: rgba(28, 28, 28, 0.9); +} +.theoplayer-skin .theo-menu::-webkit-scrollbar-track { + background-color: #424242; +} +.theoplayer-skin .theo-menu::-webkit-scrollbar { + width: 10px; +} +.theoplayer-skin .theo-menu::-webkit-scrollbar-thumb { + border-radius: 10px; + background-color: #8e8e8e; + border: 1px #424242 solid; +} +.theoplayer-skin .theo-menu-header, +.theoplayer-skin .theo-menu-item { + font-family: Arial, Helvetica, sans-serif; + text-transform: capitalize; + padding: 0.4em 1em; + font-size: 1.2em; + line-height: 1.2em; +} +.theoplayer-skin .theo-menu-header:focus, +.theoplayer-skin .theo-menu-header:hover, +.theoplayer-skin .theo-menu-item:focus, +.theoplayer-skin .theo-menu-item:hover { + outline: 0; +} +.theoplayer-skin .theo-menu-header { + text-align: center; + margin-bottom: 0.2em; + line-height: 1.4em; +} +.theoplayer-skin .theo-menu-content { + padding: 0; +} +.theoplayer-skin .theo-subtitle-options-menu-item { + font-size: 1.1em; +} +.theoplayer-skin .theo-menu.theo-menu-animatable { + overflow: visible; + background: none; +} +.theoplayer-skin .theo-menu.theo-menu-animatable .theo-menu-animation-container { + max-width: 22em; +} +.theoplayer-skin .theo-menu.theo-menu-animatable .theo-menu-animation-container { + position: absolute; + right: 0; + bottom: 0; + overflow: hidden; + -webkit-transition: + width 0.2s cubic-bezier(0.4, 0, 1, 1), + height 0.2s cubic-bezier(0.4, 0, 1, 1); + -moz-transition: + width 0.2s cubic-bezier(0.4, 0, 1, 1), + height 0.2s cubic-bezier(0.4, 0, 1, 1); + transition: + width 0.2s cubic-bezier(0.4, 0, 1, 1), + height 0.2s cubic-bezier(0.4, 0, 1, 1); +} +.theoplayer-skin .theo-menu.theo-menu-animatable .theo-menu-content-animatable { + bottom: 0; + right: 0; + -webkit-transition: + opacity 0.3s cubic-bezier(0, 0, 0.2, 1), + -webkit-transform 0.2s cubic-bezier(0.4, 0, 1, 1); + transition: + opacity 0.3s cubic-bezier(0, 0, 0.2, 1), + -webkit-transform 0.2s cubic-bezier(0.4, 0, 1, 1); + -moz-transition: + opacity 0.3s cubic-bezier(0, 0, 0.2, 1), + transform 0.2s cubic-bezier(0.4, 0, 1, 1), + -moz-transform 0.2s cubic-bezier(0.4, 0, 1, 1); + transition: + opacity 0.3s cubic-bezier(0, 0, 0.2, 1), + transform 0.2s cubic-bezier(0.4, 0, 1, 1); + transition: + opacity 0.3s cubic-bezier(0, 0, 0.2, 1), + transform 0.2s cubic-bezier(0.4, 0, 1, 1), + -webkit-transform 0.2s cubic-bezier(0.4, 0, 1, 1), + -moz-transform 0.2s cubic-bezier(0.4, 0, 1, 1); + position: absolute; + background: none; +} +.theoplayer-skin .theo-submenu .theo-menu-header { + padding: 5px 10px 5px 24px; + background-image: url("data:image/svg+xml,%3Csvg fill='%23000000' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z'/%3E%3C/svg%3E"); + background-position: left center; + background-repeat: no-repeat; +} +.theoplayer-skin .theo-submenu .theo-menu-content { + position: relative; + bottom: 0; + padding: 0; + height: 100%; + overflow: hidden; +} +.theoplayer-skin .theo-submenu .theo-menu-item { + display: block; + text-align: right; + text-transform: capitalize; + position: relative; +} +.theoplayer-skin .theo-submenu .theo-menu-item.vjs-selected { + font-weight: bold; +} +.theoplayer-skin .theo-menu .theo-menu-item { + width: 100%; + height: auto; + text-align: center; + list-style-type: none; +} +.theoplayer-skin .theo-menu .theo-menu-item:focus, +.theoplayer-skin .theo-menu .theo-menu-item:hover { + color: inherit; + background-color: rgba(255, 255, 255, 0.1); +} +.theoplayer-skin .theo-menu .theo-menu-item.vjs-selected, +.theoplayer-skin .theo-menu .theo-menu-item.vjs-selected:focus, +.theoplayer-skin .theo-menu .theo-menu-item.vjs-selected:hover { + color: #ffc50f; + background-color: rgba(255, 255, 255, 0.2); +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + transition: all 0.2s; + font-weight: normal; +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item .theo-text-track-menu-item-toggle { + background-color: rgba(255, 255, 255, 0.2); + border-radius: 1em; + width: 2.2em; + height: 0.9em; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + margin-left: 1em; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + opacity: 0.3; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + transition: all 0.2s; +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item .theo-text-track-menu-item-toggle .theo-text-track-menu-item-toggle-slider { + background-color: #949494; + width: 1.2em; + height: 1.2em; + border-radius: 50%; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + transition: all 0.2s; +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item.vjs-selected .theo-text-track-menu-item-toggle, +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item:hover .theo-text-track-menu-item-toggle { + opacity: 1; + background-color: rgba(255, 255, 255, 0.4); +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item.vjs-selected .theo-text-track-menu-item-toggle .theo-text-track-menu-item-toggle-slider, +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item:hover .theo-text-track-menu-item-toggle .theo-text-track-menu-item-toggle-slider { + background-color: #d0d0d0; +} +.theoplayer-skin .theo-menu-item.theo-text-track-menu-item.vjs-selected .theo-text-track-menu-item-toggle { + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu, +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-menu-content-animatable { + min-width: 18em; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-submenu { + min-width: 10em; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-submenu .theo-menu-item:last-child { + margin-bottom: 0.4em; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-submenu .theo-menu-item { + padding-right: 1em; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-menu-item { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; + position: relative; + white-space: nowrap; + padding-right: 2em; +} +.theoplayer-skin .theo-menu.theo-settings-control-menu .theo-submenu.theo-leaf-submenu .theo-menu-item { + display: block; +} +.theoplayer-skin .theo-settings-control-menu-item-title { + font-weight: 600; + padding-right: 0.5em; +} +.theoplayer-skin .theo-settings-control-menu-item-value { + font-size: 0.9em; +} +.theoplayer-skin .theo-context-menu { + position: absolute; + top: 0; + left: 0; + z-index: 1000; + padding: 5px 5px; + margin: 2px 0 0; + list-style: none; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; + text-align: left; + overflow: hidden; + text-shadow: none; + cursor: pointer; + background-color: rgba(28, 28, 28, 0.9); + text-decoration: none; +} +.theoplayer-skin .theo-context-menu:hover { + background-color: rgba(14, 14, 14, 0.9); +} +.theoplayer-skin .theo-context-menu .theo-context-menu-a { + text-decoration: none; +} +.theoplayer-skin .theo-context-menu .theo-context-menu-a .theo-context-menu-logo { + float: left; + position: relative; + top: 4.3px; +} +.theoplayer-skin .theo-context-menu .theo-context-menu-a .theo-context-menu-logo .theo-context-menu-logo-svg { + width: 30px; + height: 15px; +} +.theoplayer-skin .theo-context-menu .theo-context-menu-a .theo-context-version { + font-size: 11px; + text-align: center; + line-height: 20px; + color: white; + text-decoration: none; + width: 200px; +} +.theoplayer-skin .theo-settings-control-menu-quality-automatic { + color: rgba(255, 255, 255, 0.9); + text-transform: uppercase; + font-size: 0.7em; +} +.theoplayer-skin .theo-settings-control-menu-item-hd-label { + display: inline; + content: 'HD'; + font-weight: bold; + font-size: 0.7em; + margin-left: 0.2em; + position: absolute; + top: 0; + right: 0.6em; +} +.theoplayer-skin .theo-settings-control-submenu-item-alternate-value { + font-size: 0.55em; + margin-top: 1.5em; + margin-left: 0.5em; + vertical-align: sub; + font-weight: normal; + text-transform: none; + position: absolute; + right: 0.6em; +} + +.theoplayer-skin.theo-mobile { + -webkit-tap-highlight-color: transparent; +} +.theoplayer-skin.theo-mobile.vjs-fullscreen { + font-size: 12px; +} +.theoplayer-skin.theo-mobile.video-js .vjs-control:before { + font-size: 2.1em; + line-height: 1.4em; +} +.theoplayer-skin.theo-mobile .vjs-play-progress:before { + -webkit-transform: translate(50%, -50%) scale(1); + -moz-transform: translate(50%, -50%) scale(1); + transform: translate(50%, -50%) scale(1); + -webkit-transition: none; + -moz-transition: none; + transition: none; +} +.theoplayer-skin.theo-mobile .vjs-duration.vjs-time-control { + position: absolute; + top: -3.3em; + right: 1em; + text-shadow: 0 0 1em black; + font-size: 1.3em; +} +.theoplayer-skin.theo-mobile .vjs-current-time, +.theoplayer-skin.theo-mobile .vjs-time-divider, +.theoplayer-skin.theo-mobile .vjs-remaining-time, +.theoplayer-skin.theo-mobile .vjs-volume-control { + display: none; +} +.theoplayer-skin.theo-mobile:not(.theo-seekbar-inside-controls) .vjs-progress-control { + padding-top: 2.5em; + padding-bottom: 0.8em; + margin-bottom: -0.8em; +} +.theoplayer-skin.theo-mobile:not(.theo-seekbar-inside-controls) .vjs-progress-control .vjs-progress-holder { + font-size: 1.66667em; + height: 0.3em; +} +.theoplayer-skin.theo-mobile:not(.theo-seekbar-inside-controls) .vjs-progress-control .vjs-progress-holder .vjs-time-tooltip { + visibility: visible; + right: -1.7em; + bottom: -0.35em; + font-size: 0.8em; + padding: 0.3em; +} +.theoplayer-skin.theo-mobile:not(.theo-seekbar-inside-controls) .vjs-progress-control .vjs-progress-holder .vjs-play-progress:before { + font-size: 0.9em; +} +.theoplayer-skin.theo-mobile .vjs-button, +.theoplayer-skin.theo-mobile .vjs-button:before { + -webkit-transition: text-shadow 0.2s ease-in-out; + -moz-transition: text-shadow 0.2s ease-in-out; + transition: text-shadow 0.2s ease-in-out; +} +.theoplayer-skin.theo-mobile .vjs-button:hover:before { + text-shadow: none; +} +.theoplayer-skin.theo-mobile .vjs-button.theo-mobile-button-hover, +.theoplayer-skin.theo-mobile .vjs-button.theo-mobile-button-hover:before { + text-shadow: 0 0 1em white; + -webkit-transition: none; + -moz-transition: none; + transition: none; +} +.theoplayer-skin.theo-mobile .theo-mobile-menu-background { + opacity: 0; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable { + position: absolute; + top: auto; + bottom: 50%; + -webkit-transform: translateY(50%); + -moz-transform: translateY(50%); + transform: translateY(50%); + left: 15%; + right: 15%; + width: 70%; + max-width: 70%; + max-height: 100%; + overflow-y: auto; + -webkit-transition: none; + -moz-transition: none; + transition: none; + z-index: 2; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu, +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-animation-container { + position: static; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + overflow: visible; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-header { + padding: 1em; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-item { + height: 4em; + padding-left: 1em; + line-height: 3.4em; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-item.theo-mobile-menu-item-hover { + background-color: rgba(255, 255, 255, 0.1); +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-item:focus, +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-item:hover { + background-color: transparent; +} +.theoplayer-skin.theo-mobile .theo-menu.theo-menu-animatable .theo-menu-animation-container { + width: 100%; + height: 100%; + max-height: 100%; + overflow-y: auto; + bottom: auto; + right: auto; + max-width: none; + -webkit-transition: none; + -moz-transition: none; + transition: none; +} +.theoplayer-skin.theo-mobile .theo-settings-control-menu-item-title { + -webkit-align-self: auto; + -ms-flex-item-align: auto; + align-self: auto; +} +.theoplayer-skin.theo-mobile .theo-settings-control-menu-item-value { + font-size: 1em; +} +.theoplayer-skin.theo-mobile .theo-submenu .theo-submenu-content { + overflow-y: hidden; +} +.theoplayer-skin.theo-mobile .theo-subtitle-options-menu-item { + float: left; +} +.theoplayer-skin.theo-mobile.theo-mobile-portrait .theo-submenu.theo-leaf-submenu .theo-menu-item { + width: 50%; + float: left; +} +.theoplayer-skin.theo-mobile.theo-mobile-portrait .theo-submenu .theo-menu-item.theo-subtitle-options-menu-item { + width: 100%; +} +.theoplayer-skin.theo-mobile.theo-mobile-landscape .theo-submenu .theo-menu-item { + width: 50%; + float: left; +} +.theoplayer-skin.theo-mobile.theo-mobile-landscape .theo-submenu.theo-leaf-submenu .theo-menu-item { + width: 33.33%; + float: left; +} +.theoplayer-skin.theo-mobile.theo-mobile-landscape .theo-submenu .theo-menu-item.theo-subtitle-options-menu-item { + width: 100%; +} +.theoplayer-skin.theo-mobile.theo-pip-enabled .vjs-tech, +.theoplayer-skin.theo-mobile.theo-pip-enabled .vjs-control-bar { + width: 85%; + left: 7.5%; + right: 7.5%; + height: auto; +} +.theoplayer-skin.theo-mobile .theoplayer-ad-overlay-component.theoplayer-ad-touch-clickthrough { + top: 2.7em; +} +.theoplayer-skin.theo-mobile.theo-ad-playing .vjs-duration-display { + display: none; +} +.theoplayer-skin.theo-mobile .theo-button-tooltip { + visibility: hidden; +} + +.theoplayer-chapterbar { + height: 100%; + width: 100%; +} +.theoplayer-chapterbar .theoplayer-chapter-indicator { + position: absolute; + height: 100%; + border-left: 1px solid black; +} +.theoplayer-chapterbar .theoplayer-chapter-indicator .theoplayer-chapter-indicator-highlight { + position: absolute; + left: 0; + bottom: 100%; + width: 100%; + height: 0; + padding-top: 2px; + border-top: 2px solid transparent; +} +.theoplayer-chapterbar .theoplayer-chapter-indicator.theoplayer-chapter-indicator-discontinuous { + border-right: 1px solid black; +} +.theoplayer-chapterbar .theoplayer-chapter-indicator:hover .theoplayer-chapter-indicator-highlight { + border-top-color: rgba(255, 255, 255, 0.8); +} + +.theoplayer-chaptertitle { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + height: 100%; + position: absolute; + top: 0; + pointer-events: none; + -webkit-transition: opacity 0.4s ease-in; + -moz-transition: opacity 0.4s ease-in; + transition: opacity 0.4s ease-in; + opacity: 0; +} +.theoplayer-chaptertitle p { + font-size: 2.5em; + color: #fff; + padding: 0.3em; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 0.3em; + margin: 0; +} + +.vjs-user-active .theoplayer-chaptertitle.theoplayer-chapter-hovering { + opacity: 1; +} + +.theoplayer-skin.video-js .vjs-button .theo-button-icon-blur { + position: absolute; + background-color: rgba(255, 255, 255, 0.2); + width: 60%; + height: 70%; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + -webkit-filter: blur(4px); + filter: blur(4px); + visibility: hidden; +} +.theoplayer-skin.video-js .vjs-button:hover .theo-button-icon-blur, +.theoplayer-skin.video-js .vjs-button:focus .theo-button-icon-blur { + visibility: visible; +} + +.video-js .theo-close-button { + display: none; + position: absolute; + right: 0; + top: 0; + cursor: pointer; + outline: none; + margin: 0; + padding: 0; + z-index: 11; +} +.theoplayer-skin .theo-close-button { + padding: 0.5em; + font-size: 1.35em; + font-weight: bold; + text-align: center; +} +.theoplayer-skin .theo-close-button:focus:before, +.theoplayer-skin .theo-close-button:hover:before { + text-shadow: 0 0 1em white; +} + +.theoplayer-skin .theo-player-wrapper .vjs-control-bar.theo-top-controlbar { + top: 0; + height: 4em; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + visibility: hidden; + margin: 0.75em; + padding: 0; + width: auto; +} +.theo-player-wrapper .vjs-control-bar.theo-top-controlbar .theo-control-bar-shadow { + display: none; +} +.theo-player-wrapper .vjs-control-bar.theo-top-controlbar .theo-button-tooltip { + top: 100%; + bottom: auto; + margin-top: 0.3em; +} +.theo-pip.theoplayer-skin .theo-player-wrapper .vjs-control-bar.theo-top-controlbar { + display: none; +} +.theo-player-wrapper .vjs-control-bar.theo-top-controlbar .vjs-button { + visibility: visible; + background-color: rgba(33, 33, 33, 0.8); + border-radius: 100%; + height: 3em; + width: 3em; + margin: 0.5em; +} + +/* Quality Label */ +.theo-quality-label { + cursor: default; + display: none; + font-family: Arial, Helvetica, sans-serif; + height: 45%; + margin: auto; + text-align: right; + width: 100px; + right: 0; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: right; + -webkit-align-items: right; + -moz-box-align: right; + -ms-flex-align: right; + align-items: right; +} + +.theo-quality-label-text { + background-color: #333333; + border-radius: 3px; + font-size: 0.87em; + padding: 3px; + vertical-align: middle; + text-align: right; + margin-right: 5px; +} + +.theo-quality-label-show { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; +} + +.theo-quality-label-fadeout { + -webkit-transition: opacity 0.25s linear; + -moz-transition: opacity 0.25s linear; + transition: opacity 0.25s linear; + opacity: 0; +} + +/* THEOplayer extensions */ +.vjs-descriptions-button { + -webkit-box-ordinal-group: 91; + -webkit-order: 90; + -moz-box-ordinal-group: 91; + -ms-flex-order: 90; + order: 90; +} + +/* Chromecast button */ +.theo-chromecast-button { + -webkit-box-ordinal-group: 94; + -webkit-order: 93; + -moz-box-ordinal-group: 94; + -ms-flex-order: 93; + order: 93; +} +.theo-chromecast-unavailable .theo-chromecast-button { + display: none; +} +.theo-chromecast-button .theo-chromecast-rings { + -webkit-clip-path: polygon(50% -100%, 50% 50%, 100% 50%, 100% -100%); + clip-path: polygon(50% -100%, 50% 50%, 100% 50%, 100% -100%); +} + +.theo-chromecast-button .theo-chromecast-inner { + opacity: 0; + -webkit-transition: opacity 0.5s ease-in-out; + -moz-transition: opacity 0.5s ease-in-out; + transition: opacity 0.5s ease-in-out; +} +.theo-chromecast-connected .theo-chromecast-button .theo-chromecast-inner { + opacity: 1; +} + +.theo-chromecast-connecting .theo-chromecast-button .theo-chromecast-ring { + -webkit-animation: 0.9s linear infinite; + -moz-animation: 0.9s linear infinite; + animation: 0.9s linear infinite; +} +.theo-chromecast-connecting .theo-chromecast-button .theo-chromecast-ring1 { + -webkit-animation-name: theo-chromecast-connecting-ring1; + -moz-animation-name: theo-chromecast-connecting-ring1; + animation-name: theo-chromecast-connecting-ring1; +} +.theo-chromecast-connecting .theo-chromecast-button .theo-chromecast-ring2 { + -webkit-animation-name: theo-chromecast-connecting-ring2; + -moz-animation-name: theo-chromecast-connecting-ring2; + animation-name: theo-chromecast-connecting-ring2; +} +.theo-chromecast-connecting .theo-chromecast-button .theo-chromecast-ring3 { + -webkit-animation-name: theo-chromecast-connecting-ring3; + -moz-animation-name: theo-chromecast-connecting-ring3; + animation-name: theo-chromecast-connecting-ring3; +} +.theo-chromecast-connecting .theo-chromecast-button .theo-chromecast-ring4 { + -webkit-animation-name: theo-chromecast-connecting-ring4; + -moz-animation-name: theo-chromecast-connecting-ring4; + animation-name: theo-chromecast-connecting-ring4; +} + +@-webkit-keyframes theo-chromecast-connecting-ring1 { + 0%, + 37.5% { + -webkit-transform: scale(0); + transform: scale(0); + } + 62.5%, + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@-moz-keyframes theo-chromecast-connecting-ring1 { + 0%, + 37.5% { + -moz-transform: scale(0); + transform: scale(0); + } + 62.5%, + 100% { + -moz-transform: scale(1); + transform: scale(1); + } +} + +@keyframes theo-chromecast-connecting-ring1 { + 0%, + 37.5% { + -webkit-transform: scale(0); + -moz-transform: scale(0); + transform: scale(0); + } + 62.5%, + 100% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + transform: scale(1); + } +} +@-webkit-keyframes theo-chromecast-connecting-ring2 { + 0%, + 20% { + -webkit-transform: scale(0.25); + transform: scale(0.25); + stroke-width: 24; + } + 35% { + -webkit-transform: scale(0.5); + transform: scale(0.5); + stroke-width: 10; + } + 55%, + 100% { + -webkit-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@-moz-keyframes theo-chromecast-connecting-ring2 { + 0%, + 20% { + -moz-transform: scale(0.25); + transform: scale(0.25); + stroke-width: 24; + } + 35% { + -moz-transform: scale(0.5); + transform: scale(0.5); + stroke-width: 10; + } + 55%, + 100% { + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@keyframes theo-chromecast-connecting-ring2 { + 0%, + 20% { + -webkit-transform: scale(0.25); + -moz-transform: scale(0.25); + transform: scale(0.25); + stroke-width: 24; + } + 35% { + -webkit-transform: scale(0.5); + -moz-transform: scale(0.5); + transform: scale(0.5); + stroke-width: 10; + } + 55%, + 100% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@-webkit-keyframes theo-chromecast-connecting-ring3 { + 0%, + 15% { + -webkit-transform: scale(0.6); + transform: scale(0.6); + stroke-width: 6.66667; + } + 45%, + 100% { + -webkit-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@-moz-keyframes theo-chromecast-connecting-ring3 { + 0%, + 15% { + -moz-transform: scale(0.6); + transform: scale(0.6); + stroke-width: 6.66667; + } + 45%, + 100% { + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@keyframes theo-chromecast-connecting-ring3 { + 0%, + 15% { + -webkit-transform: scale(0.6); + -moz-transform: scale(0.6); + transform: scale(0.6); + stroke-width: 6.66667; + } + 45%, + 100% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + } +} +@-webkit-keyframes theo-chromecast-connecting-ring4 { + 0% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + stroke-width: 4; + stroke-dashoffset: 0; + stroke-dasharray: 32, 99; + } + 35% { + opacity: 1; + -webkit-transform: scale(1.4); + transform: scale(1.4); + stroke-width: 2.8571; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50% { + opacity: 1; + -webkit-transform: scale(1.5); + transform: scale(1.5); + stroke-width: 0; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50.001%, + 100% { + opacity: 0; + } +} +@-moz-keyframes theo-chromecast-connecting-ring4 { + 0% { + opacity: 1; + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + stroke-dashoffset: 0; + stroke-dasharray: 32, 99; + } + 35% { + opacity: 1; + -moz-transform: scale(1.4); + transform: scale(1.4); + stroke-width: 2.8571; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50% { + opacity: 1; + -moz-transform: scale(1.5); + transform: scale(1.5); + stroke-width: 0; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50.001%, + 100% { + opacity: 0; + } +} +@keyframes theo-chromecast-connecting-ring4 { + 0% { + opacity: 1; + -webkit-transform: scale(1); + -moz-transform: scale(1); + transform: scale(1); + stroke-width: 4; + stroke-dashoffset: 0; + stroke-dasharray: 32, 99; + } + 35% { + opacity: 1; + -webkit-transform: scale(1.4); + -moz-transform: scale(1.4); + transform: scale(1.4); + stroke-width: 2.8571; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50% { + opacity: 1; + -webkit-transform: scale(1.5); + -moz-transform: scale(1.5); + transform: scale(1.5); + stroke-width: 0; + stroke-dashoffset: -18; + stroke-dasharray: 0, 99; + } + 50.001%, + 100% { + opacity: 0; + } +} +/* Chromecast overlay */ +.theo-chromecast-overlay { + display: none; + position: absolute; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + top: 0; + pointer-events: none; +} +.theo-chromecast-connected .theo-chromecast-overlay { + display: block; +} +.theo-chromecast-overlay .theo-chromecast-status { + position: absolute; + left: 35px; + right: 35px; + bottom: 4em; + opacity: 0.7; +} +.theo-chromecast-overlay .theo-chromecast-status-icon { + float: left; + width: 80px; + height: 80px; +} +.theo-chromecast-overlay .theo-chromecast-status-info { + font-size: 130%; + font-weight: 500; + text-transform: uppercase; + top: 18px; +} +.theo-chromecast-overlay .theo-chromecast-status-title { + font-size: 250%; + top: 35px; +} +.theo-chromecast-overlay .theo-chromecast-status-info, +.theo-chromecast-overlay .theo-chromecast-status-title { + position: absolute; + left: 75px; + text-shadow: 0 0 2px rgba(0, 0, 0, 0.5); +} + +.theo-airplay-button { + -webkit-box-ordinal-group: 95; + -webkit-order: 94; + -moz-box-ordinal-group: 95; + -ms-flex-order: 94; + order: 94; +} +.theo-airplay-unavailable .theo-airplay-button { + display: none; +} + +/* Update the AirplayButton's showing */ +.theo-airplay-button .theo-cast-inner { + opacity: 0; + -webkit-transition: opacity 0.5s ease-in-out; + -moz-transition: opacity 0.5s ease-in-out; + transition: opacity 0.5s ease-in-out; +} +.theo-airplay-connected .theo-airplay-button .theo-cast-inner { + opacity: 1; +} + +.theo-airplay-connected .theo-audio-track-control-button, +.theo-airplay-connected .theo-text-track-control-button, +.theo-airplay-connected .vjs-volume-control, +.theo-airplay-connected .vjs-mute-control { + display: none; +} + +/* Chromecast and Airplay button*/ +.video-js .vjs-control.theo-cast-button .theo-cast-svg-container { + width: 100%; + height: 100%; +} +.video-js .vjs-control.theo-cast-button svg { + color: inherit; + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + transform-origin: 0 0; + pointer-events: none; + margin: 0.5em; +} + +.theoplayer-ad-linear { + top: 0; + z-index: 10; +} + +.theoplayer-skin .theoplayer-ad-skip, +.theoplayer-skin .theoplayer-ad-overlay-component { + color: white; + background-color: rgba(51, 51, 51, 0.6); + z-index: 12; + padding: 1em; + cursor: pointer; + font-size: 1.25em; +} +.theoplayer-skin .theoplayer-ad-skip.theo-ad-remaining-container, +.theoplayer-skin .theoplayer-ad-overlay-component.theo-ad-remaining-container { + top: 0; + position: absolute; + width: 100%; + text-align: center; + padding: 0.5em; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip-countdown, +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip-button, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip-countdown, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip-button { + bottom: 3.2em; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip { + padding: 0; + position: absolute; + line-height: 4em; + height: 4em; + right: 0; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip.theo-size-xs .theoplayer-ad-skip-poster, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip.theo-size-xs .theoplayer-ad-skip-poster { + display: none; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip.theo-size-xs.theoplayer-ad-skip-countdown, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip.theo-size-xs.theoplayer-ad-skip-countdown { + line-height: 2em; + height: 2em; + bottom: 3.5em; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip span, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip span { + display: table-cell; + padding: 0 1em; + position: relative; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip .theoplayer-ad-skip-poster, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip .theoplayer-ad-skip-poster { + width: 7em; + height: 4em; + display: table-cell; + background-size: cover; + background-position: center; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-skip-countdown, +.theoplayer-skin .theoplayer-ad-skip.theo-ad-remaining-container, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-skip-countdown, +.theoplayer-skin .theoplayer-ad-overlay-component.theo-ad-remaining-container { + cursor: default; +} +.theoplayer-skin .theoplayer-ad-skip.theoplayer-ad-touch-clickthrough, +.theoplayer-skin .theoplayer-ad-overlay-component.theoplayer-ad-touch-clickthrough { + top: 1em; + right: 0; +} + +.theoplayer-ad-nonlinear .theoplayer-ad-nonlinear-content .theoplayer-ad-nonlinear-close:before { + display: inline-block; + content: '×'; + padding: 0.1em 0.15em 0.12em 0.2em; + color: white; + text-shadow: + -1px 0 black, + 0 1px black, + 1px 0 black, + 0 -1px black; +} +.theoplayer-ad-nonlinear .theoplayer-ad-nonlinear-content .theoplayer-ad-nonlinear-close:hover:before { + text-shadow: + -1px 0 0.8em black, + 0 1px 0.8em black, + 1px 0 0.8em black, + 0 -1px 0.8em black; +} + +.theo-ad-playing .vjs-progress-control { + pointer-events: none; + cursor: default; +} +.theo-ad-playing .theo-settings-control-button, +.theo-ad-playing .theo-settings-control-menu { + display: none !important; +} + +.theo-dai-clickthrough, +.theo-dai-countdown { + opacity: 0; + display: none; +} + +.theo-dai-clickthrough { + font-weight: bold; + color: white; + background: rgba(51, 51, 51, 0.6) none; + position: absolute; + height: auto; + z-index: 10; + width: auto; + padding: 0.65em; + right: 0; + top: 0; + cursor: pointer; +} + +.vjs-has-started.theo-dai-ad-playing .theo-top-controlbar { + display: none; +} +.vjs-has-started.theo-dai-ad-playing .theo-dai-countdown { + opacity: 1; + display: block; + background: rgba(51, 51, 51, 0.4); + bottom: 4em; + padding: 0.65em; + color: white; + position: absolute; + left: 2em; + right: auto; + z-index: 10; + visibility: visible; + width: auto; + min-width: 0; +} +.vjs-has-started.theo-dai-ad-playing .theo-dai-countdown:before { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + content: ''; + background: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.3)), to(transparent)); + background: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.3), transparent); + background: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.3), transparent); + background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent); + z-index: -1; + opacity: 0; +} +.vjs-has-started.theo-dai-ad-playing .theo-dai-clickthrough { + opacity: 1; + display: block; +} +.vjs-has-started.theo-dai-ad-playing .theo-dai-clickthrough:focus { + background-color: #333333; +} + +.vjs-has-started.theo-dai-ad-playing.vjs-user-inactive.vjs-playing:not(.theo-menu-opened) .theo-dai-countdown { + bottom: 0; + left: 0; + min-width: 100%; + -webkit-transition-duration: 0s; + -moz-transition-duration: 0s; + transition-duration: 0s; + background-color: transparent; + text-shadow: black 1px 1px 2px; + padding-top: 1em; + -webkit-transition: + left 0s 0.45s, + min-width 0s 0.45s, + text-shadow 0s 0.45s, + bottom 0.15s 0.45s, + background-color 0.15s 0.45s, + padding-top 0.15s 0.45s; + -moz-transition: + left 0s 0.45s, + min-width 0s 0.45s, + text-shadow 0s 0.45s, + bottom 0.15s 0.45s, + background-color 0.15s 0.45s, + padding-top 0.15s 0.45s; + transition: + left 0s 0.45s, + min-width 0s 0.45s, + text-shadow 0s 0.45s, + bottom 0.15s 0.45s, + background-color 0.15s 0.45s, + padding-top 0.15s 0.45s; +} +.vjs-has-started.theo-dai-ad-playing.vjs-user-inactive.vjs-playing:not(.theo-menu-opened) .theo-dai-countdown:before { + opacity: 1; + -webkit-transition: opacity 0s 0.45s; + -moz-transition: opacity 0s 0.45s; + transition: opacity 0s 0.45s; +} + +/* + freewheel + */ +.theo-freewheel, +.theo-freewheel-video { + z-index: 10; + top: 0; + left: 0; + right: 0; + bottom: 0; + position: absolute; +} + +.freewheel-nonlinear-ad .theo-freewheel { + bottom: 3.5em; +} + +/* + YoSpace + */ +.theoplayer-yospace-advert { + top: 0; + left: 0; +} + +.theo-pip-overlay { + display: none; +} + +.theo-pip:not(.vjs-fullscreen) .theo-player-wrapper { + position: fixed !important; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin:not(.theo-ios-sdk) { + background-color: #757575; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .theo-control-bar-shadow { + display: none; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-control:before, +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .theo-close-button:before { + text-shadow: + 0 0 1px #000000, + 0 0 1px #000000, + 0 0 1px #000000, + 0 0 1px #000000, + 0 0 1px #000000; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-control, +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-time-divider { + display: none; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-play-control, +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-mute-control, +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-fullscreen-control, +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .theo-pip-close { + display: block; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .vjs-custom-control-spacer { + display: block; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin .theo-pip-close { + opacity: 1; + -webkit-transition: opacity 0.1s; + -moz-transition: opacity 0.1s; + transition: opacity 0.1s; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin.vjs-user-inactive.vjs-playing .theo-pip-close { + opacity: 0; + -webkit-transition: opacity 1s; + -moz-transition: opacity 1s; + transition: opacity 1s; +} +.theo-pip:not(.vjs-fullscreen).theoplayer-skin.theo-pip .theo-button-tooltip { + margin-bottom: 0; +} +.theo-pip:not(.vjs-fullscreen).theo-pip-top-left .theo-player-wrapper { + right: auto !important; + bottom: auto !important; + -webkit-animation: theo-pip-top-left 0.3s forwards; + -moz-animation: theo-pip-top-left 0.3s forwards; + animation: theo-pip-top-left 0.3s forwards; +} +.theo-pip:not(.vjs-fullscreen).theo-pip-top-right .theo-player-wrapper { + left: auto !important; + bottom: auto !important; + -webkit-animation: theo-pip-top-right 0.3s forwards; + -moz-animation: theo-pip-top-right 0.3s forwards; + animation: theo-pip-top-right 0.3s forwards; +} +.theo-pip:not(.vjs-fullscreen).theo-pip-bottom-left .theo-player-wrapper { + top: auto !important; + right: auto !important; + -webkit-animation: theo-pip-bottom-left 0.3s forwards; + -moz-animation: theo-pip-bottom-left 0.3s forwards; + animation: theo-pip-bottom-left 0.3s forwards; +} +.theo-pip:not(.vjs-fullscreen) .theo-player-wrapper, +.theo-pip:not(.vjs-fullscreen).theo-pip-bottom-right .theo-player-wrapper { + top: auto !important; + left: auto !important; + -webkit-animation: theo-pip-bottom-right 0.3s forwards; + -moz-animation: theo-pip-bottom-right 0.3s forwards; + animation: theo-pip-bottom-right 0.3s forwards; +} +.theo-pip:not(.vjs-fullscreen) .theo-pip-overlay { + display: block; + position: absolute; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + top: 0; +} +.theo-pip:not(.vjs-fullscreen) .theo-pip-overlay .theo-pip-overlay-text { + position: absolute; + left: 35px; + right: 35px; + bottom: 4em; + font-size: 130%; + font-weight: 500; + opacity: 0.7; +} + +@-webkit-keyframes theo-pip-bottom-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + right: 1.5em; + bottom: 1.5em; + } +} + +@-moz-keyframes theo-pip-bottom-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + right: 1.5em; + bottom: 1.5em; + } +} + +@keyframes theo-pip-bottom-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + right: 1.5em; + bottom: 1.5em; + } +} +@-webkit-keyframes theo-pip-bottom-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + left: 1.5em; + bottom: 1.5em; + } +} +@-moz-keyframes theo-pip-bottom-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + left: 1.5em; + bottom: 1.5em; + } +} +@keyframes theo-pip-bottom-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + left: 1.5em; + bottom: 1.5em; + } +} +@-webkit-keyframes theo-pip-top-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + right: 1.5em; + } +} +@-moz-keyframes theo-pip-top-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + right: 1.5em; + } +} +@keyframes theo-pip-top-right { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + right: 1.5em; + } +} +@-webkit-keyframes theo-pip-top-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + left: 1.5em; + } +} +@-moz-keyframes theo-pip-top-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + left: 1.5em; + } +} +@keyframes theo-pip-top-left { + to { + width: 320px; + height: 180px; + z-index: 1000000000; + top: 1.5em; + left: 1.5em; + } +} +.vjs-button.theo-related-button { + cursor: pointer; + -webkit-box-ordinal-group: 21; + -webkit-order: 20; + -moz-box-ordinal-group: 21; + -ms-flex-order: 20; + order: 20; + /* Hide related button and grid when no content is available */ +} +.theoplayer-skin:not(.theo-related-available) .vjs-button.theo-related-button { + display: none; +} + +.theo-related { + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + top: 0; +} +.theoplayer-skin:not(.theo-related-showing) .theo-related { + visibility: hidden; +} +.theoplayer-skin:not(.theo-related-showing) .theo-related .theo-overlay-panel { + opacity: 0; + top: 50%; +} +.theoplayer-skin.theo-related-showing .theo-button-tooltip { + display: none; +} + +.theo-related-grid { + width: 100%; + height: auto; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row wrap; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; +} +.theo-related-grid .theo-related-grid-tile { + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; + padding: 0; + border: 1px solid black; + position: relative; +} +.theo-related-grid .theo-related-grid-tile:hover .theo-related-grid-tile-content .theo-related-grid-tile-title, +.theo-related-grid .theo-related-grid-tile:hover .theo-related-grid-tile-content .theo-related-grid-tile-duration { + color: #ebebeb; + background-color: rgba(0, 0, 0, 0.85); +} +.theo-related-grid .theo-related-grid-tile:hover .theo-related-grid-tile-content .theo-related-grid-tile-image { + opacity: 1; +} +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content { + width: 100%; + padding-bottom: 56.25%; + background-size: cover; + display: block; + color: #cdcdcd; +} +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content .theo-related-grid-tile-image { + height: 100%; + width: 100%; + position: absolute; + background-size: cover; + opacity: 0.85; + -webkit-transition: opacity 0.3s; + -moz-transition: opacity 0.3s; + transition: opacity 0.3s; +} +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content .theo-related-grid-tile-title, +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content .theo-related-grid-tile-duration { + position: absolute; + background-color: rgba(0, 0, 0, 0.7); + padding: 0.4em 0.6em; + -webkit-transition: + background-color 0.3s, + color 0.3s; + -moz-transition: + background-color 0.3s, + color 0.3s; + transition: + background-color 0.3s, + color 0.3s; +} +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content .theo-related-grid-tile-title { + bottom: 0; + line-height: 1.3em; + width: 100%; + border-bottom: 0.2em solid transparent; +} +.theo-related-grid .theo-related-grid-tile .theo-related-grid-tile-content .theo-related-grid-tile-duration { + top: 0; + left: 0; + border-bottom-right-radius: 3px; +} + +/* + AVAILABLE GRID ORGANIZATION CLASSES: + theo-{1, 2, 3, 4, 6, 8, 9, 12, 15}-item-grid + + AVAILABLE TILE WIDTHS: + 20%, 25%, 33.33%, 50%, 100% + + SUPPORTED PLAYER SIZES: + theoplayer-xs (0-576), -s (576-768), -m (768-992), -l (992-1200px), -xl (12000 - ...px) +*/ +/* TILE SIZES */ +/* 1-item-grid is always a full-tile */ +.theo-1-item-grid .theo-related-grid-tile { + width: 100%; +} + +.theo-size-xs { + /* Hide third item in 3-item-grid */ + /* Hide fifth and following items in 6 to 12-item-grid */ +} +.theo-size-xs.theo-2-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-3-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-4-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-6-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-8-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-9-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-12-item-grid .theo-related-grid-tile, +.theo-size-xs.theo-15-item-grid .theo-related-grid-tile { + width: 50%; +} +.theo-size-xs.theo-3-item-grid .theo-related-grid-tile:nth-child(n + 3) { + display: none; +} +.theo-size-xs.theo-6-item-grid .theo-related-grid-tile:nth-child(n + 5), +.theo-size-xs.theo-8-item-grid .theo-related-grid-tile:nth-child(n + 5), +.theo-size-xs.theo-9-item-grid .theo-related-grid-tile:nth-child(n + 5), +.theo-size-xs.theo-12-item-grid .theo-related-grid-tile:nth-child(n + 5), +.theo-size-xs.theo-15-item-grid .theo-related-grid-tile:nth-child(n + 5) { + display: none; +} + +.theo-size-s, +.theo-size-m { + /* Hide sixth and following items in 8 to 12-item-grid */ +} +.theo-size-s.theo-2-item-grid .theo-related-grid-tile, +.theo-size-s.theo-4-item-grid .theo-related-grid-tile, +.theo-size-m.theo-2-item-grid .theo-related-grid-tile, +.theo-size-m.theo-4-item-grid .theo-related-grid-tile { + width: 50%; +} +.theo-size-s.theo-3-item-grid .theo-related-grid-tile, +.theo-size-s.theo-6-item-grid .theo-related-grid-tile, +.theo-size-s.theo-8-item-grid .theo-related-grid-tile, +.theo-size-s.theo-9-item-grid .theo-related-grid-tile, +.theo-size-s.theo-12-item-grid .theo-related-grid-tile, +.theo-size-s.theo-15-item-grid .theo-related-grid-tile, +.theo-size-m.theo-3-item-grid .theo-related-grid-tile, +.theo-size-m.theo-6-item-grid .theo-related-grid-tile, +.theo-size-m.theo-8-item-grid .theo-related-grid-tile, +.theo-size-m.theo-9-item-grid .theo-related-grid-tile, +.theo-size-m.theo-12-item-grid .theo-related-grid-tile, +.theo-size-m.theo-15-item-grid .theo-related-grid-tile { + width: 33.33%; +} +.theo-size-s.theo-8-item-grid .theo-related-grid-tile:nth-child(n + 7), +.theo-size-s.theo-12-item-grid .theo-related-grid-tile:nth-child(n + 7), +.theo-size-s.theo-15-item-grid .theo-related-grid-tile:nth-child(n + 7), +.theo-size-m.theo-8-item-grid .theo-related-grid-tile:nth-child(n + 7), +.theo-size-m.theo-12-item-grid .theo-related-grid-tile:nth-child(n + 7), +.theo-size-m.theo-15-item-grid .theo-related-grid-tile:nth-child(n + 7) { + display: none; +} + +.theo-size-l.theo-2-item-grid .theo-related-grid-tile, +.theo-size-l.theo-4-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-2-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-4-item-grid .theo-related-grid-tile { + width: 50%; +} +.theo-size-l.theo-3-item-grid .theo-related-grid-tile, +.theo-size-l.theo-6-item-grid .theo-related-grid-tile, +.theo-size-l.theo-9-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-3-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-6-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-9-item-grid .theo-related-grid-tile { + width: 33.33%; +} +.theo-size-l.theo-8-item-grid .theo-related-grid-tile, +.theo-size-l.theo-12-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-8-item-grid .theo-related-grid-tile, +.theo-size-xl.theo-12-item-grid .theo-related-grid-tile { + width: 25%; +} + +.theo-size-l.theo-15-item-grid { + /* Hide thirteenth and following items in 15-item-grid */ +} +.theo-size-l.theo-15-item-grid .theo-related-grid-tile { + width: 25%; +} +.theo-size-l.theo-15-item-grid .theo-related-grid-tile:nth-child(n + 13) { + display: none; +} + +.theo-size-xl.theo-15-item-grid .theo-related-grid-tile { + width: 20%; +} + +.vjs-button.theo-social-button { + cursor: pointer; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + -moz-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; + /* Hide related button and grid when no content is available */ +} +.theoplayer-skin:not(.theo-social-available) .vjs-button.theo-social-button { + display: none; +} + +.theo-social { + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + top: 0; +} +.theoplayer-skin:not(.theo-social-showing) .theo-social { + visibility: hidden; +} +.theoplayer-skin:not(.theo-social-showing) .theo-social .theo-overlay-panel { + opacity: 0; + top: 50%; +} +.theoplayer-skin.theo-social-showing .theo-button-tooltip { + display: none; +} + +.theo-social .theo-social-container { + width: 60%; + max-width: 750px; +} +.theo-social .theo-social-container .theo-social-icon-container .theo-social-text-container { + width: 100%; +} +.theo-social .theo-social-container .theo-social-icon-container { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.theo-social .theo-social-container .theo-social-icon-container .theo-social-iconurl { + margin: 0.5em 0.5em 0.5em 0; + min-width: 25px; + min-height: 25px; + width: 7%; +} +.theo-social .theo-social-container .theo-social-icon-container .theo-social-iconurl img { + width: 100%; + height: auto; +} +.theo-social .theo-social-container .theo-social-text-container .theo-social-content-container { + padding: 0.7em; + margin: 0.5em; + max-height: 5em; + text-overflow: ellipsis; + font-family: monospace; + font-size: 1.1em; + line-height: 1.1em; + white-space: pre-wrap; + word-wrap: break-word; + overflow: hidden; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + user-select: all; + cursor: copy; +} +.theo-social .theo-social-container .theo-social-text-container .theo-social-content-container:hover { + background-color: rgba(54, 54, 54, 0.9); +} +.theo-social .theo-social-container .theo-social-text-container .theo-social-texturl a { + color: white; + font-style: italic; +} +.theo-social .theo-social-container .theo-social-label { + font-family: monospace; + display: inline-block; + padding: 0.25em 0.5em; + margin-bottom: 0; +} + +.theo-social.theo-size-xs .theo-social-container { + width: 90%; +} +.theo-social.theo-size-xs .theo-social-container .theo-social-label { + display: none; +} +.theo-social.theo-size-xs .theo-social-container .theo-social-content-container { + padding: 0.4em; + font-size: 1em; + white-space: pre; +} + +.theo-upnext-panel { + width: 100%; + height: 100%; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + overflow: hidden; + visibility: hidden; +} +.theo-upnext-panel .theo-upnext-panel-content { + color: white; + background-color: rgba(20, 20, 20, 0.85); +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-image { + height: 100%; + background-size: cover; + position: absolute; + width: 100%; +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-autoplay svg { + cursor: pointer; + display: block; + width: 20%; + height: auto; + max-height: 100%; + padding: 1em 0; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-autoplay svg .theo-play-svg-circle { + stroke-dasharray: 458.6725274241; + stroke-dashoffset: 458.6725274241; + -webkit-transition: stroke-dashoffset 1s linear; + -moz-transition: stroke-dashoffset 1s linear; + transition: stroke-dashoffset 1s linear; +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-text { + padding: 8%; + text-align: center; + width: 100%; + position: absolute; + text-shadow: 0px 2px 4px #000000; +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-text .theo-upnext-panel-upnext { + font-weight: bold; + margin-bottom: 0.5em; + font-size: 1.7em; +} +.theo-upnext-panel .theo-upnext-panel-content .theo-upnext-panel-text .theo-upnext-panel-title { + overflow: hidden; + height: 3em; + font-size: 1.8em; +} +.theo-upnext-panel.theo-size-s .theo-upnext-panel-content .theo-upnext-panel-text .theo-upnext-panel-title { + height: 2em; +} +.theo-upnext-panel.theo-size-xs .theo-upnext-panel-content .theo-upnext-panel-text .theo-upnext-panel-title { + height: 1em; +} + +.theoplayer-skin.vjs-has-started.theo-upnext-panel-showing .theo-upnext-panel { + visibility: visible; +} +.theoplayer-skin.vjs-has-started.theo-upnext-panel-showing .vjs-button.theo-related-button { + display: none; +} +.theoplayer-skin.vjs-has-started.theo-upnext-panel-showing .vjs-button.theo-social-button { + display: none; +} + +.theo-upnext-bar { + width: 33%; + height: 15%; + position: absolute; + right: 0; + font-size: 1.25em; + bottom: 3.5em; + overflow: hidden; + max-width: 20em; + max-height: 5em; + min-height: 3em; + min-width: 10em; + cursor: pointer; +} +.theo-upnext-bar .theo-upnext-bar-content { + text-decoration: none; + color: white; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + height: 100%; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 100%; + width: 0; + background-color: rgba(20, 20, 20, 0.85); + -webkit-transition: none; + -moz-transition: none; + transition: none; + padding-right: 0.8em; + cursor: inherit; +} +.theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-image { + height: 100%; + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -ms-flex: 1; + flex: 1; + background-size: cover; + position: relative; + width: 0; +} +.theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-image .theo-upnext-bar-duration { + display: none; + bottom: 0; + right: 0; + border-top-left-radius: 3px; + position: absolute; + color: #ebebeb; + background-color: rgba(20, 20, 20, 0.85); + padding: 0.4em 0.6em; + font-size: 0.8em; +} +.theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-text { + margin: 0.5em 0 0.5em 0.5em; + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -ms-flex: 1; + flex: 1; + font-size: 0.8em; + width: 0; +} +.theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-text .theo-upnext-bar-upnext { + font-weight: bold; + margin-bottom: 0.5em; +} +.theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-text .theo-upnext-bar-title { + overflow: hidden; + height: 3em; +} +.theo-upnext-bar.theo-size-s .theo-upnext-bar-content .theo-upnext-bar-text .theo-upnext-bar-title { + height: 2em; +} +.theo-upnext-bar.theo-size-xs .theo-upnext-bar-content .theo-upnext-bar-text .theo-upnext-bar-title { + height: 1em; +} + +/* Hide upnext bar when not in showing mode */ +.theoplayer-skin:not(.theo-upnext-bar-showing) .theo-upnext-bar { + pointer-events: none; +} + +.theoplayer-skin.vjs-has-started.theo-upnext-bar-showing.vjs-user-inactive.vjs-playing:not(.theo-menu-opened) .theo-upnext-bar { + bottom: 1em; + -webkit-transition: bottom 0.1s ease-out 0.6s; + -moz-transition: bottom 0.1s ease-out 0.6s; + transition: bottom 0.1s ease-out 0.6s; +} +.theoplayer-skin.vjs-has-started.theo-upnext-bar-showing .theo-upnext-bar .theo-upnext-bar-content { + left: 0; + width: 100%; + -webkit-transition: left 0.2s ease-in-out; + -moz-transition: left 0.2s ease-in-out; + transition: left 0.2s ease-in-out; +} +.theoplayer-skin.vjs-has-started.theo-upnext-bar-showing .theo-upnext-bar .theo-upnext-bar-image .theo-upnext-bar-duration { + display: inline; +} + +.theoplayer-skin.theo-mobile .theo-upnext-bar { + bottom: 5em; +} +.theoplayer-skin.theo-mobile .theo-upnext-bar .theo-upnext-bar-content .theo-upnext-bar-image .theo-upnext-bar-duration { + padding: 0.2em 0.3em; + font-size: 0.7em; +} + +.theoplayer-skin .theo-overlay-panel { + background-color: black; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + top: 0; + opacity: 1; + -webkit-transition: + opacity 0.2s cubic-bezier(0.4, 0, 1, 1), + top 0.2s cubic-bezier(0.4, 0, 1, 1); + -moz-transition: + opacity 0.2s cubic-bezier(0.4, 0, 1, 1), + top 0.2s cubic-bezier(0.4, 0, 1, 1); + transition: + opacity 0.2s cubic-bezier(0.4, 0, 1, 1), + top 0.2s cubic-bezier(0.4, 0, 1, 1); + position: absolute; + width: 100%; + height: 100%; +} +.theoplayer-skin .theo-overlay-panel .theo-close-button { + display: block; + width: 1.5em; + height: 1.5em; + margin: 0.75em; + padding: 0; + border-radius: 50%; + line-height: 1em; + text-align: center; + cursor: pointer; +} +.theoplayer-skin .theo-overlay-panel .theo-close-button:after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: -0.75em; +} + +.theo-upnext-bar.theo-upnext-verizonmedia { + cursor: default; +} + +.theo-verizonmedia-content-notification-bar { + position: absolute; + bottom: 3.5em; + width: 100%; + text-align: center; +} +.theo-verizonmedia-content-notification-bar .theo-verizonmedia-content-notification { + width: 100%; + font-size: 1.25em; + color: white; + background-color: rgba(51, 51, 51, 0.6); + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.theo-verizonmedia-content-notification-bar .theo-verizonmedia-content-notification .theo-verizonmedia-content-notification-thumbnail { + width: 100%; + height: 100%; + -o-object-fit: contain; + object-fit: contain; + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -ms-flex: 1; + flex: 1; +} +.theo-verizonmedia-content-notification-bar .theo-verizonmedia-content-notification .theo-verizonmedia-content-notification-description { + -webkit-box-flex: 2; + -webkit-flex: 2; + -moz-box-flex: 2; + -ms-flex: 2; + flex: 2; + margin: 1em; +} +.theo-verizonmedia-content-notification-bar .theo-verizonmedia-content-notification .theo-verizonmedia-content-notification-countdown { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -ms-flex: 1; + flex: 1; + margin: 1em 1em 1em 0; +} +.theo-verizonmedia-content-notification-bar.theo-verizonmedia-content-notification-bar-ios { + bottom: 6em; +} + +.theo-verizonmedia-adbreak-marker-controller { + position: absolute; + height: 100%; + width: 100%; +} + +.theo-verizonmedia-marker { + position: absolute; + height: 100%; +} + +.theo-verizonmedia-marker-adbreak { + background-color: rgba(255, 0, 0, 0.3); +} + +.theo-verizonmedia-marker-asset { + border-left: 1px solid black; + border-right: 1px solid black; +} + +.theo-360-compass { + position: absolute; + top: 0; + right: 0; + z-index: 1; + margin: 0.5em; + font-size: 26px; + width: 1em; + height: 1em; + border: 0.025em solid #fff; + border-radius: 100%; + pointer-events: none; +} +.theoplayer-skin.vjs-error .theo-360-compass, +.theoplayer-skin:not(.vjs-has-started) .theo-360-compass { + display: none; +} +.theo-360-compass:before, +.theo-360-compass:after { + content: ''; + position: absolute; + width: 0; + height: 0; +} +.theo-360-compass:before { + top: 50%; + left: 50%; + border: 0.075em solid #fff; + border-radius: 100%; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.theo-360-compass:after { + top: 0; + left: 50%; + border-left: 0.1em solid transparent; + border-right: 0.1em solid transparent; + border-bottom: 0.1em solid #fff; + -webkit-transform: translate(-50%, -100%); + -moz-transform: translate(-50%, -100%); + transform: translate(-50%, -100%); + -webkit-transform-origin: 50% 100%; + -moz-transform-origin: 50% 100%; + transform-origin: 50% 100%; +} + +.theo-360-fov { + overflow: hidden; + position: absolute; + left: 0; + top: 0; + width: 50%; + height: 50%; + -webkit-transform-origin: 100% 100%; + -moz-transform-origin: 100% 100%; + transform-origin: 100% 100%; + -webkit-transform: scale(0.875) rotate(40deg) skew(-10deg); + -moz-transform: scale(0.875) rotate(40deg) skew(-10deg); + transform: scale(0.875) rotate(40deg) skew(-10deg); +} +.theo-360-fov:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 200%; + height: 200%; + border: 0.35em solid rgba(255, 255, 255, 0.75); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 100%; + -webkit-transform: skew(10deg); + -moz-transform: skew(10deg); + transform: skew(10deg); +} + +.theoplayer-skin .theo-vr-container { + -webkit-box-ordinal-group: 95; + -webkit-order: 94; + -moz-box-ordinal-group: 95; + -ms-flex-order: 94; + order: 94; +} + +.theo-upcoming-ad-notification { + width: auto; + height: auto; + position: absolute; + margin-right: 1em; + right: 0; + font-size: 1.25em; + bottom: 3.5em; + overflow: hidden; + min-width: 10em; + display: none; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + z-index: 0; +} + +@media (max-width: 375px) { + .theo-upcoming-ad-notification { + font-size: 1.15em; + bottom: 3.6em; + } +} +.theo-upcoming-ad-notification-text { + color: white; + height: 100%; + text-shadow: 0.1em 0.1em 0.2em black; +} + +.theo-upcoming-ad-notification-show-browser { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; +} + +.theo-upcoming-ad-notification-show-mobile { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + bottom: auto; + top: 1em; + left: 1em; + right: auto; + font-size: 1.05em; + margin: 0; +} + +.vjs-user-inactive.vjs-playing .theo-upcoming-ad-notification.theo-upcoming-ad-notification-show-browser { + bottom: 1em; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} + +.theo-probably-keyboard-focus :focus, +.theo-probably-keyboard-focus .focus-within { + -webkit-box-shadow: inset 0 0 0 2px rgba(27, 127, 204, 0.8); + box-shadow: inset 0 0 0 2px rgba(27, 127, 204, 0.8); +} +.theo-probably-keyboard-focus .focus-within :focus { + /* handled by .focus-within */ + -webkit-box-shadow: none; + box-shadow: none; +} +.theo-probably-keyboard-focus .vjs-big-play-button:focus { + border-radius: 0; +} +.theo-probably-keyboard-focus .vjs-progress-holder:focus { + -webkit-box-shadow: 0 0 0 2px rgba(27, 127, 204, 0.8); + box-shadow: 0 0 0 2px rgba(27, 127, 204, 0.8); +} +.theo-probably-keyboard-focus .theo-social-container a:focus, +.theo-probably-keyboard-focus .theo-related-grid a:focus { + outline: none; +} +.theo-probably-keyboard-focus .theo-related-grid-tile-content:focus:before { + content: ''; + -webkit-box-shadow: inset 0 0 0 2px rgba(27, 127, 204, 0.8); + box-shadow: inset 0 0 0 2px rgba(27, 127, 204, 0.8); + top: 0; + right: 0; + bottom: 0; + left: 0; + position: absolute; + z-index: 1; +} diff --git a/apps/e2e/web/stub/CastButtonStub.tsx b/apps/e2e/web/stub/CastButtonStub.tsx new file mode 100644 index 00000000..85d5e6cf --- /dev/null +++ b/apps/e2e/web/stub/CastButtonStub.tsx @@ -0,0 +1,7 @@ +import type { ViewProps } from 'react-native'; +import React, { JSX } from 'react'; + +// Provides a stub for react-native-google-cast on web. +export function CastButton(_props: ViewProps): JSX.Element { + return <>; +} diff --git a/apps/e2e/web/stub/Config.ts b/apps/e2e/web/stub/Config.ts new file mode 100644 index 00000000..18a28770 --- /dev/null +++ b/apps/e2e/web/stub/Config.ts @@ -0,0 +1,3 @@ +// Expose the global env variable for test purposes +window.GLOBAL_ENV = GLOBAL_ENV || {}; +export default GLOBAL_ENV; diff --git a/apps/e2e/web/stub/global.d.ts b/apps/e2e/web/stub/global.d.ts new file mode 100644 index 00000000..54e39f2a --- /dev/null +++ b/apps/e2e/web/stub/global.d.ts @@ -0,0 +1,5 @@ +type EnvConfig = { [key: string]: string }; +interface Window { + GLOBAL_ENV: EnvConfig; +} +declare const GLOBAL_ENV: EnvConfig; diff --git a/apps/e2e/web/webpack.config.js b/apps/e2e/web/webpack.config.js new file mode 100644 index 00000000..d7843810 --- /dev/null +++ b/apps/e2e/web/webpack.config.js @@ -0,0 +1,142 @@ +/* eslint-disable @typescript-eslint/no-var-requires,no-undef */ +const path = require('path'); +const webpack = require('webpack'); +const dotenv = require('dotenv'); +const fs = require('fs'); +const HTMLWebpackPlugin = require('html-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); +const workspaceDirectory = path.resolve(__dirname, '../../..'); +const appDirectory = path.resolve(__dirname, '..'); + +// A folder for any stub components we need in case there is no counterpart for it on react-native-web. +const stubDirectory = path.resolve(appDirectory, './web/stub/'); + +const HTMLWebpackPluginConfig = new HTMLWebpackPlugin({ + template: path.resolve(appDirectory, './web/public/index.html'), + filename: 'index.html', + inject: 'body', +}); + +// THEOplayer's libraryLocation. +const libraryLocation = 'theoplayer'; + +// Webpack's output location +const outputLocation = 'dist'; + +// Prepare env keys +const envPath = path.resolve(appDirectory, '.env'); +const env = dotenv.parse(fs.readFileSync(envPath)); +const envKeys = { + 'GLOBAL_ENV': `{${Object.entries(env) + .map(([key, value]) => `${JSON.stringify(key)}:${JSON.stringify(value)}`) + .join(',')}}`, +}; + +const CopyWebpackPluginConfig = new CopyWebpackPlugin({ + patterns: [ + { + // Copy transmuxer worker files. + // THEOplayer will find them by setting `libraryLocation` in the playerConfiguration. + from: path.resolve(workspaceDirectory, './node_modules/theoplayer/THEOplayer.transmux.*').replace(/\\/g, '/'), + to: `${libraryLocation}/[name][ext]`, + }, + { + // Copy service worker + // THEOplayer will find them by setting `libraryLocation` in the playerConfiguration. + from: path.resolve(workspaceDirectory, './node_modules/theoplayer/theoplayer.sw.js').replace(/\\/g, '/'), + to: `${libraryLocation}/[name][ext]`, + }, + { + // Copy CSS files + from: path.resolve(appDirectory, './web/public/*.css').replace(/\\/g, '/'), + to: `[name][ext]`, + }, + ], +}); + +// This is needed for webpack to compile JavaScript. +// Many OSS React Native packages are not compiled to ES5 before being +// published. If you depend on uncompiled packages they may cause webpack build +// errors. To fix this webpack can be configured to compile to the necessary +// `node_module`. +// +// /\.tsx?$/ : process all tsx files. +// /.*@theoplayer\/.*\.js$/ : process all js files from @theoplayer packages to apply the root import alias. This is only needed for this example. +const babelLoaderConfiguration = { + test: [/\.tsx?$/, /.*@theoplayer\/.*\.js$/], + exclude: ['/**/*.d.ts', '/**/node_modules/'], + use: { + loader: 'babel-loader', + options: { + cacheDirectory: true, + // The 'metro-react-native-babel-preset' preset is recommended to match React Native's packager + presets: ['module:@react-native/babel-preset'], + // Re-write paths to import only the modules needed by the app + plugins: ['react-native-web'], + }, + }, +}; + +// This is needed for webpack to import static images in JavaScript files. +const imageLoaderConfiguration = { + test: /\.(gif|jpe?g|png|svg)$/, + use: { + loader: 'react-native-web-image-loader', + }, +}; + +module.exports = { + entry: [ + // load any web API polyfills + // path.resolve(appDirectory, 'polyfills-web.js'), + // your web-specific entry file + path.resolve(appDirectory, 'index.web.tsx'), + ], + + // configures where the build ends up + output: { + filename: 'bundle.web.js', + path: path.resolve(appDirectory, outputLocation), + }, + + module: { + rules: [babelLoaderConfiguration, imageLoaderConfiguration], + }, + resolve: { + extensions: ['.web.js', '.web.ts', '.web.tsx', '.js', '.ts', '.tsx'], + alias: { + // [pkg.name]: path.resolve(workspaceDirectory, pkg.source), + + 'react-native$': 'react-native-web', + 'react-native-url-polyfill': 'url-polyfill', + 'react-native-google-cast': path.resolve(stubDirectory, 'CastButtonStub'), + 'react-native-web': path.resolve(appDirectory, 'node_modules/react-native-web'), + 'react-native-svg': path.resolve(appDirectory, 'node_modules/react-native-svg-web'), + 'react-native-config': path.resolve(stubDirectory, 'Config'), + + // Avoid duplicate react env. + react: path.resolve(appDirectory, 'node_modules/react'), + }, + }, + plugins: [HTMLWebpackPluginConfig, CopyWebpackPluginConfig, new NodePolyfillPlugin(), new webpack.DefinePlugin(envKeys)], + devServer: { + // Tells dev-server to open the browser after server had been started. + open: true, + historyApiFallback: true, + static: [ + { + directory: path.join(appDirectory, 'web/public'), + }, + ], + // Hot reload on source changes + hot: true, + client: { + overlay: { + errors: true, + warnings: false, + runtimeErrors: false, + }, + }, + }, +}; From 3afd203e9d86550d3614b47b8a04917ec80d19d6 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Thu, 29 Jan 2026 15:30:36 +0100 Subject: [PATCH 28/40] Attach player to bitmovin collector --- bitmovin/ios/Connector/BitmovinConnector.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bitmovin/ios/Connector/BitmovinConnector.swift b/bitmovin/ios/Connector/BitmovinConnector.swift index 8076ff0b..d22a1152 100644 --- a/bitmovin/ios/Connector/BitmovinConnector.swift +++ b/bitmovin/ios/Connector/BitmovinConnector.swift @@ -14,7 +14,8 @@ class BitmovinConnector { let config: AnalyticsConfig = BitmovinAdapter.parseConfig(bitmovinConfig) let metadata: DefaultMetadata = BitmovinAdapter.parseDefaultMetadata(defaultMetadata) self.theoplayerCollector = THEOplayerCollector.THEOplayerCollectorFactory.create(config: config, defaultMetadata: metadata) - log("Initialized Bitmovin Connector with config: \(config) and default metadata: \(metadata)") + log("Initialized Bitmovin Connector with config: \(bitmovinConfig) and default metadata: \(defaultMetadata ?? [:])") + self.theoplayerCollector.attach(to: player) } func updateSourceMetadata(_ metadata: [String:Any]) -> Void { From 3113623d16b8e302c515b602447547ed7e99af67 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Thu, 29 Jan 2026 15:32:19 +0100 Subject: [PATCH 29/40] Add programChange placeholder for iOS --- bitmovin/ios/Connector/BitmovinConnector.swift | 18 ++++++++++++------ .../ios/THEOplayerBitmovinRCTBitmovinAPI.swift | 16 +++++++++++++--- bitmovin/ios/THEOplayerBitmovinRCTBridge.m | 4 +++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/bitmovin/ios/Connector/BitmovinConnector.swift b/bitmovin/ios/Connector/BitmovinConnector.swift index d22a1152..5a0a911e 100644 --- a/bitmovin/ios/Connector/BitmovinConnector.swift +++ b/bitmovin/ios/Connector/BitmovinConnector.swift @@ -18,23 +18,29 @@ class BitmovinConnector { self.theoplayerCollector.attach(to: player) } - func updateSourceMetadata(_ metadata: [String:Any]) -> Void { - self.theoplayerCollector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(metadata) - log("Updated source metadata: \(self.theoplayerCollector.sourceMetadata)") + func updateSourceMetadata(_ sourceMetadata: [String:Any]) -> Void { + self.theoplayerCollector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(sourceMetadata) + log("Updated source metadata: \(sourceMetadata)") + } + + func programChange(_ sourceMetadata: [String:Any]) -> Void { + // let newSourceMetadata = BitmovinAdapter.parseSourceMetadata(sourceMetadata) + // TODO: self.theoplayerCollector.programChange(newSourceMetadata) + log("TODO: Notifying program change with source metadata: \(sourceMetadata)") } func updateCustomMetadata(_ customData: [String:Any]) -> Void { self.theoplayerCollector.customData = BitmovinAdapter.parseCustomData(customData) - log("Updated custom data: \(self.theoplayerCollector.customData)") + log("Updated custom data: \(customData)") } func sendCustomDataEvent(_ customData: [String:Any]) -> Void { - log("Sending custom data event is not yet implemented.") + log("TODO: Sending custom data event is not yet implemented.") // TODO: Implement when THEOplayerCollector supports sending custom data events } func destroy() -> Void { - log("Destroying Bitmovin Connector is not yet implemented.") + log("TODO: Destroying Bitmovin Connector is not yet implemented.") // TODO: Implement when THEOplayerCollector supports detaching } } diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift index a578a9f9..edfa82a2 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift +++ b/bitmovin/ios/THEOplayerBitmovinRCTBitmovinAPI.swift @@ -42,16 +42,26 @@ class THEOplayerBitmovinRCTBitmovinAPI: NSObject, RCTBridgeModule { } } - @objc(updateSourceMetadata:metadata:) - func updateSourceMetadata(_ node: NSNumber, metadata: NSDictionary) { + @objc(updateSourceMetadata:sourceMetadata:) + func updateSourceMetadata(_ node: NSNumber, sourceMetadata: NSDictionary) { log("updateSourceMetadata triggered.") DispatchQueue.main.async { - if let sourceMetadata = metadata as? [String:Any] { + if let sourceMetadata = sourceMetadata as? [String:Any] { self.connectors[node]?.updateSourceMetadata(sourceMetadata) } } } + @objc(programChange:sourceMetadata:) + func programChange(_ node: NSNumber, sourceMetadata: NSDictionary) { + log("programChange triggered.") + DispatchQueue.main.async { + if let sourceMetadata = sourceMetadata as? [String:Any] { + self.connectors[node]?.programChange(sourceMetadata) + } + } + } + @objc(updateCustomMetadata:customData:) func updateCustomMetadata(_ node: NSNumber, customData: NSDictionary) { log("updateCustomMetadata triggered.") diff --git a/bitmovin/ios/THEOplayerBitmovinRCTBridge.m b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m index 8b81faf9..5bf76f54 100644 --- a/bitmovin/ios/THEOplayerBitmovinRCTBridge.m +++ b/bitmovin/ios/THEOplayerBitmovinRCTBridge.m @@ -11,10 +11,12 @@ @interface RCT_EXTERN_REMAP_MODULE(BitmovinModule, THEOplayerBitmovinRCTBitmovin bitmovinConfig:(nonnull NSDictionary *)bitmovinConfig defaultMetadata:(nullable NSDictionary *)defaultMetadata) -RCT_EXTERN_METHOD(updateSourceMetadata:(nonnull NSNumber *)node metadata:(nonnull NSDictionary *)metadata) +RCT_EXTERN_METHOD(updateSourceMetadata:(nonnull NSNumber *)node sourceMetadata:(nonnull NSDictionary *)sourceMetadata) RCT_EXTERN_METHOD(updateCustomMetadata:(nonnull NSNumber *)node customData:(nonnull NSDictionary *)customData) +RCT_EXTERN_METHOD(programChange:(nonnull NSNumber *)node sourceMetadata:(nonnull NSDictionary *)sourceMetadata) + RCT_EXTERN_METHOD(sendCustomDataEvent:(nonnull NSNumber *)node customData:(nonnull NSDictionary *)customData) RCT_EXTERN_METHOD(destroy:(nonnull NSNumber *)node) From 1c875372e77e424b7646ed1fe26141de14bb9f85 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 15:39:57 +0100 Subject: [PATCH 30/40] Bump version --- bitmovin/package.json | 2 +- package-lock.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bitmovin/package.json b/bitmovin/package.json index 4509a1ec..73b7ba8d 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -1,6 +1,6 @@ { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.6", + "version": "1.0.0-alpha.9", "description": "Bitmovin analytics connector for @theoplayer/react-native", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/package-lock.json b/package-lock.json index 589c4572..1476afb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -134,7 +134,7 @@ }, "bitmovin": { "name": "@theoplayer/react-native-analytics-bitmovin", - "version": "1.0.0-alpha.6", + "version": "1.0.0-alpha.9", "license": "SEE LICENSE AT https://www.theoplayer.com/terms", "peerDependencies": { "react": "*", From 2e05ae50767e2f1279b8ba4767585afead2f9112 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 15:44:06 +0100 Subject: [PATCH 31/40] Update changelog --- bitmovin/CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bitmovin/CHANGELOG.md b/bitmovin/CHANGELOG.md index 7565ff35..851c0061 100644 --- a/bitmovin/CHANGELOG.md +++ b/bitmovin/CHANGELOG.md @@ -1,7 +1 @@ # @theoplayer/react-native-analytics-bitmovin - -## 1.0.0 - -### ✨ Features - -- Initial release From 9fd9eb7febc56ae92b3dcddba09cfd35cd806adf Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 29 Jan 2026 15:44:32 +0100 Subject: [PATCH 32/40] Add changeset entry --- .changeset/rude-lamps-teach.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rude-lamps-teach.md diff --git a/.changeset/rude-lamps-teach.md b/.changeset/rude-lamps-teach.md new file mode 100644 index 00000000..001c387a --- /dev/null +++ b/.changeset/rude-lamps-teach.md @@ -0,0 +1,5 @@ +--- +'@theoplayer/react-native-analytics-bitmovin': patch +--- + +Initial release. From 1ab95144550170ffc58a9e77dd2946fd81782924 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 13:57:34 +0100 Subject: [PATCH 33/40] Disable THEOplayerCollector usage until available through pod and threading issues resolved --- bitmovin/ios/Connector/BitmovinConnector.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bitmovin/ios/Connector/BitmovinConnector.swift b/bitmovin/ios/Connector/BitmovinConnector.swift index 5a0a911e..9efbd6da 100644 --- a/bitmovin/ios/Connector/BitmovinConnector.swift +++ b/bitmovin/ios/Connector/BitmovinConnector.swift @@ -5,22 +5,22 @@ import Foundation import THEOplayerSDK import CoreCollector -import THEOplayerCollector +// TODO: import THEOplayerCollector // Update when THEOplayerCollector module is available through cocoapods. class BitmovinConnector { - private let theoplayerCollector: THEOplayerCollector.THEOplayerCollectorApi + // TODO: private let theoplayerCollector: THEOplayerCollector.THEOplayerCollectorApi init(player: THEOplayer, bitmovinConfig: [String:Any], defaultMetadata: [String:Any]? = nil) { let config: AnalyticsConfig = BitmovinAdapter.parseConfig(bitmovinConfig) let metadata: DefaultMetadata = BitmovinAdapter.parseDefaultMetadata(defaultMetadata) - self.theoplayerCollector = THEOplayerCollector.THEOplayerCollectorFactory.create(config: config, defaultMetadata: metadata) - log("Initialized Bitmovin Connector with config: \(bitmovinConfig) and default metadata: \(defaultMetadata ?? [:])") - self.theoplayerCollector.attach(to: player) + // TODO: self.theoplayerCollector = THEOplayerCollector.THEOplayerCollectorFactory.create(config: config, defaultMetadata: metadata) + // TODO: self.theoplayerCollector.attach(to: player) + log("TODO: Initialized Bitmovin Connector with config: \(bitmovinConfig) and default metadata: \(defaultMetadata ?? [:])") } func updateSourceMetadata(_ sourceMetadata: [String:Any]) -> Void { - self.theoplayerCollector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(sourceMetadata) - log("Updated source metadata: \(sourceMetadata)") + // TODO: self.theoplayerCollector.sourceMetadata = BitmovinAdapter.parseSourceMetadata(sourceMetadata) + log("TODO: Updated source metadata: \(sourceMetadata)") } func programChange(_ sourceMetadata: [String:Any]) -> Void { @@ -30,8 +30,8 @@ class BitmovinConnector { } func updateCustomMetadata(_ customData: [String:Any]) -> Void { - self.theoplayerCollector.customData = BitmovinAdapter.parseCustomData(customData) - log("Updated custom data: \(customData)") + // TODO: self.theoplayerCollector.customData = BitmovinAdapter.parseCustomData(customData) + log("TODO: Updated custom data: \(customData)") } func sendCustomDataEvent(_ customData: [String:Any]) -> Void { From 02cd99493e33a9954e2e49f545609c33eeab3761 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 30 Jan 2026 14:01:43 +0100 Subject: [PATCH 34/40] Update license --- bitmovin/LICENSE | 33 +++++++++++++++++++++++++++++++++ bitmovin/package.json | 4 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 bitmovin/LICENSE diff --git a/bitmovin/LICENSE b/bitmovin/LICENSE new file mode 100644 index 00000000..ed130fc5 --- /dev/null +++ b/bitmovin/LICENSE @@ -0,0 +1,33 @@ +The Clear BSD License + +Copyright (c) 2025 Dolby International AB +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the disclaimer +below) provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bitmovin/package.json b/bitmovin/package.json index 73b7ba8d..f14ea7dc 100644 --- a/bitmovin/package.json +++ b/bitmovin/package.json @@ -46,8 +46,8 @@ "type": "git", "url": "git@github.com:THEOplayer/react-native-connectors.git" }, - "author": "THEO Technologies", - "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "author": "Dolby Laboratories, Inc.", + "license": "BSD-3-Clause-Clear", "homepage": "https://github.com/THEOplayer/react-native-connectors/tree/main/bitmovin#readme", "publishConfig": { "registry": "https://registry.npmjs.org/" From 90a93d0908e2d8832a63b83ca843327eeebd152b Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 30 Jan 2026 14:04:26 +0100 Subject: [PATCH 35/40] Disable setting customData on Android --- .../reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt index 09268dec..95d392ce 100644 --- a/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt +++ b/bitmovin/android/src/main/java/com/theoplayer/reactnative/bitmovin/ReactTHEOplayerBitmovinModule.kt @@ -43,13 +43,14 @@ class ReactTHEOplayerBitmovinModule(context: ReactApplicationContext) : @ReactMethod fun updateCustomData(tag: Int, customData: ReadableMap) { - bitmovinConnectors[tag]?.customData = BitmovinAdapter.parseCustomData(customData) + // TODO: resolve threading issue first + //bitmovinConnectors[tag]?.customData = BitmovinAdapter.parseCustomData(customData) } @ReactMethod fun programChange(tag: Int, sourceMetadata: ReadableMap) { - val t = "NYI" -// bitmovinConnectors[tag]?.programChange(BitmovinAdapter.parseSourceMetadata(sourceMetadata)) + // NYI + //bitmovinConnectors[tag]?.programChange(BitmovinAdapter.parseSourceMetadata(sourceMetadata)) } @ReactMethod From 77d5b5c656802bb6c8cd925a63b3590c09c44521 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 14:27:47 +0100 Subject: [PATCH 36/40] Make InitBitmovin public on API --- bitmovin/src/api/hooks/useBitmovin.ts | 2 +- bitmovin/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bitmovin/src/api/hooks/useBitmovin.ts b/bitmovin/src/api/hooks/useBitmovin.ts index 9b7719c8..e10ac454 100644 --- a/bitmovin/src/api/hooks/useBitmovin.ts +++ b/bitmovin/src/api/hooks/useBitmovin.ts @@ -3,7 +3,7 @@ import { RefObject, useEffect, useRef } from 'react'; import { AnalyticsConfig, BitmovinConnector } from '@theoplayer/react-native-analytics-bitmovin'; import { DefaultMetadata } from '../DefaultMetadata'; -type InitBitmovin = (player: THEOplayer | undefined, defaultMetadata?: DefaultMetadata) => void; +export type InitBitmovin = (player: THEOplayer | undefined, defaultMetadata?: DefaultMetadata) => void; export function useBitmovin(config: AnalyticsConfig): [RefObject, InitBitmovin] { const connector = useRef(undefined); diff --git a/bitmovin/src/index.ts b/bitmovin/src/index.ts index 06d4859b..41baf304 100644 --- a/bitmovin/src/index.ts +++ b/bitmovin/src/index.ts @@ -3,5 +3,5 @@ export * from './api/AnalyticsConfig'; export * from './api/CustomData'; export * from './api/SourceMetadata'; export * from './api/DefaultMetadata'; -export { useBitmovin } from './api/hooks/useBitmovin'; +export * from './api/hooks/useBitmovin'; export { sdkVersions } from './internal/version/Version'; From 1f4cc0cfaa7da8122b0717598d9e7c5533bdf3b0 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 30 Jan 2026 15:51:46 +0100 Subject: [PATCH 37/40] Align device-info version --- apps/e2e/package-lock.json | 6 ++++-- apps/e2e/package.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/e2e/package-lock.json b/apps/e2e/package-lock.json index 428f270b..6b59e206 100644 --- a/apps/e2e/package-lock.json +++ b/apps/e2e/package-lock.json @@ -15,7 +15,7 @@ "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", "react-native-config": "^1.6.1", - "react-native-device-info": "^10.14.0", + "react-native-device-info": "^14.0.4", "react-native-safe-area-context": "^5.6.2", "react-native-status-bar-height": "^2.6.0", "react-native-svg": "^15.11.2", @@ -12607,7 +12607,9 @@ } }, "node_modules/react-native-device-info": { - "version": "10.14.0", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-14.1.1.tgz", + "integrity": "sha512-lXFpe6DJmzbQXNLWxlMHP2xuTU5gwrKAvI8dCAZuERhW9eOXSubOQIesk9lIBnsi9pI19GMrcpJEvs4ARPRYmw==", "license": "MIT", "peerDependencies": { "react-native": "*" diff --git a/apps/e2e/package.json b/apps/e2e/package.json index a005dda4..ecc3ebfc 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -25,7 +25,7 @@ "react-dom": "19.0.0", "react-native": "npm:react-native-tvos@^0.79.0-0", "react-native-config": "^1.6.1", - "react-native-device-info": "^10.14.0", + "react-native-device-info": "^14.0.4", "react-native-safe-area-context": "^5.6.2", "react-native-status-bar-height": "^2.6.0", "react-native-svg": "^15.11.2", From 1e114e6f3fb54d451d6ba1e7ed5f307fa0ed3333 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 16:11:59 +0100 Subject: [PATCH 38/40] Remove adobe-edge pod from e2e PodFile --- apps/e2e/ios/Podfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/e2e/ios/Podfile b/apps/e2e/ios/Podfile index 71e7f173..2cbed5ae 100755 --- a/apps/e2e/ios/Podfile +++ b/apps/e2e/ios/Podfile @@ -32,7 +32,6 @@ target 'ReactNativeTHEOplayer' do pod 'react-native-theoplayer-conviva', :path => '../../../conviva' pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen' pod 'react-native-theoplayer-adobe', :path => '../../../adobe' - pod 'react-native-theoplayer-adobe-edge', :path => '../../../adobe-edge' pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin' google_cast_redirect @@ -50,7 +49,6 @@ target 'ReactNativeTHEOplayer-tvOS' do pod 'react-native-theoplayer-conviva', :path => '../../../conviva' pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen' pod 'react-native-theoplayer-adobe', :path => '../../../adobe' - pod 'react-native-theoplayer-adobe-edge', :path => '../../../adobe-edge' pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin' end From 23d2c6df98cf0276460333de66619a8ef3799a70 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 30 Jan 2026 16:17:53 +0100 Subject: [PATCH 39/40] Add alias --- apps/e2e/metro.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/e2e/metro.config.js b/apps/e2e/metro.config.js index f3f1604b..b69fc482 100644 --- a/apps/e2e/metro.config.js +++ b/apps/e2e/metro.config.js @@ -6,7 +6,8 @@ const packages = [ 'react', 'react-native', 'react-native-theoplayer', - '@babel/runtime' + '@babel/runtime', + 'react-native-device-info' ]; const connectors = [ From 7cbceb48d133f0ae71e2dd7e88bdc135bf8bc4c1 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 17:01:26 +0100 Subject: [PATCH 40/40] Add extra watch folder for root package dependencies --- apps/e2e/metro.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/e2e/metro.config.js b/apps/e2e/metro.config.js index b69fc482..53bdb9ab 100644 --- a/apps/e2e/metro.config.js +++ b/apps/e2e/metro.config.js @@ -6,8 +6,7 @@ const packages = [ 'react', 'react-native', 'react-native-theoplayer', - '@babel/runtime', - 'react-native-device-info' + '@babel/runtime' ]; const connectors = [ @@ -35,6 +34,7 @@ const connectors = [ const config = { projectRoot: __dirname, watchFolders: [ + path.resolve(root, 'node_modules'), ...connectors.map(cn => path.resolve(root, cn)), ], resolver: {