mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5983edd21b | ||
|
|
bf13ecba7f | ||
|
|
5f8807acc2 | ||
|
|
026e22bb8d | ||
|
|
f1894393ca | ||
|
|
77ee24ddce | ||
|
|
327057fad5 | ||
|
|
cd71c9620c | ||
|
|
9bb53c02dd | ||
|
|
f67078df07 | ||
|
|
3b185e4bce | ||
|
|
8b2e309479 |
@@ -118,7 +118,6 @@ async function collectResults(discordWebHook) {
|
||||
} else {
|
||||
console.log('Discord webhook not set');
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Initialize Firebase client
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
|
||||
|
||||
import type {HostInstance} from 'react-native';
|
||||
|
||||
import * as Fantom from '@react-native/fantom';
|
||||
import * as React from 'react';
|
||||
import {createRef} from 'react';
|
||||
import {ImageBackground} from 'react-native';
|
||||
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
|
||||
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
|
||||
|
||||
describe('<ImageBackground>', () => {
|
||||
describe('props', () => {
|
||||
describe('ImageProps', () => {
|
||||
it('can have local source', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<ImageBackground source={require('./img/img1.png')} />);
|
||||
});
|
||||
|
||||
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
|
||||
<rn-image
|
||||
source-scale="1"
|
||||
source-size="{1, 1}"
|
||||
source-type="local"
|
||||
source-uri="file://drawable-mdpi/packages_reactnative_libraries_image___tests___img_img1.png"
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
it('can have remote source', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ImageBackground
|
||||
source={{
|
||||
uri: 'https://reactnative.dev/img/tiny_logo.png',
|
||||
width: 100,
|
||||
height: 100,
|
||||
scale: 2,
|
||||
cache: 'only-if-cached',
|
||||
method: 'POST',
|
||||
body: 'name=React+Native',
|
||||
headers: {
|
||||
Authorization: 'Basic RandomString',
|
||||
},
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
|
||||
<rn-image
|
||||
source-body="name=React+Native"
|
||||
source-cache="only-if-cached"
|
||||
source-header-Authorization="Basic RandomString"
|
||||
source-method="POST"
|
||||
source-scale="2"
|
||||
source-size="{100, 100}"
|
||||
source-type="remote"
|
||||
source-uri="https://reactnative.dev/img/tiny_logo.png"
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
it('can have srcSet', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ImageBackground srcSet="https://reactnative.dev/img/tiny_logo.png 1x, https://reactnative.dev/img/header_logo.svg 2x" />,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
|
||||
<rn-image
|
||||
source-1x-scale="1"
|
||||
source-1x-type="remote"
|
||||
source-1x-uri="https://reactnative.dev/img/tiny_logo.png"
|
||||
source-2x-scale="2"
|
||||
source-2x-type="remote"
|
||||
source-2x-uri="https://reactnative.dev/img/header_logo.svg"
|
||||
/>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('style', () => {
|
||||
it('can be set', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<ImageBackground style={{width: 100, height: 100}} />);
|
||||
});
|
||||
|
||||
expect(
|
||||
root.getRenderedOutput({props: ['width|height']}).toJSX(),
|
||||
).toEqual(<rn-image width="100.000000" height="100.000000" />);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ref', () => {
|
||||
it('Allows to set a reference to the inner `Image` component', () => {
|
||||
const elementRef = createRef<HostInstance>();
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<ImageBackground imageRef={elementRef} />);
|
||||
});
|
||||
|
||||
const image = ensureInstance(elementRef.current, ReactNativeElement);
|
||||
expect(image.tagName).toBe('RN:Image');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,9 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow
|
||||
* @generated SignedSource<<16b364e89f43b8a47832b0dfb98af11e>>
|
||||
*
|
||||
* This file was sync'd from the facebook/react repository.
|
||||
* @generated SignedSource<<cf323fc5ca893bab5669c7d321660412>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow strict-local
|
||||
* @generated SignedSource<<1dd9e9c3f20e37ae14e485fc6ee3d9e9>>
|
||||
*
|
||||
* This file was sync'd from the facebook/react repository.
|
||||
* @generated SignedSource<<908f5fb85384725318e261f40e49d9a6>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow
|
||||
* @generated SignedSource<<e2c46705ed927302dbe9332dafba459d>>
|
||||
*
|
||||
* This file was sync'd from the facebook/react repository.
|
||||
* @generated SignedSource<<8f46fdc9267fcc4fdc9e76842fe24066>>
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
||||
+1
-3
@@ -7,9 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow strict-local
|
||||
* @generated SignedSource<<e8dce0e82b831c91465d04b49fb48ab2>>
|
||||
*
|
||||
* This file was sync'd from the facebook/react repository.
|
||||
* @generated SignedSource<<83073425aa3f71ced2c8c51f25a25938>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
+1
-3
@@ -7,9 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow strict-local
|
||||
* @generated SignedSource<<556d1487de0b9e4a09cbc67dd130a884>>
|
||||
*
|
||||
* This file was sync'd from the facebook/react repository.
|
||||
* @generated SignedSource<<52163887de05f1cff05388145cf85b3b>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -3348,8 +3348,10 @@ public final class com/facebook/react/uimanager/DisplayMetricsHolder {
|
||||
public static final fun getDisplayMetricsWritableMap (D)Lcom/facebook/react/bridge/WritableMap;
|
||||
public static final fun getScreenDisplayMetrics ()Landroid/util/DisplayMetrics;
|
||||
public static final fun getWindowDisplayMetrics ()Landroid/util/DisplayMetrics;
|
||||
public static final fun initDisplayMetrics (Landroid/content/Context;)V
|
||||
public static final fun initDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
|
||||
public static final fun initScreenDisplayMetrics (Landroid/content/Context;)V
|
||||
public static final fun initScreenDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
|
||||
public static final fun initWindowDisplayMetrics (Landroid/content/Context;)V
|
||||
public static final fun initWindowDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
|
||||
public static final fun setScreenDisplayMetrics (Landroid/util/DisplayMetrics;)V
|
||||
public static final fun setWindowDisplayMetrics (Landroid/util/DisplayMetrics;)V
|
||||
}
|
||||
|
||||
@@ -630,6 +630,7 @@ dependencies {
|
||||
api(libs.androidx.autofill)
|
||||
api(libs.androidx.swiperefreshlayout)
|
||||
api(libs.androidx.tracing)
|
||||
api(libs.androidx.window)
|
||||
|
||||
api(libs.fbjni)
|
||||
api(libs.fresco)
|
||||
|
||||
+15
-1
@@ -229,6 +229,9 @@ public class ReactInstanceManager {
|
||||
return new ReactInstanceManagerBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @noinspection deprecation
|
||||
*/
|
||||
/* package */ ReactInstanceManager(
|
||||
Context applicationContext,
|
||||
@Nullable Activity currentActivity,
|
||||
@@ -259,7 +262,11 @@ public class ReactInstanceManager {
|
||||
FLog.d(TAG, "ReactInstanceManager.ctor()");
|
||||
initializeSoLoaderIfNecessary(applicationContext);
|
||||
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(applicationContext);
|
||||
|
||||
if (currentActivity != null) {
|
||||
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
|
||||
}
|
||||
|
||||
// See {@code ReactInstanceManagerBuilder} for description of all flags here.
|
||||
mApplicationContext = applicationContext;
|
||||
@@ -924,6 +931,13 @@ public class ReactInstanceManager {
|
||||
|
||||
ReactContext currentReactContext = getCurrentReactContext();
|
||||
if (currentReactContext != null) {
|
||||
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext);
|
||||
Activity currentActivity = currentReactContext.getCurrentActivity();
|
||||
|
||||
if (currentActivity != null) {
|
||||
DisplayMetricsHolder.initWindowDisplayMetrics(currentActivity);
|
||||
}
|
||||
|
||||
AppearanceModule appearanceModule =
|
||||
currentReactContext.getNativeModule(AppearanceModule.class);
|
||||
|
||||
|
||||
+6
-5
@@ -136,9 +136,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
setRootViewTag(ReactRootViewTagGenerator.getNextRootViewTag());
|
||||
setClipChildren(false);
|
||||
|
||||
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
|
||||
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
|
||||
}
|
||||
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
|
||||
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -883,7 +882,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
private int mDeviceRotation = 0;
|
||||
|
||||
/* package */ CustomGlobalLayoutListener() {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext().getApplicationContext());
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(getContext());
|
||||
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(getContext());
|
||||
mVisibleViewArea = new Rect();
|
||||
mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60);
|
||||
}
|
||||
@@ -1006,7 +1006,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
return;
|
||||
}
|
||||
mDeviceRotation = rotation;
|
||||
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
|
||||
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
|
||||
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
|
||||
emitOrientationChanged(rotation);
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -25,6 +25,11 @@ import com.facebook.react.packagerconnection.RequestHandler
|
||||
*/
|
||||
internal class DefaultDevSupportManagerFactory : DevSupportManagerFactory {
|
||||
|
||||
@Deprecated(
|
||||
"Use the other create() method with useDevSupport parameter for New Architecture. This method will be removed in a future release.",
|
||||
replaceWith =
|
||||
ReplaceWith(
|
||||
"create(applicationContext, reactInstanceManagerHelper, packagerPathForJSBundleName, enableOnCreate, redBoxHandler, devBundleDownloadListener, minNumShakes, customPackagerCommandHandlers, surfaceDelegateFactory, devLoadingViewManager, pausedInDebuggerOverlayManager)"))
|
||||
override fun create(
|
||||
applicationContext: Context,
|
||||
reactInstanceManagerHelper: ReactInstanceDevHelper,
|
||||
|
||||
+6
@@ -22,6 +22,12 @@ public interface DevSupportManagerFactory {
|
||||
* Factory used by the Old Architecture flow to create a [DevSupportManager] and a
|
||||
* [BridgeDevSupportManager]
|
||||
*/
|
||||
@Deprecated(
|
||||
message =
|
||||
"Use the other create() method with useDevSupport parameter for New Architecture. This method will be removed in a future release.",
|
||||
replaceWith =
|
||||
ReplaceWith(
|
||||
"create(applicationContext, reactInstanceManagerHelper, packagerPathForJSBundleName, enableOnCreate, redBoxHandler, devBundleDownloadListener, minNumShakes, customPackagerCommandHandlers, surfaceDelegateFactory, devLoadingViewManager, pausedInDebuggerOverlayManager)"))
|
||||
public fun create(
|
||||
applicationContext: Context,
|
||||
reactInstanceManagerHelper: ReactInstanceDevHelper,
|
||||
|
||||
+4
-2
@@ -15,7 +15,8 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder.getDisplayMetricsWritableMap
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder.initDisplayMetricsIfNotInitialized
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized
|
||||
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
|
||||
|
||||
/** Module that exposes Android Constants to JS. */
|
||||
@@ -26,7 +27,8 @@ internal class DeviceInfoModule(reactContext: ReactApplicationContext) :
|
||||
private var previousDisplayMetrics: ReadableMap? = null
|
||||
|
||||
init {
|
||||
initDisplayMetricsIfNotInitialized(reactContext)
|
||||
initScreenDisplayMetricsIfNotInitialized(reactContext)
|
||||
reactContext.currentActivity?.let { initWindowDisplayMetricsIfNotInitialized(it) }
|
||||
reactContext.addLifecycleEventListener(this)
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -625,9 +625,8 @@ public class ReactHostImpl(
|
||||
override fun onConfigurationChanged(context: Context) {
|
||||
val currentReactContext = this.currentReactContext
|
||||
if (currentReactContext != null) {
|
||||
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
|
||||
DisplayMetricsHolder.initDisplayMetrics(currentReactContext)
|
||||
}
|
||||
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext)
|
||||
currentReactContext.currentActivity?.let { DisplayMetricsHolder.initWindowDisplayMetrics(it) }
|
||||
|
||||
val appearanceModule = currentReactContext.getNativeModule(AppearanceModule::class.java)
|
||||
appearanceModule?.onConfigurationChanged(context)
|
||||
@@ -918,6 +917,7 @@ public class ReactHostImpl(
|
||||
val instance =
|
||||
ReactInstance(
|
||||
reactContext,
|
||||
currentActivity,
|
||||
reactHostDelegate,
|
||||
componentFactory,
|
||||
devSupportManager,
|
||||
|
||||
+4
-1
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.runtime
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.res.AssetManager
|
||||
import android.view.View
|
||||
import com.facebook.common.logging.FLog
|
||||
@@ -88,6 +89,7 @@ import kotlin.jvm.JvmStatic
|
||||
@UnstableReactNativeAPI
|
||||
internal class ReactInstance(
|
||||
private val context: BridgelessReactContext,
|
||||
private val activity: Activity?,
|
||||
delegate: ReactHostDelegate,
|
||||
componentFactory: ComponentFactory,
|
||||
devSupportManager: DevSupportManager,
|
||||
@@ -240,7 +242,8 @@ internal class ReactInstance(
|
||||
FabricUIManager(context, ViewManagerRegistry(viewManagerResolver), eventBeatManager)
|
||||
|
||||
// Misc initialization that needs to be done before Fabric init
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(context)
|
||||
activity?.let { DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(it) }
|
||||
|
||||
val binding = FabricUIManagerBinding()
|
||||
binding.register(
|
||||
|
||||
+46
-17
@@ -13,16 +13,20 @@ import android.util.DisplayMetrics
|
||||
import android.view.WindowManager
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.bridge.WritableNativeMap
|
||||
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
|
||||
|
||||
/**
|
||||
* Holds an instance of the current DisplayMetrics so we don't have to thread it through all the
|
||||
* classes that need it.
|
||||
*/
|
||||
public object DisplayMetricsHolder {
|
||||
private const val INITIALIZATION_MISSING_MESSAGE =
|
||||
"DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics"
|
||||
private const val SCREEN_INITIALIZATION_MISSING_MESSAGE =
|
||||
"DisplayMetricsHolder must be initialized with initScreenDisplayMetricsIfNotInitialized or initScreenDisplayMetrics"
|
||||
private const val WINDOW_INITIALIZATION_MISSING_MESSAGE =
|
||||
"DisplayMetricsHolder must be initialized with initWindowDisplayMetricsIfNotInitialized or initWindowDisplayMetrics"
|
||||
|
||||
@JvmStatic private var windowDisplayMetrics: DisplayMetrics? = null
|
||||
@JvmStatic private var screenDisplayMetrics: DisplayMetrics? = null
|
||||
@@ -30,7 +34,7 @@ public object DisplayMetricsHolder {
|
||||
/** The metrics of the window associated to the Context used to initialize ReactNative */
|
||||
@JvmStatic
|
||||
public fun getWindowDisplayMetrics(): DisplayMetrics {
|
||||
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
|
||||
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
|
||||
return windowDisplayMetrics as DisplayMetrics
|
||||
}
|
||||
|
||||
@@ -42,7 +46,7 @@ public object DisplayMetricsHolder {
|
||||
/** Screen metrics returns the metrics of the default screen on the device. */
|
||||
@JvmStatic
|
||||
public fun getScreenDisplayMetrics(): DisplayMetrics {
|
||||
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
|
||||
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
|
||||
return screenDisplayMetrics as DisplayMetrics
|
||||
}
|
||||
|
||||
@@ -52,33 +56,58 @@ public object DisplayMetricsHolder {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun initDisplayMetricsIfNotInitialized(context: Context) {
|
||||
if (screenDisplayMetrics != null) {
|
||||
return
|
||||
public fun initScreenDisplayMetricsIfNotInitialized(context: Context) {
|
||||
if (screenDisplayMetrics == null) {
|
||||
initScreenDisplayMetrics(context)
|
||||
}
|
||||
initDisplayMetrics(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun initDisplayMetrics(context: Context) {
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
windowDisplayMetrics = displayMetrics
|
||||
val screenDisplayMetrics = DisplayMetrics()
|
||||
screenDisplayMetrics.setTo(displayMetrics)
|
||||
public fun initWindowDisplayMetricsIfNotInitialized(context: Context) {
|
||||
if (windowDisplayMetrics == null) {
|
||||
initWindowDisplayMetrics(context)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun initScreenDisplayMetrics(context: Context) {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
displayMetrics.setTo(context.resources.displayMetrics)
|
||||
|
||||
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
// Get the real display metrics if we are using API level 17 or higher.
|
||||
// The real metrics include system decor elements (e.g. soft menu bar).
|
||||
//
|
||||
// See:
|
||||
// http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics)
|
||||
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
|
||||
DisplayMetricsHolder.screenDisplayMetrics = screenDisplayMetrics
|
||||
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(displayMetrics)
|
||||
screenDisplayMetrics = displayMetrics
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Unlike [initScreenDisplayMetrics], this method needs a UiContext (Activity of
|
||||
* InputMethodService) else WindowMetircsCalculator will throw an exception.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun initWindowDisplayMetrics(context: Context) {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
displayMetrics.setTo(context.resources.displayMetrics)
|
||||
|
||||
if (isEdgeToEdgeFeatureFlagOn) {
|
||||
WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context).let { windowMetrics
|
||||
->
|
||||
displayMetrics.widthPixels = windowMetrics.bounds.width()
|
||||
displayMetrics.heightPixels = windowMetrics.bounds.height()
|
||||
}
|
||||
}
|
||||
|
||||
windowDisplayMetrics = displayMetrics
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun getDisplayMetricsWritableMap(fontScale: Double): WritableMap {
|
||||
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
|
||||
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
|
||||
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
|
||||
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
|
||||
|
||||
return WritableNativeMap().apply {
|
||||
putMap(
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@ public object PixelUtil {
|
||||
}
|
||||
|
||||
return TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getWindowDisplayMetrics())
|
||||
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getScreenDisplayMetrics())
|
||||
}
|
||||
|
||||
/** Convert from DIP to PX */
|
||||
@@ -37,7 +37,7 @@ public object PixelUtil {
|
||||
return Float.NaN
|
||||
}
|
||||
|
||||
val displayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics()
|
||||
val displayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics()
|
||||
val scaledValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, displayMetrics)
|
||||
|
||||
if (maxFontScale >= 1) {
|
||||
@@ -60,13 +60,13 @@ public object PixelUtil {
|
||||
return Float.NaN
|
||||
}
|
||||
|
||||
return value / DisplayMetricsHolder.getWindowDisplayMetrics().density
|
||||
return value / DisplayMetricsHolder.getScreenDisplayMetrics().density
|
||||
}
|
||||
|
||||
/** @return [Float] that represents the density of the display metrics for device screen. */
|
||||
@JvmStatic
|
||||
public fun getDisplayMetricDensity(): Float =
|
||||
DisplayMetricsHolder.getWindowDisplayMetrics().density
|
||||
DisplayMetricsHolder.getScreenDisplayMetrics().density
|
||||
|
||||
/* Kotlin extensions */
|
||||
public fun Int.dpToPx(): Float = toPixelFromDIP(this.toFloat())
|
||||
|
||||
+11
-2
@@ -12,6 +12,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_M
|
||||
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
|
||||
import static com.facebook.react.uimanager.common.UIManagerType.LEGACY;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.content.res.Configuration;
|
||||
import android.view.View;
|
||||
@@ -126,7 +127,11 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
ViewManagerResolver viewManagerResolver,
|
||||
int minTimeLeftInFrameForNonBatchedOperationMs) {
|
||||
super(reactContext);
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext);
|
||||
Activity currentActivity = reactContext.getCurrentActivity();
|
||||
if (currentActivity != null) {
|
||||
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
|
||||
}
|
||||
mEventDispatcher = new EventDispatcherImpl(reactContext);
|
||||
mModuleConstants = createConstants(viewManagerResolver);
|
||||
mCustomDirectEvents = UIManagerModuleConstants.directEventTypeConstants;
|
||||
@@ -146,7 +151,11 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
List<ViewManager> viewManagersList,
|
||||
int minTimeLeftInFrameForNonBatchedOperationMs) {
|
||||
super(reactContext);
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext);
|
||||
Activity currentActivity = reactContext.getCurrentActivity();
|
||||
if (currentActivity != null) {
|
||||
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
|
||||
}
|
||||
mEventDispatcher = new EventDispatcherImpl(reactContext);
|
||||
mCustomDirectEvents = MapBuilder.newHashMap();
|
||||
mModuleConstants = createConstants(viewManagersList, null, mCustomDirectEvents);
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
@@ -27,6 +29,9 @@ import com.facebook.react.uimanager.IllegalViewOperationException
|
||||
* order to animate layout when a valid configuration has been supplied by the application.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal abstract class AbstractLayoutAnimation {
|
||||
var interpolator: Interpolator? = null
|
||||
var delayMs: Int = 0
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -15,6 +17,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
* creation.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal enum class AnimatedPropertyType {
|
||||
OPACITY,
|
||||
SCALE_X,
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
@@ -17,6 +19,9 @@ import com.facebook.react.uimanager.IllegalViewOperationException
|
||||
|
||||
/** Class responsible for default layout animation, i.e animation of view creation and deletion. */
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal abstract class BaseLayoutAnimation : AbstractLayoutAnimation() {
|
||||
abstract fun isReverse(): Boolean
|
||||
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -14,6 +16,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
* Enum representing the different interpolators that can be used in layout animation configuration.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal enum class InterpolatorType {
|
||||
LINEAR,
|
||||
EASE_IN,
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.util.SparseArray
|
||||
@@ -29,6 +31,9 @@ import javax.annotation.concurrent.NotThreadSafe
|
||||
*/
|
||||
@NotThreadSafe
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
public open class LayoutAnimationController {
|
||||
private val layoutCreateAnimation: AbstractLayoutAnimation = LayoutCreateAnimation()
|
||||
private val layoutUpdateAnimation: AbstractLayoutAnimation = LayoutUpdateAnimation()
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -12,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
|
||||
/** Listener invoked when a layout animation has completed. */
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
public fun interface LayoutAnimationListener {
|
||||
public fun onAnimationEnd()
|
||||
}
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -15,6 +17,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
|
||||
* Enum representing the different animation type that can be specified in layout animation config.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal enum class LayoutAnimationType {
|
||||
CREATE,
|
||||
UPDATE,
|
||||
|
||||
+2
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -16,6 +18,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
|
||||
* config was supplied for the layout animation of DELETE type.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal class LayoutDeleteAnimation : BaseLayoutAnimation() {
|
||||
|
||||
override fun isReverse(): Boolean = true
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
@@ -12,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
|
||||
/** Interface for an animation type that takes care of updating the view layout. */
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal interface LayoutHandlingAnimation {
|
||||
/**
|
||||
* Notifies the animation of a layout update in case one occurs during the animation. This avoids
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
@@ -19,6 +21,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
|
||||
* was supplied for the layout animation of UPDATE type.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal class LayoutUpdateAnimation : AbstractLayoutAnimation() {
|
||||
|
||||
override fun isValid(): Boolean = durationMs > 0
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
@@ -21,6 +23,9 @@ import java.lang.ref.WeakReference
|
||||
* optimize rendering performances.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal class OpacityAnimation(view: View, private val startOpacity: Float, endOpacity: Float) :
|
||||
Animation() {
|
||||
private val viewRef = WeakReference(view)
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
@@ -22,6 +24,9 @@ import java.lang.ref.WeakReference
|
||||
* ScaleAnimation and TranslateAnimation.
|
||||
*/
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal class PositionAndSizeAnimation(view: View, x: Int, y: Int, width: Int, height: Int) :
|
||||
Animation(), LayoutHandlingAnimation {
|
||||
private val viewRef = WeakReference(view)
|
||||
|
||||
+5
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.animation.Interpolator
|
||||
@@ -19,6 +21,9 @@ import kotlin.math.sin
|
||||
/** Simple spring interpolator */
|
||||
// TODO(7613736): Improve spring interpolator with friction and damping variable support
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING)
|
||||
internal class SimpleSpringInterpolator @JvmOverloads constructor(springDamping: Float = FACTOR) :
|
||||
Interpolator {
|
||||
private val _springDamping: Float = springDamping
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.yoga;
|
||||
|
||||
public class YogaConstants {
|
||||
|
||||
public static final float UNDEFINED = Float.NaN;
|
||||
|
||||
public static boolean isUndefined(float value) {
|
||||
return Float.compare(value, UNDEFINED) == 0;
|
||||
}
|
||||
|
||||
public static boolean isUndefined(YogaValue value) {
|
||||
return value.unit == YogaUnit.UNDEFINED;
|
||||
}
|
||||
|
||||
public static float getUndefined() {
|
||||
return UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.yoga
|
||||
|
||||
public object YogaConstants {
|
||||
@JvmField public val UNDEFINED: Float = Float.NaN
|
||||
|
||||
@JvmStatic public fun isUndefined(value: Float): Boolean = value.compareTo(UNDEFINED) == 0
|
||||
|
||||
@JvmStatic public fun isUndefined(value: YogaValue): Boolean = value.unit == YogaUnit.UNDEFINED
|
||||
|
||||
@JvmStatic public fun getUndefined(): Float = UNDEFINED
|
||||
}
|
||||
@@ -71,7 +71,8 @@ class RootViewTest {
|
||||
reactContext = spy(BridgeReactContext(RuntimeEnvironment.getApplication()))
|
||||
reactContext.initializeWithInstance(catalystInstanceMock)
|
||||
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext)
|
||||
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext)
|
||||
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(reactContext)
|
||||
val uiManagerModuleMock: UIManagerModule = mock()
|
||||
whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java))
|
||||
.thenReturn(uiManagerModuleMock)
|
||||
|
||||
+22
@@ -11,12 +11,18 @@
|
||||
|
||||
package com.facebook.react.bridge
|
||||
|
||||
import android.app.Application
|
||||
import com.facebook.react.bridge.queue.MessageQueueThreadSpec
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfiguration
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationImpl
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.runtime.BridgelessReactContext
|
||||
import com.facebook.react.runtime.ReactHostImpl
|
||||
import com.facebook.react.runtime.internal.bolts.Task
|
||||
import com.facebook.react.uimanager.UIManagerModule
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
|
||||
@@ -49,4 +55,20 @@ object ReactTestHelper {
|
||||
whenever(reactInstance.isDestroyed).thenReturn(false)
|
||||
return reactInstance
|
||||
}
|
||||
|
||||
@OptIn(UnstableReactNativeAPI::class)
|
||||
fun createTestReactApplicationContext(application: Application): ReactApplicationContext {
|
||||
val reactHost =
|
||||
spy(
|
||||
ReactHostImpl(
|
||||
RuntimeEnvironment.getApplication(),
|
||||
mock(),
|
||||
mock(),
|
||||
Task.Companion.IMMEDIATE_EXECUTOR,
|
||||
Task.Companion.IMMEDIATE_EXECUTOR,
|
||||
false /* allowPackagerServerAccess */,
|
||||
false /* useDevSupport */,
|
||||
))
|
||||
return BridgelessReactContext(application, reactHost)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -467,7 +467,7 @@ class TouchEventDispatchTest {
|
||||
metrics.xdpi = 1f
|
||||
metrics.ydpi = 1f
|
||||
metrics.density = 1f
|
||||
DisplayMetricsHolder.setWindowDisplayMetrics(metrics)
|
||||
DisplayMetricsHolder.setScreenDisplayMetrics(metrics)
|
||||
|
||||
val reactContext = ReactTestHelper.createCatalystContextForTest()
|
||||
|
||||
|
||||
+16
-7
@@ -5,36 +5,45 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.modules.clipboard
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import com.facebook.react.bridge.BridgeReactContext
|
||||
import com.facebook.react.bridge.ReactTestHelper.createTestReactApplicationContext
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
|
||||
import com.facebook.testutils.shadows.ShadowSoLoader
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("ClipboardManager", "DeprecatedClass")
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowSoLoader::class])
|
||||
class ClipboardModuleTest {
|
||||
private lateinit var clipboardModule: ClipboardModule
|
||||
private lateinit var clipboardManager: ClipboardManager
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
clipboardModule = ClipboardModule(BridgeReactContext(RuntimeEnvironment.getApplication()))
|
||||
ReactNativeFeatureFlagsForTests.setUp()
|
||||
clipboardModule =
|
||||
ClipboardModule(createTestReactApplicationContext(RuntimeEnvironment.getApplication()))
|
||||
clipboardManager =
|
||||
RuntimeEnvironment.getApplication().getSystemService(Context.CLIPBOARD_SERVICE)
|
||||
as ClipboardManager
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
ReactNativeFeatureFlags.dangerouslyReset()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
fun testSetString() {
|
||||
clipboardModule.setString(TEST_CONTENT)
|
||||
|
||||
+2
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
|
||||
+2
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
+2
@@ -5,6 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager.layoutanimation
|
||||
|
||||
import android.view.View
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class ColorStopTest {
|
||||
fun setUp() {
|
||||
val metrics = DisplayMetrics()
|
||||
metrics.density = 1f
|
||||
DisplayMetricsHolder.setWindowDisplayMetrics(metrics)
|
||||
DisplayMetricsHolder.setScreenDisplayMetrics(metrics)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-2
@@ -75,14 +75,14 @@ class ReactImagePropertyTest {
|
||||
context.initializeWithInstance(catalystInstanceMock)
|
||||
themeContext = ThemedReactContext(context, context, null, -1)
|
||||
Fresco.initialize(context)
|
||||
DisplayMetricsHolder.setWindowDisplayMetrics(DisplayMetrics())
|
||||
DisplayMetricsHolder.setScreenDisplayMetrics(DisplayMetrics())
|
||||
|
||||
ReactNativeFeatureFlagsForTests.setUp()
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
DisplayMetricsHolder.setWindowDisplayMetrics(null)
|
||||
DisplayMetricsHolder.setScreenDisplayMetrics(null)
|
||||
rnLog.close()
|
||||
flogMock.close()
|
||||
}
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ class ReactTextInputPropertyTest {
|
||||
context.initializeWithInstance(catalystInstanceMock)
|
||||
themedContext = ThemedReactContext(context, context.baseContext, null, ID_NULL)
|
||||
manager = ReactTextInputManager()
|
||||
DisplayMetricsHolder.setWindowDisplayMetrics(DisplayMetrics())
|
||||
DisplayMetricsHolder.setScreenDisplayMetrics(DisplayMetrics())
|
||||
view = manager.createViewInstance(themedContext)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ class ReactVirtualViewTest {
|
||||
|
||||
val displayMetricsHolder = mockStatic(DisplayMetricsHolder::class.java)
|
||||
displayMetricsHolder
|
||||
.`when`<DisplayMetrics> { DisplayMetricsHolder.getWindowDisplayMetrics() }
|
||||
.`when`<DisplayMetrics> { DisplayMetricsHolder.getScreenDisplayMetrics() }
|
||||
.thenAnswer { DisplayMetrics().apply { density = 1f } }
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
||||
extern const char AndroidSwitchComponentName[] = "AndroidSwitch";
|
||||
|
||||
void AndroidSwitchShadowNode::setAndroidSwitchMeasurementsManager(
|
||||
|
||||
+1
@@ -15,6 +15,7 @@
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
||||
extern const char AndroidSwitchComponentName[];
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,6 +16,7 @@ androidx-swiperefreshlayout = "1.1.0"
|
||||
androidx-test = "1.5.0"
|
||||
androidx-test-junit = "1.2.1"
|
||||
androidx-tracing = "1.1.0"
|
||||
androidx-window = "1.4.0"
|
||||
assertj = "3.21.0"
|
||||
binary-compatibility-validator = "0.13.2"
|
||||
download = "5.4.0"
|
||||
@@ -64,6 +65,7 @@ androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-
|
||||
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test" }
|
||||
androidx-tracing = { module = "androidx.tracing:tracing", version.ref = "androidx-tracing" }
|
||||
androidx-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
|
||||
androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" }
|
||||
|
||||
fbjni = { module = "com.facebook.fbjni:fbjni", version.ref = "fbjni" }
|
||||
fresco = { module = "com.facebook.fresco:fresco", version.ref = "fresco" }
|
||||
|
||||
@@ -377,7 +377,7 @@ end
|
||||
|
||||
# This method can be used to set the fast_float config
|
||||
# that can be used to configure libraries.
|
||||
def set_fast_float_config(fmt_config)
|
||||
def set_fast_float_config(fast_float_config)
|
||||
Helpers::Constants.set_fast_float_config(fast_float_config)
|
||||
end
|
||||
|
||||
|
||||
+19
-22
@@ -8,6 +8,8 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {markdownTable} from './utils';
|
||||
|
||||
type TestTaskTiming = {
|
||||
name: string,
|
||||
latency: {
|
||||
@@ -31,7 +33,7 @@ export const printBenchmarkResultsRanking = (
|
||||
testArtifact: mixed,
|
||||
}>,
|
||||
) => {
|
||||
const testTaskTimings: {[string]: Array<[string, number]>} = {};
|
||||
const testTaskTimings: {[string]: {[string]: number}} = {};
|
||||
let numTestVariants = 0;
|
||||
|
||||
for (const testResult of testResults) {
|
||||
@@ -49,12 +51,9 @@ export const printBenchmarkResultsRanking = (
|
||||
for (const taskTiming of testArtifact.timings) {
|
||||
const taskName = taskTiming.name;
|
||||
if (testTaskTimings[taskName] === undefined) {
|
||||
testTaskTimings[taskName] = [];
|
||||
testTaskTimings[taskName] = {};
|
||||
}
|
||||
testTaskTimings[taskName].push([
|
||||
testResult.title,
|
||||
taskTiming.latency.p50,
|
||||
]);
|
||||
testTaskTimings[taskName][testResult.title] = taskTiming.latency.p50;
|
||||
}
|
||||
}
|
||||
if (numTestVariants <= 1 || Object.keys(testTaskTimings).length === 0) {
|
||||
@@ -62,25 +61,23 @@ export const printBenchmarkResultsRanking = (
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort by each task's execution times
|
||||
// Find relative execution times for tasks
|
||||
const results: {[string]: {[string]: string}} = {};
|
||||
for (const taskName in testTaskTimings) {
|
||||
testTaskTimings[taskName].sort((a, b) => a[1] - b[1]);
|
||||
const kv = Object.entries(testTaskTimings[taskName]);
|
||||
kv.sort((a, b) => a[1] - b[1]);
|
||||
const bestTiming = kv[0][1];
|
||||
results[taskName] = {};
|
||||
kv.forEach(([key, val]) => {
|
||||
results[taskName][key] =
|
||||
`${val.toFixed(3)}ms ${getTimingDelta(bestTiming, val)}`;
|
||||
});
|
||||
results[taskName][kv[0][0]] = `🏆 ${bestTiming.toFixed(3)}ms`;
|
||||
}
|
||||
|
||||
// Print the rankings
|
||||
console.log('### Benchmark Results Ranking ###');
|
||||
for (const taskName in testTaskTimings) {
|
||||
console.log(`> ${taskName}:`);
|
||||
let lastTiming;
|
||||
for (const [i, [testVariationName, latency]] of testTaskTimings[
|
||||
taskName
|
||||
].entries()) {
|
||||
console.log(
|
||||
` ${i + 1}. ${testVariationName}: ${latency.toFixed(2)}ms ${getTimingDelta(lastTiming, latency)}`,
|
||||
);
|
||||
lastTiming = latency;
|
||||
}
|
||||
}
|
||||
console.log('### Benchmark Times Comparison (p50): ###');
|
||||
console.log(markdownTable(results, 'Task name'));
|
||||
console.log('');
|
||||
};
|
||||
|
||||
function getTimingDelta(lastTiming: ?number, currentTiming: ?number): string {
|
||||
|
||||
+61
@@ -371,3 +371,64 @@ export function printConsoleLog(log: ConsoleLogMessage): void {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a markdown table corresponding to the given data, adopted from the RN console.table polyfill implementation
|
||||
export function markdownTable(
|
||||
data: {[string]: {[string]: string}},
|
||||
indexColumnName?: string = '',
|
||||
): string {
|
||||
const repeat = (element: string, n: number) =>
|
||||
Array.apply(null, Array(n)).map(() => element);
|
||||
|
||||
const rows = Object.keys(data).map((key: string) => ({
|
||||
[indexColumnName]: key,
|
||||
...data[key],
|
||||
}));
|
||||
|
||||
if (rows.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const columns = Array.from(
|
||||
rows.reduce((columnSet: Set<string>, row) => {
|
||||
Object.keys(row).forEach(key => columnSet.add(key));
|
||||
return columnSet;
|
||||
}, new Set()),
|
||||
);
|
||||
const stringRows: Array<Array<string>> = [];
|
||||
const columnWidths = [];
|
||||
|
||||
// Figure out max cell width for each column
|
||||
columns.forEach((k, i) => {
|
||||
columnWidths[i] = k.length;
|
||||
for (let j = 0; j < rows.length; j++) {
|
||||
const cellStr = rows[j][k];
|
||||
stringRows[j] = stringRows[j] || [];
|
||||
stringRows[j][i] = cellStr;
|
||||
columnWidths[i] = Math.max(columnWidths[i], cellStr.length);
|
||||
}
|
||||
});
|
||||
|
||||
// Join all elements in the row into a single string with | separators
|
||||
// (appends extra spaces to each cell to make separators | aligned)
|
||||
const joinRow = (row: Array<string>, space?: string = ' ') => {
|
||||
const cells = row.map((cell: string, i) => {
|
||||
const extraSpaces = repeat(' ', columnWidths[i] - cell.length).join('');
|
||||
return cell + extraSpaces;
|
||||
});
|
||||
return '| ' + cells.join(space + '|' + space) + ' |';
|
||||
};
|
||||
|
||||
const separators = columnWidths.map(columnWidth =>
|
||||
repeat('-', columnWidth).join(''),
|
||||
);
|
||||
const separatorRow = joinRow(separators);
|
||||
const header = joinRow(columns);
|
||||
const table = [header, separatorRow];
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
table.push(joinRow(stringRows[i]));
|
||||
}
|
||||
|
||||
return '\n' + table.join('\n');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user