mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
35
Commits
@@ -20,8 +20,6 @@ runs:
|
||||
- name: Set React Native Version
|
||||
shell: bash
|
||||
run: node ./scripts/releases/set-rn-artifacts-version.js --build-type ${{ inputs.release-type }}
|
||||
# We don't want to re-set the artifacts version if we're on the release branch.
|
||||
if: ${{ !contains(github.ref, '-stable') }}
|
||||
- name: Setup gradle
|
||||
uses: ./.github/actions/setup-gradle
|
||||
with:
|
||||
|
||||
@@ -157,7 +157,7 @@ jobs:
|
||||
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
||||
|
||||
test_ios_rntester:
|
||||
runs-on: macos-13
|
||||
runs-on: macos-13-large
|
||||
needs:
|
||||
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos]
|
||||
env:
|
||||
@@ -369,6 +369,11 @@ jobs:
|
||||
sed -i 's/newArchEnabled=true/newArchEnabled=false/' android/gradle.properties
|
||||
fi
|
||||
|
||||
if [[ ${{matrix.jsengine}} == "JSC" ]]; then
|
||||
echo "Using JSC instead of Hermes"
|
||||
sed -i 's/hermesEnabled=true/hermesEnabled=false/' android/gradle.properties
|
||||
fi
|
||||
|
||||
# Build
|
||||
cd android
|
||||
CAPITALIZED_FLAVOR=$(echo "${{ matrix.flavor }}" | awk '{print toupper(substr($0, 1, 1)) substr($0, 2)}')
|
||||
|
||||
@@ -6,3 +6,4 @@ ruby ">= 2.6.10"
|
||||
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
|
||||
gem 'xcodeproj', '< 1.26.0'
|
||||
gem 'concurrent-ruby', '< 1.3.4'
|
||||
|
||||
+2
-2
@@ -49,8 +49,8 @@
|
||||
"@babel/preset-flow": "^7.24.7",
|
||||
"@definitelytyped/dtslint": "^0.0.127",
|
||||
"@jest/create-cache-key-function": "^29.6.3",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/metro-config": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.78.0",
|
||||
"@react-native/metro-config": "0.78.0",
|
||||
"@tsconfig/node18": "1.0.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/assets-registry",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Asset support code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-plugin-codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Babel plugin to generate native module and view manager code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/traverse": "^7.25.3",
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.78.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2"
|
||||
|
||||
@@ -15,7 +15,7 @@ Start the React Native development server.
|
||||
#### Usage
|
||||
|
||||
```sh
|
||||
npx react-native start [options]
|
||||
npx @react-native-community/cli start [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
@@ -37,6 +37,7 @@ npx react-native start [options]
|
||||
| `--cert <path>` | Specify path to a custom SSL cert. |
|
||||
| `--config <string>` | Path to the CLI configuration file. |
|
||||
| `--no-interactive` | Disable interactive mode. |
|
||||
| `--client-logs` | **[Deprecated]** Enable plain text JavaScript log streaming for all connected apps. |
|
||||
|
||||
### `bundle`
|
||||
|
||||
@@ -45,7 +46,7 @@ Build the bundle for the provided JavaScript entry file.
|
||||
#### Usage
|
||||
|
||||
```sh
|
||||
npx react-native bundle --entry-file <path> [options]
|
||||
npx @react-native-community/cli bundle --entry-file <path> [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/community-cli-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Core CLI commands for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -22,8 +22,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/dev-middleware": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/dev-middleware": "0.78.0",
|
||||
"@react-native/metro-babel-transformer": "0.78.0",
|
||||
"chalk": "^4.0.0",
|
||||
"debug": "^2.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
|
||||
@@ -95,6 +95,14 @@ const startCommand: Command = {
|
||||
name: '--no-interactive',
|
||||
description: 'Disables interactive mode',
|
||||
},
|
||||
{
|
||||
name: '--client-logs',
|
||||
description:
|
||||
'[Deprecated] Enable plain text JavaScript log streaming for all ' +
|
||||
'connected apps. This feature is deprecated and will be removed in ' +
|
||||
'future.',
|
||||
default: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ export type StartCommandArgs = {
|
||||
config?: string,
|
||||
projectRoot?: string,
|
||||
interactive: boolean,
|
||||
clientLogs: boolean,
|
||||
};
|
||||
|
||||
async function runServer(
|
||||
@@ -96,6 +97,11 @@ async function runServer(
|
||||
require.resolve(plugin),
|
||||
);
|
||||
}
|
||||
// TODO(T214991636): Remove legacy Metro log forwarding
|
||||
if (!args.clientLogs) {
|
||||
// $FlowIgnore[cannot-write] Assigning to readonly property
|
||||
metroConfig.server.forwardClientLogs = false;
|
||||
}
|
||||
|
||||
let reportEvent: (event: TerminalReportableEvent) => void;
|
||||
const terminal = new Terminal(process.stdout);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/core-cli-utils",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "React Native CLI library for Frameworks to build on",
|
||||
"license": "MIT",
|
||||
"main": "./src/index.flow.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/debugger-frontend",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Debugger frontend for React Native based on Chrome DevTools",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/dev-middleware",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Dev server middleware for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -23,11 +23,12 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@isaacs/ttlcache": "^1.4.1",
|
||||
"@react-native/debugger-frontend": "0.77.0-main",
|
||||
"@react-native/debugger-frontend": "0.78.0",
|
||||
"chrome-launcher": "^0.15.2",
|
||||
"chromium-edge-launcher": "^0.2.0",
|
||||
"connect": "^3.6.5",
|
||||
"debug": "^2.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
"nullthrows": "^1.1.1",
|
||||
"open": "^7.0.3",
|
||||
"selfsigned": "^2.4.1",
|
||||
|
||||
@@ -150,6 +150,17 @@ function createWrappedEventReporter(
|
||||
`Profiling build target "${event.appId}" registered for debugging`,
|
||||
);
|
||||
break;
|
||||
case 'fusebox_console_notice':
|
||||
logger?.info(
|
||||
'\n' +
|
||||
'\u001B[7m' +
|
||||
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
||||
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
||||
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
||||
'\u001B[27m' +
|
||||
'\n',
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
reporter?.logEvent(event);
|
||||
|
||||
@@ -41,6 +41,8 @@ const PAGES_POLLING_INTERVAL = 1000;
|
||||
// more details.
|
||||
const FILE_PREFIX = 'file://';
|
||||
|
||||
let fuseboxConsoleNoticeLogged = false;
|
||||
|
||||
type DebuggerConnection = {
|
||||
// Debugger web socket connection
|
||||
socket: WS,
|
||||
@@ -519,6 +521,7 @@ export default class Device {
|
||||
// created instead of manually checking this on every getPages result.
|
||||
for (const page of this.#pages.values()) {
|
||||
if (this.#pageHasCapability(page, 'nativePageReloads')) {
|
||||
this.#logFuseboxConsoleNotice();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1073,4 +1076,14 @@ export default class Device {
|
||||
dangerouslyGetSocket(): WS {
|
||||
return this.#deviceSocket;
|
||||
}
|
||||
|
||||
// TODO(T214991636): Remove notice
|
||||
#logFuseboxConsoleNotice() {
|
||||
if (fuseboxConsoleNoticeLogged) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#deviceEventReporter?.logFuseboxConsoleNotice();
|
||||
fuseboxConsoleNoticeLogged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,6 +223,12 @@ class DeviceEventReporter {
|
||||
});
|
||||
}
|
||||
|
||||
logFuseboxConsoleNotice(): void {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'fusebox_console_notice',
|
||||
});
|
||||
}
|
||||
|
||||
#logExpiredCommand(pendingCommand: PendingCommand): void {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
|
||||
@@ -82,6 +82,9 @@ export type ReportableEvent =
|
||||
status: 'success',
|
||||
...DebuggerSessionIDs,
|
||||
}
|
||||
| {
|
||||
type: 'fusebox_console_notice',
|
||||
}
|
||||
| {
|
||||
type: 'proxy_error',
|
||||
status: 'error',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "ESLint config for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/eslint-parser": "^7.25.1",
|
||||
"@react-native/eslint-plugin": "0.77.0-main",
|
||||
"@react-native/eslint-plugin": "0.78.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "ESLint rules for @react-native/eslint-config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "ESLint rules to validate NativeModule and Component Specs",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
|
||||
"@react-native/codegen": "0.77.0-main",
|
||||
"@react-native/codegen": "0.78.0",
|
||||
"make-dir": "^2.1.0",
|
||||
"pirates": "^4.0.1",
|
||||
"source-map-support": "0.5.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/gradle-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Gradle Plugin for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -5,3 +5,4 @@ ruby ">= 2.6.10"
|
||||
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
|
||||
gem 'xcodeproj', '< 1.26.0'
|
||||
gem 'concurrent-ruby', '< 1.3.4'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "helloworld",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"bootstrap": "node ./cli.js bootstrap",
|
||||
@@ -13,16 +13,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "19.0.0",
|
||||
"react-native": "1000.0.0"
|
||||
"react-native": "0.78.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"@react-native/core-cli-utils": "0.77.0-main",
|
||||
"@react-native/eslint-config": "0.77.0-main",
|
||||
"@react-native/metro-config": "0.77.0-main",
|
||||
"@react-native/babel-preset": "0.78.0",
|
||||
"@react-native/core-cli-utils": "0.78.0",
|
||||
"@react-native/eslint-config": "0.78.0",
|
||||
"@react-native/metro-config": "0.78.0",
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^12.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/js-polyfills": "0.78.0",
|
||||
"@react-native/metro-babel-transformer": "0.78.0",
|
||||
"metro-config": "^0.81.0",
|
||||
"metro-runtime": "^0.81.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/normalize-colors",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Color normalization for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/js-polyfills",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Polyfills for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-preset",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Babel preset for React Native applications",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
@@ -55,7 +55,7 @@
|
||||
"@babel/plugin-transform-typescript": "^7.25.2",
|
||||
"@babel/plugin-transform-unicode-regex": "^7.24.7",
|
||||
"@babel/template": "^7.25.0",
|
||||
"@react-native/babel-plugin-codegen": "0.77.0-main",
|
||||
"@react-native/babel-plugin-codegen": "0.78.0",
|
||||
"babel-plugin-syntax-hermes-parser": "0.25.1",
|
||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-babel-transformer",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Babel transformer for React Native applications.",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"@react-native/babel-preset": "0.78.0",
|
||||
"hermes-parser": "0.25.1",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/bots",
|
||||
"description": "React Native Bots",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen-typescript-test",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"private": true,
|
||||
"description": "TypeScript related unit test for @react-native/codegen",
|
||||
"license": "MIT",
|
||||
@@ -19,7 +19,7 @@
|
||||
"prepare": "yarn run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.78.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Code generation tools for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@react-native/fantom",
|
||||
"private": true,
|
||||
"version": "0.77.0-main",
|
||||
"main": "src/index.js",
|
||||
"description": "Internal integration testing and benchmarking tool for React Native",
|
||||
"peerDependencies":{
|
||||
"jest":"^29.7.0",
|
||||
"jest-snapshot": "^29.7.0"
|
||||
}
|
||||
"name": "@react-native/fantom",
|
||||
"private": true,
|
||||
"version": "0.78.0",
|
||||
"main": "src/index.js",
|
||||
"description": "Internal integration testing and benchmarking tool for React Native",
|
||||
"peerDependencies": {
|
||||
"jest": "^29.7.0",
|
||||
"jest-snapshot": "^29.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-info",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"main": "build/index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/popup-menu-android",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "PopupMenu for the Android platform",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.78.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/oss-library-example",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"private": true,
|
||||
"description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.",
|
||||
"license": "MIT",
|
||||
@@ -26,8 +26,8 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"react-native": "1000.0.0"
|
||||
"@react-native/babel-preset": "0.78.0",
|
||||
"react-native": "0.78.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
import type {EventSubscription} from '../../vendor/emitter/EventEmitter';
|
||||
import type {PlatformConfig} from '../AnimatedPlatformConfig';
|
||||
import type Animation, {EndCallback} from '../animations/Animation';
|
||||
import type {InterpolationConfigType} from './AnimatedInterpolation';
|
||||
import type AnimatedNode from './AnimatedNode';
|
||||
@@ -84,6 +85,7 @@ function _executeAsAnimatedBatch(id: string, operation: () => void) {
|
||||
* See https://reactnative.dev/docs/animatedvalue
|
||||
*/
|
||||
export default class AnimatedValue extends AnimatedWithChildren {
|
||||
#attached: boolean = false;
|
||||
#updateSubscription: ?EventSubscription = null;
|
||||
|
||||
_value: number;
|
||||
@@ -106,14 +108,8 @@ export default class AnimatedValue extends AnimatedWithChildren {
|
||||
}
|
||||
|
||||
__attach(): void {
|
||||
if (this.__isNative) {
|
||||
// NOTE: In theory, we should only need to call this when any listeners
|
||||
// are added. However, there is a global `onUserDrivenAnimationEnded`
|
||||
// listener that relies on `onAnimatedValueUpdate` having fired to update
|
||||
// the values in JavaScript. If that listener is removed, this could be
|
||||
// re-optimized.
|
||||
this.#ensureUpdateSubscriptionExists();
|
||||
}
|
||||
this.#attached = true;
|
||||
this.#ensureUpdateSubscriptionExists();
|
||||
}
|
||||
|
||||
__detach(): void {
|
||||
@@ -125,16 +121,34 @@ export default class AnimatedValue extends AnimatedWithChildren {
|
||||
}
|
||||
this.stopAnimation();
|
||||
super.__detach();
|
||||
this.#attached = false;
|
||||
}
|
||||
|
||||
__getValue(): number {
|
||||
return this._value + this._offset;
|
||||
}
|
||||
|
||||
__makeNative(platformConfig: ?PlatformConfig): void {
|
||||
super.__makeNative(platformConfig);
|
||||
this.#ensureUpdateSubscriptionExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: In theory, we should only need to call this when any listeners
|
||||
* are added. However, there is a global `onUserDrivenAnimationEnded`
|
||||
* listener that relies on `onAnimatedValueUpdate` having fired to update
|
||||
* the values in JavaScript. If that listener is removed, this could be
|
||||
* re-optimized.
|
||||
*/
|
||||
#ensureUpdateSubscriptionExists(): void {
|
||||
if (this.#updateSubscription != null) {
|
||||
return;
|
||||
}
|
||||
// The order in which `__attach` and `__makeNative` are called is not
|
||||
// deterministic, and we only want to do this when both have occurred.
|
||||
if (!this.#attached || !this.__isNative) {
|
||||
return;
|
||||
}
|
||||
const nativeTag = this.__getNativeTag();
|
||||
NativeAnimatedAPI.startListeningToAnimatedNodeValue(nativeTag);
|
||||
const subscription: EventSubscription =
|
||||
|
||||
+14
-13
@@ -276,6 +276,20 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void {
|
||||
// if the queue is empty. When multiple animated components are mounted at
|
||||
// the same time. Only first component flushes the queue and the others will noop.
|
||||
NativeAnimatedHelper.API.flushQueue();
|
||||
let drivenAnimationEndedListener: ?EventSubscription = null;
|
||||
if (node.__isNative) {
|
||||
drivenAnimationEndedListener =
|
||||
NativeAnimatedHelper.nativeEventEmitter.addListener(
|
||||
'onUserDrivenAnimationEnded',
|
||||
data => {
|
||||
node.update();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
drivenAnimationEndedListener?.remove();
|
||||
};
|
||||
});
|
||||
|
||||
useInsertionEffect(() => {
|
||||
@@ -287,17 +301,6 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void {
|
||||
|
||||
useInsertionEffect(() => {
|
||||
node.__attach();
|
||||
let drivenAnimationEndedListener: ?EventSubscription = null;
|
||||
|
||||
if (node.__isNative) {
|
||||
drivenAnimationEndedListener =
|
||||
NativeAnimatedHelper.nativeEventEmitter.addListener(
|
||||
'onUserDrivenAnimationEnded',
|
||||
data => {
|
||||
node.update();
|
||||
},
|
||||
);
|
||||
}
|
||||
if (prevNodeRef.current != null) {
|
||||
const prevNode = prevNodeRef.current;
|
||||
// TODO: Stop restoring default values (unless `reset` is called).
|
||||
@@ -312,8 +315,6 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void {
|
||||
} else {
|
||||
prevNodeRef.current = node;
|
||||
}
|
||||
|
||||
drivenAnimationEndedListener?.remove();
|
||||
};
|
||||
}, [node]);
|
||||
}
|
||||
|
||||
@@ -255,9 +255,12 @@ class RCTAppDelegateBridgelessFeatureFlags : public ReactNativeFeatureFlagsDefau
|
||||
|
||||
- (void)_setUpFeatureFlags
|
||||
{
|
||||
if ([self bridgelessEnabled]) {
|
||||
ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
|
||||
}
|
||||
static dispatch_once_t setupFeatureFlagsToken;
|
||||
dispatch_once(&setupFeatureFlagsToken, ^{
|
||||
if ([self bridgelessEnabled]) {
|
||||
ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,8 +14,8 @@ const version: $ReadOnly<{
|
||||
patch: number,
|
||||
prerelease: string | null,
|
||||
}> = {
|
||||
major: 1000,
|
||||
minor: 0,
|
||||
major: 0,
|
||||
minor: 78,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
@@ -42,9 +42,8 @@ if (__DEV__) {
|
||||
if (!Platform.isTesting) {
|
||||
const HMRClient = require('../Utilities/HMRClient');
|
||||
|
||||
if (global.__FUSEBOX_HAS_FULL_CONSOLE_SUPPORT__) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
} else if (console._isPolyfilled) {
|
||||
// TODO(T214991636): Remove legacy Metro log forwarding
|
||||
if (console._isPolyfilled) {
|
||||
// We assume full control over the console and send JavaScript logs to Metro.
|
||||
[
|
||||
'trace',
|
||||
|
||||
@@ -477,7 +477,15 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
|
||||
// Add missing png extension
|
||||
if (request.URL.fileURL && request.URL.pathExtension.length == 0) {
|
||||
mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"];
|
||||
// Check if there exists a file with that url on disk already
|
||||
// This should fix issue https://github.com/facebook/react-native/issues/46870
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:request.URL.path]) {
|
||||
mutableRequest.URL = request.URL;
|
||||
} else {
|
||||
// This is the default behavior in case there is no file on disk with no extension.
|
||||
// We assume that the extension is `png`.
|
||||
mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"];
|
||||
}
|
||||
}
|
||||
if (_redirectDelegate != nil) {
|
||||
mutableRequest.URL = [_redirectDelegate redirectAssetsURL:mutableRequest.URL];
|
||||
|
||||
@@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null;
|
||||
let currentCompileErrorMessage: string | null = null;
|
||||
let didConnect: boolean = false;
|
||||
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
||||
let pendingFuseboxConsoleNotification = false;
|
||||
|
||||
type LogLevel =
|
||||
| 'trace'
|
||||
@@ -52,7 +51,6 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string,
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -142,29 +140,6 @@ const HMRClient: HMRClientNativeInterface = {
|
||||
}
|
||||
},
|
||||
|
||||
unstable_notifyFuseboxConsoleEnabled() {
|
||||
if (!hmrClient) {
|
||||
pendingFuseboxConsoleNotification = true;
|
||||
return;
|
||||
}
|
||||
hmrClient.send(
|
||||
JSON.stringify({
|
||||
type: 'log',
|
||||
level: 'info',
|
||||
data: [
|
||||
'\n' +
|
||||
'\u001B[7m' +
|
||||
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
||||
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
||||
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
||||
'\u001B[27m' +
|
||||
'\n',
|
||||
],
|
||||
}),
|
||||
);
|
||||
pendingFuseboxConsoleNotification = false;
|
||||
},
|
||||
|
||||
// Called once by the bridge on startup, even if Fast Refresh is off.
|
||||
// It creates the HMR client but doesn't actually set up the socket yet.
|
||||
setup(
|
||||
@@ -341,9 +316,6 @@ function flushEarlyLogs(client: MetroHMRClient) {
|
||||
pendingLogs.forEach(([level, data]) => {
|
||||
HMRClient.log(level, data);
|
||||
});
|
||||
if (pendingFuseboxConsoleNotification) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
}
|
||||
} finally {
|
||||
pendingLogs.length = 0;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ const HMRClientProdShim: HMRClientNativeInterface = {
|
||||
disable() {},
|
||||
registerBundle() {},
|
||||
log() {},
|
||||
unstable_notifyFuseboxConsoleEnabled() {},
|
||||
};
|
||||
|
||||
module.exports = HMRClientProdShim;
|
||||
|
||||
@@ -1169,6 +1169,7 @@ declare export default class AnimatedValue extends AnimatedWithChildren {
|
||||
__attach(): void;
|
||||
__detach(): void;
|
||||
__getValue(): number;
|
||||
__makeNative(platformConfig: ?PlatformConfig): void;
|
||||
setValue(value: number): void;
|
||||
setOffset(offset: number): void;
|
||||
flattenOffset(): void;
|
||||
@@ -9000,7 +9001,6 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
declare const HMRClient: HMRClientNativeInterface;
|
||||
declare module.exports: HMRClient;
|
||||
|
||||
@@ -21,8 +21,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(void){
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(1000),
|
||||
RCTVersionMinor: @(0),
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(78),
|
||||
RCTVersionPatch: @(0),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
};
|
||||
|
||||
@@ -54,13 +54,11 @@
|
||||
]];
|
||||
|
||||
UIButton *resumeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[resumeButton setImage:[UIImage systemImageNamed:@"forward.frame.fill"] forState:UIControlStateNormal];
|
||||
UIImage *image = [UIImage systemImageNamed:@"forward.frame.fill"];
|
||||
[resumeButton setImage:image forState:UIControlStateNormal];
|
||||
[resumeButton setImage:image forState:UIControlStateDisabled];
|
||||
resumeButton.tintColor = [UIColor colorWithRed:0.37 green:0.37 blue:0.37 alpha:1];
|
||||
|
||||
resumeButton.configurationUpdateHandler = ^(UIButton *button) {
|
||||
button.imageView.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
|
||||
};
|
||||
|
||||
resumeButton.enabled = NO;
|
||||
[NSLayoutConstraint activateConstraints:@[
|
||||
[resumeButton.widthAnchor constraintEqualToConstant:48],
|
||||
|
||||
@@ -2215,7 +2215,7 @@ public abstract interface class com/facebook/react/devsupport/HMRClient : com/fa
|
||||
public abstract fun disable ()V
|
||||
public abstract fun enable ()V
|
||||
public abstract fun registerBundle (Ljava/lang/String;)V
|
||||
public abstract fun setup (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V
|
||||
public abstract fun setup (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZLjava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/devsupport/InspectorFlags {
|
||||
@@ -3482,6 +3482,14 @@ public class com/facebook/react/modules/network/ResponseUtil {
|
||||
public static fun onResponseReceived (Lcom/facebook/react/bridge/ReactApplicationContext;IILcom/facebook/react/bridge/WritableMap;Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/modules/network/ReactCookieJarContainer : com/facebook/react/modules/network/CookieJarContainer {
|
||||
public fun <init> ()V
|
||||
public fun loadForRequest (Lokhttp3/HttpUrl;)Ljava/util/List;
|
||||
public fun removeCookieJar ()V
|
||||
public fun saveFromResponse (Lokhttp3/HttpUrl;Ljava/util/List;)V
|
||||
public fun setCookieJar (Lokhttp3/CookieJar;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/modules/network/TLSSocketFactory : javax/net/ssl/SSLSocketFactory {
|
||||
public fun <init> ()V
|
||||
public fun createSocket (Ljava/lang/String;I)Ljava/net/Socket;
|
||||
@@ -7342,6 +7350,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
||||
public static final field TA_KEY_LETTER_SPACING S
|
||||
public static final field TA_KEY_LINE_BREAK_STRATEGY S
|
||||
public static final field TA_KEY_LINE_HEIGHT S
|
||||
public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S
|
||||
public static final field TA_KEY_OPACITY S
|
||||
public static final field TA_KEY_ROLE S
|
||||
public static final field TA_KEY_TEXT_DECORATION_COLOR S
|
||||
@@ -7374,6 +7383,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
||||
protected field mLetterSpacingInput F
|
||||
protected field mLineHeight F
|
||||
protected field mLineHeightInput F
|
||||
protected field mMaxFontSizeMultiplier F
|
||||
protected field mNumberOfLines I
|
||||
protected field mOpacity F
|
||||
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
|
||||
@@ -7823,4 +7833,3 @@ public final class com/facebook/react/views/view/WindowUtilKt {
|
||||
public static final fun setStatusBarVisibility (Landroid/view/Window;Z)V
|
||||
public static final fun setSystemBarsTranslucency (Landroid/view/Window;Z)V
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.78.0
|
||||
react.internal.publishingGroup=com.facebook.react
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
+3
-1
@@ -685,10 +685,12 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
URL sourceUrl = new URL(getSourceUrl());
|
||||
String path = sourceUrl.getPath().substring(1); // strip initial slash in path
|
||||
String host = sourceUrl.getHost();
|
||||
String scheme = sourceUrl.getProtocol();
|
||||
int port = sourceUrl.getPort() != -1 ? sourceUrl.getPort() : sourceUrl.getDefaultPort();
|
||||
mCurrentReactContext
|
||||
.getJSModule(HMRClient.class)
|
||||
.setup("android", path, host, port, mDevSettings.isHotModuleReplacementEnabled());
|
||||
.setup(
|
||||
"android", path, host, port, mDevSettings.isHotModuleReplacementEnabled(), scheme);
|
||||
} catch (MalformedURLException e) {
|
||||
showNewJavaError(e.getMessage(), e);
|
||||
}
|
||||
|
||||
+4
-1
@@ -26,8 +26,11 @@ public interface HMRClient extends JavaScriptModule {
|
||||
* @param host The host that the HMRClient should communicate with.
|
||||
* @param port The port that the HMRClient should communicate with on the host.
|
||||
* @param isEnabled Whether HMR is enabled initially.
|
||||
* @param scheme The protocol that the HMRClient should communicate with on the host (defaults to
|
||||
* http).
|
||||
*/
|
||||
void setup(String platform, String bundleEntry, String host, int port, boolean isEnabled);
|
||||
void setup(
|
||||
String platform, String bundleEntry, String host, int port, boolean isEnabled, String scheme);
|
||||
|
||||
/** Registers an additional JS bundle with HMRClient. */
|
||||
void registerBundle(String bundleUrl);
|
||||
|
||||
+15
-8
@@ -331,14 +331,11 @@ public class MountingManager {
|
||||
@AnyThread
|
||||
@ThreadConfined(ANY)
|
||||
public @Nullable EventEmitterWrapper getEventEmitter(int surfaceId, int reactTag) {
|
||||
SurfaceMountingManager surfaceMountingManager =
|
||||
(surfaceId == ViewUtil.NO_SURFACE_ID
|
||||
? getSurfaceManagerForView(reactTag)
|
||||
: getSurfaceManager(surfaceId));
|
||||
if (surfaceMountingManager == null) {
|
||||
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
||||
if (smm == null) {
|
||||
return null;
|
||||
}
|
||||
return surfaceMountingManager.getEventEmitter(reactTag);
|
||||
return smm.getEventEmitter(reactTag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -458,11 +455,21 @@ public class MountingManager {
|
||||
boolean canCoalesceEvent,
|
||||
@Nullable WritableMap params,
|
||||
@EventCategoryDef int eventCategory) {
|
||||
@Nullable SurfaceMountingManager smm = getSurfaceManager(surfaceId);
|
||||
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
||||
if (smm == null) {
|
||||
// Cannot queue event without valid surface mountng manager. Do nothing here.
|
||||
FLog.d(
|
||||
TAG,
|
||||
"Cannot queue event without valid surface mounting manager for tag: %d, surfaceId: %d",
|
||||
reactTag,
|
||||
surfaceId);
|
||||
return;
|
||||
}
|
||||
smm.enqueuePendingEvent(reactTag, eventName, canCoalesceEvent, params, eventCategory);
|
||||
}
|
||||
|
||||
private @Nullable SurfaceMountingManager getSurfaceMountingManager(int surfaceId, int reactTag) {
|
||||
return (surfaceId == ViewUtil.NO_SURFACE_ID
|
||||
? getSurfaceManagerForView(reactTag)
|
||||
: getSurfaceManager(surfaceId));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
/** Basic okhttp3 CookieJar container */
|
||||
internal class ReactCookieJarContainer : CookieJarContainer {
|
||||
public class ReactCookieJarContainer : CookieJarContainer {
|
||||
|
||||
private var cookieJar: CookieJar? = null
|
||||
|
||||
|
||||
+2
-2
@@ -15,8 +15,8 @@ import java.util.Map;
|
||||
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 1000,
|
||||
"minor", 0,
|
||||
"major", 0,
|
||||
"minor", 78,
|
||||
"patch", 0,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,5 +17,5 @@ public interface ReactOverflowView {
|
||||
* Gets the overflow state of a view. If set, this should be one of [ViewProps#HIDDEN],
|
||||
* [ViewProps#VISIBLE] or [ViewProps#SCROLL].
|
||||
*/
|
||||
public fun getOverflow(): String?
|
||||
public val overflow: String?
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,6 +13,6 @@ package com.facebook.react.uimanager
|
||||
*/
|
||||
public interface ReactPointerEventsView {
|
||||
|
||||
/** Return the PointerEvents of the View. */
|
||||
public fun getPointerEvents(): PointerEvents
|
||||
/** The PointerEvents of the View. */
|
||||
public val pointerEvents: PointerEvents
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@ package com.facebook.react.uimanager
|
||||
|
||||
/** A task to execute on the UI View for third party libraries. */
|
||||
public fun interface UIBlock {
|
||||
public fun execute(nativeViewHierarchyManager: NativeViewHierarchyManager?): Unit
|
||||
public fun execute(nativeViewHierarchyManager: NativeViewHierarchyManager): Unit
|
||||
}
|
||||
|
||||
+16
-2
@@ -61,6 +61,7 @@ public class TextAttributeProps {
|
||||
public static final short TA_KEY_LINE_BREAK_STRATEGY = 25;
|
||||
public static final short TA_KEY_ROLE = 26;
|
||||
public static final short TA_KEY_TEXT_TRANSFORM = 27;
|
||||
public static final short TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
||||
|
||||
public static final int UNSET = -1;
|
||||
|
||||
@@ -81,6 +82,7 @@ public class TextAttributeProps {
|
||||
protected float mLineHeight = Float.NaN;
|
||||
protected boolean mIsColorSet = false;
|
||||
protected boolean mAllowFontScaling = true;
|
||||
protected float mMaxFontSizeMultiplier = Float.NaN;
|
||||
protected int mColor;
|
||||
protected boolean mIsBackgroundColorSet = false;
|
||||
protected int mBackgroundColor;
|
||||
@@ -227,6 +229,9 @@ public class TextAttributeProps {
|
||||
case TA_KEY_TEXT_TRANSFORM:
|
||||
result.setTextTransform(entry.getStringValue());
|
||||
break;
|
||||
case TA_KEY_MAX_FONT_SIZE_MULTIPLIER:
|
||||
result.setMaxFontSizeMultiplier((float) entry.getDoubleValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +248,8 @@ public class TextAttributeProps {
|
||||
result.setLineHeight(getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET));
|
||||
result.setLetterSpacing(getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN));
|
||||
result.setAllowFontScaling(getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true));
|
||||
result.setMaxFontSizeMultiplier(
|
||||
getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN));
|
||||
result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET));
|
||||
result.setColor(props.hasKey(ViewProps.COLOR) ? props.getInt(ViewProps.COLOR, 0) : null);
|
||||
result.setColor(
|
||||
@@ -411,7 +418,14 @@ public class TextAttributeProps {
|
||||
mAllowFontScaling = allowFontScaling;
|
||||
setFontSize(mFontSizeInput);
|
||||
setLineHeight(mLineHeightInput);
|
||||
setLetterSpacing(mLetterSpacingInput);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
|
||||
if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) {
|
||||
mMaxFontSizeMultiplier = maxFontSizeMultiplier;
|
||||
setFontSize(mFontSizeInput);
|
||||
setLineHeight(mLineHeightInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +434,7 @@ public class TextAttributeProps {
|
||||
if (fontSize != ReactConstants.UNSET) {
|
||||
fontSize =
|
||||
mAllowFontScaling
|
||||
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize))
|
||||
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier))
|
||||
: (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));
|
||||
}
|
||||
mFontSize = (int) fontSize;
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace facebook::react {
|
||||
|
||||
constexpr struct {
|
||||
int32_t Major = 1000;
|
||||
int32_t Minor = 0;
|
||||
int32_t Major = 0;
|
||||
int32_t Minor = 78;
|
||||
int32_t Patch = 0;
|
||||
std::string_view Prerelease = "";
|
||||
} ReactNativeVersion;
|
||||
|
||||
+13
-4
@@ -123,6 +123,15 @@ std::vector<ExportedMethod> parseExportedMethods(std::string moduleName, Class m
|
||||
NSArray<RCTMethodArgument *> *arguments;
|
||||
SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments));
|
||||
NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector];
|
||||
if (objCMethodSignature == nullptr) {
|
||||
RCTLogWarn(
|
||||
@"The objective-c `%s` method signature for the JS method `%@` can not be found in the ObjecitveC definition of the %s module.\nThe `%@` JS method will not be available.",
|
||||
methodInfo->objcName,
|
||||
jsMethodName,
|
||||
moduleName.c_str(),
|
||||
jsMethodName);
|
||||
continue;
|
||||
}
|
||||
std::string objCMethodReturnType = [objCMethodSignature methodReturnType];
|
||||
|
||||
if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) {
|
||||
@@ -337,7 +346,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
SEL selector = selectorForType(argumentType);
|
||||
|
||||
if ([RCTConvert respondsToSelector:selector]) {
|
||||
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
|
||||
if (objCArgType == @encode(char)) {
|
||||
char arg = RCTConvertTo<char>(selector, objCArg);
|
||||
@@ -491,7 +500,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock arg =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
if (arg) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
@@ -506,7 +515,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock senderBlock =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
RCTResponseErrorBlock arg = ^(NSError *error) {
|
||||
senderBlock(@[ RCTJSErrorFromNSError(error) ]);
|
||||
};
|
||||
@@ -536,7 +545,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
runtime, errorPrefix + "JavaScript argument must be a plain object. Got " + getType(runtime, jsiArg));
|
||||
}
|
||||
|
||||
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
|
||||
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
RCTManagedPointer *box = convert([RCTCxxConvert class], selector, arg);
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ using EventEmitterCallback = std::function<void(const std::string &, id)>;
|
||||
namespace TurboModuleConvertUtils {
|
||||
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker);
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull);
|
||||
} // namespace TurboModuleConvertUtils
|
||||
|
||||
template <>
|
||||
|
||||
+16
-8
@@ -112,20 +112,20 @@ static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::St
|
||||
}
|
||||
|
||||
static NSArray *
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull)
|
||||
{
|
||||
size_t size = value.size(runtime);
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
||||
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker);
|
||||
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker, useNSNull);
|
||||
[result addObject:convertedObject ? convertedObject : (id)kCFNull];
|
||||
}
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
static NSDictionary *
|
||||
convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull)
|
||||
{
|
||||
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
||||
size_t size = propertyNames.size(runtime);
|
||||
@@ -133,7 +133,7 @@ convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value,
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
||||
NSString *k = convertJSIStringToNSString(runtime, name);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker, useNSNull);
|
||||
if (v) {
|
||||
result[k] = v;
|
||||
}
|
||||
@@ -159,11 +159,14 @@ convertJSIFunctionToCallback(jsi::Runtime &rt, jsi::Function &&function, std::sh
|
||||
};
|
||||
}
|
||||
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull)
|
||||
{
|
||||
if (value.isUndefined() || value.isNull()) {
|
||||
if (value.isUndefined() || (value.isNull() && !useNSNull)) {
|
||||
return nil;
|
||||
}
|
||||
if (value.isNull() && useNSNull) {
|
||||
return [NSNull null];
|
||||
}
|
||||
if (value.isBool()) {
|
||||
return @(value.getBool());
|
||||
}
|
||||
@@ -176,17 +179,22 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s
|
||||
if (value.isObject()) {
|
||||
jsi::Object o = value.getObject(runtime);
|
||||
if (o.isArray(runtime)) {
|
||||
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
|
||||
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker, useNSNull);
|
||||
}
|
||||
if (o.isFunction(runtime)) {
|
||||
return convertJSIFunctionToCallback(runtime, o.getFunction(runtime), jsInvoker);
|
||||
}
|
||||
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
|
||||
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker, useNSNull);
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported jsi::Value kind");
|
||||
}
|
||||
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
{
|
||||
return convertJSIValueToObjCObject(runtime, value, jsInvoker, NO);
|
||||
}
|
||||
|
||||
static jsi::Value createJSRuntimeError(jsi::Runtime &runtime, const std::string &message)
|
||||
{
|
||||
return runtime.global().getPropertyAsFunction(runtime, "Error").call(runtime, message);
|
||||
|
||||
@@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) {
|
||||
allowFontScaling = textAttributes.allowFontScaling.has_value()
|
||||
? textAttributes.allowFontScaling
|
||||
: allowFontScaling;
|
||||
maxFontSizeMultiplier = !std::isnan(textAttributes.maxFontSizeMultiplier)
|
||||
? textAttributes.maxFontSizeMultiplier
|
||||
: maxFontSizeMultiplier;
|
||||
dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value()
|
||||
? textAttributes.dynamicTypeRamp
|
||||
: dynamicTypeRamp;
|
||||
@@ -168,6 +171,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
|
||||
rhs.accessibilityRole,
|
||||
rhs.role,
|
||||
rhs.textTransform) &&
|
||||
floatEquality(maxFontSizeMultiplier, rhs.maxFontSizeMultiplier) &&
|
||||
floatEquality(opacity, rhs.opacity) &&
|
||||
floatEquality(fontSize, rhs.fontSize) &&
|
||||
floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) &&
|
||||
@@ -224,6 +228,10 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const {
|
||||
"allowFontScaling",
|
||||
allowFontScaling,
|
||||
textAttributes.allowFontScaling),
|
||||
debugStringConvertibleItem(
|
||||
"maxFontSizeMultiplier",
|
||||
maxFontSizeMultiplier,
|
||||
textAttributes.maxFontSizeMultiplier),
|
||||
debugStringConvertibleItem(
|
||||
"dynamicTypeRamp", dynamicTypeRamp, textAttributes.dynamicTypeRamp),
|
||||
debugStringConvertibleItem(
|
||||
|
||||
@@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible {
|
||||
std::optional<FontStyle> fontStyle{};
|
||||
std::optional<FontVariant> fontVariant{};
|
||||
std::optional<bool> allowFontScaling{};
|
||||
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
|
||||
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<TextTransform> textTransform{};
|
||||
@@ -117,6 +118,7 @@ struct hash<facebook::react::TextAttributes> {
|
||||
textAttributes.opacity,
|
||||
textAttributes.fontFamily,
|
||||
textAttributes.fontSize,
|
||||
textAttributes.maxFontSizeMultiplier,
|
||||
textAttributes.fontSizeMultiplier,
|
||||
textAttributes.fontWeight,
|
||||
textAttributes.fontStyle,
|
||||
|
||||
@@ -910,6 +910,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25;
|
||||
constexpr static MapBuffer::Key TA_KEY_ROLE = 26;
|
||||
constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27;
|
||||
constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28;
|
||||
constexpr static MapBuffer::Key TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
||||
|
||||
// constants for ParagraphAttributes serialization
|
||||
constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0;
|
||||
@@ -1004,6 +1005,10 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) {
|
||||
builder.putBool(
|
||||
TA_KEY_ALLOW_FONT_SCALING, *textAttributes.allowFontScaling);
|
||||
}
|
||||
if (!std::isnan(textAttributes.maxFontSizeMultiplier)) {
|
||||
builder.putDouble(
|
||||
TA_KEY_MAX_FONT_SIZE_MULTIPLIER, textAttributes.maxFontSizeMultiplier);
|
||||
}
|
||||
if (!std::isnan(textAttributes.letterSpacing)) {
|
||||
builder.putDouble(TA_KEY_LETTER_SPACING, textAttributes.letterSpacing);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,12 @@ static TextAttributes convertRawProp(
|
||||
"allowFontScaling",
|
||||
sourceTextAttributes.allowFontScaling,
|
||||
defaultTextAttributes.allowFontScaling);
|
||||
textAttributes.maxFontSizeMultiplier = convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"maxFontSizeMultiplier",
|
||||
sourceTextAttributes.maxFontSizeMultiplier,
|
||||
defaultTextAttributes.maxFontSizeMultiplier);
|
||||
textAttributes.dynamicTypeRamp = convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
@@ -266,6 +272,12 @@ void BaseTextProps::setProp(
|
||||
defaults, value, textAttributes, fontVariant, "fontVariant");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults, value, textAttributes, allowFontScaling, "allowFontScaling");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults,
|
||||
value,
|
||||
textAttributes,
|
||||
maxFontSizeMultiplier,
|
||||
"maxFontSizeMultiplier");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults, value, textAttributes, letterSpacing, "letterSpacing");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
|
||||
+5
-3
@@ -135,6 +135,7 @@ inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynam
|
||||
inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes)
|
||||
{
|
||||
if (textAttributes.allowFontScaling.value_or(true)) {
|
||||
CGFloat fontSizeMultiplier = !isnan(textAttributes.fontSizeMultiplier) ? textAttributes.fontSizeMultiplier : 1.0;
|
||||
if (textAttributes.dynamicTypeRamp.has_value()) {
|
||||
DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value();
|
||||
UIFontMetrics *fontMetrics =
|
||||
@@ -142,10 +143,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex
|
||||
// Using a specific font size reduces rounding errors from -scaledValueForValue:
|
||||
CGFloat requestedSize =
|
||||
isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize;
|
||||
return [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
|
||||
} else {
|
||||
return textAttributes.fontSizeMultiplier;
|
||||
fontSizeMultiplier = [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
|
||||
}
|
||||
CGFloat maxFontSizeMultiplier =
|
||||
!isnan(textAttributes.maxFontSizeMultiplier) ? textAttributes.maxFontSizeMultiplier : 0.0;
|
||||
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.78.0",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -108,13 +108,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.6.3",
|
||||
"@react-native/assets-registry": "0.77.0-main",
|
||||
"@react-native/codegen": "0.77.0-main",
|
||||
"@react-native/community-cli-plugin": "0.77.0-main",
|
||||
"@react-native/gradle-plugin": "0.77.0-main",
|
||||
"@react-native/js-polyfills": "0.77.0-main",
|
||||
"@react-native/normalize-colors": "0.77.0-main",
|
||||
"@react-native/virtualized-lists": "0.77.0-main",
|
||||
"@react-native/assets-registry": "0.78.0",
|
||||
"@react-native/codegen": "0.78.0",
|
||||
"@react-native/community-cli-plugin": "0.78.0",
|
||||
"@react-native/gradle-plugin": "0.78.0",
|
||||
"@react-native/js-polyfills": "0.78.0",
|
||||
"@react-native/normalize-colors": "0.78.0",
|
||||
"@react-native/virtualized-lists": "0.78.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
|
||||
@@ -84,12 +84,18 @@ const codegenCommand = {
|
||||
name: '--outputPath <path>',
|
||||
description: 'Path where generated artifacts will be output to.',
|
||||
},
|
||||
{
|
||||
name: '--source <string>',
|
||||
description: 'Whether the script is invoked from an `app` or a `library`',
|
||||
default: 'app',
|
||||
},
|
||||
],
|
||||
func: (argv, config, args) =>
|
||||
require('./scripts/codegen/generate-artifacts-executor').execute(
|
||||
args.path,
|
||||
args.platform,
|
||||
args.outputPath,
|
||||
args.source,
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
@@ -899,11 +899,12 @@ function generateFBReactNativeSpecIOS(projectRoot /*: string */) /*: void*/ {
|
||||
* @parameter projectRoot: the directory with the app source code, where the package.json lives.
|
||||
* @parameter baseOutputPath: the base output path for the CodeGen.
|
||||
* @parameter targetPlatform: the target platform. Supported values: 'android', 'ios', 'all'.
|
||||
* @parameter source: the source that is invoking codegen. Supported values: 'app', 'library'.
|
||||
* @throws If it can't find a config file for react-native.
|
||||
* @throws If it can't find a CodeGen configuration in the file.
|
||||
* @throws If it can't find a cli for the CodeGen.
|
||||
*/
|
||||
function execute(projectRoot, targetPlatform, baseOutputPath) {
|
||||
function execute(projectRoot, targetPlatform, baseOutputPath, source) {
|
||||
try {
|
||||
codegenLog(`Analyzing ${path.join(projectRoot, 'package.json')}`);
|
||||
|
||||
@@ -951,9 +952,12 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
|
||||
platform,
|
||||
);
|
||||
|
||||
generateRCTThirdPartyComponents(libraries, outputPath);
|
||||
generateCustomURLHandlers(libraries, outputPath);
|
||||
generateAppDependencyProvider(outputPath);
|
||||
if (source === 'app') {
|
||||
// These components are only required by apps, not by libraries
|
||||
generateRCTThirdPartyComponents(libraries, outputPath);
|
||||
generateCustomURLHandlers(libraries, outputPath);
|
||||
generateAppDependencyProvider(outputPath);
|
||||
}
|
||||
|
||||
cleanupEmptyFilesAndFolders(outputPath);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,12 @@ const argv = yargs
|
||||
alias: 'outputPath',
|
||||
description: 'Path where generated artifacts will be output to.',
|
||||
})
|
||||
.option('s', {
|
||||
alias: 'source',
|
||||
description: 'Whether the script is invoked from an `app` or a `library`',
|
||||
default: 'app',
|
||||
})
|
||||
.usage('Usage: $0 -p [path to app] -t [target platform] -o [output path]')
|
||||
.demandOption(['p', 't']).argv;
|
||||
|
||||
executor.execute(argv.path, argv.targetPlatform, argv.outputPath);
|
||||
executor.execute(argv.path, argv.targetPlatform, argv.outputPath, argv.source);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hermes-2025-01-13-RNv0.78.0-a942ef374897d85da38e9c8904574f8376555388
|
||||
@@ -9,3 +9,4 @@ gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||
gem 'rexml'
|
||||
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
|
||||
gem 'xcodeproj', '< 1.26.0'
|
||||
gem 'concurrent-ruby', '< 1.3.4'
|
||||
|
||||
+291
-291
File diff suppressed because it is too large
Load Diff
@@ -482,6 +482,37 @@ function AllowFontScalingExample(props: {}): React.Node {
|
||||
);
|
||||
}
|
||||
|
||||
function MaxFontSizeMultiplierExample(props: {}): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the maxFontSizeMultiplier
|
||||
prop to set an upper limit on how much the font size will be scaled.
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
style={{marginTop: 10}}>
|
||||
This text will not scale up (max 1x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
|
||||
This text will scale up (max 1.5x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text>Inherit max (max 1x)</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={1.5}>
|
||||
Override inherited max (max 1.5x)
|
||||
</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function NumberOfLinesExample(props: {}): React.Node {
|
||||
return (
|
||||
<>
|
||||
@@ -1462,6 +1493,13 @@ const examples = [
|
||||
return <AllowFontScalingExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return <MaxFontSizeMultiplierExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'selectable attribute',
|
||||
name: 'selectable',
|
||||
|
||||
@@ -1175,6 +1175,62 @@ const examples = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
style={{marginTop: 10}}>
|
||||
This text will not scale up (max 1x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
|
||||
This text will scale up (max 1.5x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text>Inherit max (max 1x)</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={1.5}>
|
||||
Override inherited max (max 1.5x)
|
||||
</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2">
|
||||
This text will scale with 'title2' dynamic type ramp (no max)
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2"
|
||||
maxFontSizeMultiplier={1.2}>
|
||||
This text will scale with 'title2' dynamic type ramp (max 1.2x)
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2"
|
||||
maxFontSizeMultiplier={1}>
|
||||
This text uses 'title2' dynamic type ramp but will not scale up (max
|
||||
1x)
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Inline views',
|
||||
render: (): React.Node => <TextInlineView.Basic />,
|
||||
@@ -1440,9 +1496,27 @@ const examples = [
|
||||
<Text style={{fontSize: 20}} dynamicTypeRamp="title3">
|
||||
Title 3
|
||||
</Text>
|
||||
<Text style={{fontSize: 17}} dynamicTypeRamp="headline">
|
||||
Headline
|
||||
</Text>
|
||||
<Text style={{fontSize: 17}} dynamicTypeRamp="body">
|
||||
Body
|
||||
</Text>
|
||||
<Text style={{fontSize: 16}} dynamicTypeRamp="callout">
|
||||
Callout
|
||||
</Text>
|
||||
<Text style={{fontSize: 15}} dynamicTypeRamp="subheadline">
|
||||
Subheadline
|
||||
</Text>
|
||||
<Text style={{fontSize: 13}} dynamicTypeRamp="footnote">
|
||||
Footnote
|
||||
</Text>
|
||||
<Text style={{fontSize: 12}} dynamicTypeRamp="caption1">
|
||||
Caption
|
||||
</Text>
|
||||
<Text style={{fontSize: 11}} dynamicTypeRamp="caption2">
|
||||
Caption 2
|
||||
</Text>
|
||||
</View>
|
||||
<View style={boxStyle}>
|
||||
<Text style={boldStyle}>Without `dynamicTypeRamp`:</Text>
|
||||
@@ -1450,7 +1524,13 @@ const examples = [
|
||||
<Text style={{fontSize: 28}}>Title</Text>
|
||||
<Text style={{fontSize: 22}}>Title 2</Text>
|
||||
<Text style={{fontSize: 20}}>Title 3</Text>
|
||||
<Text style={{fontSize: 17}}>Headline</Text>
|
||||
<Text style={{fontSize: 17}}>Body</Text>
|
||||
<Text style={{fontSize: 16}}>Callout</Text>
|
||||
<Text style={{fontSize: 15}}>Subheadline</Text>
|
||||
<Text style={{fontSize: 13}}>Footnote</Text>
|
||||
<Text style={{fontSize: 12}}>Caption</Text>
|
||||
<Text style={{fontSize: 11}}>Caption 2</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -305,6 +305,59 @@ const examples: Array<RNTesterModuleExample> = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function (): React.Node {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
By default, text will respect Text Size accessibility setting on
|
||||
Android. It means that all font sizes will be increased or decreased
|
||||
depending on the value of the Text Size setting in the OS's Settings
|
||||
app.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={false}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
style={{marginTop: 10}}
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={true}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
placeholder="This text will not scale up (max 1x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'non-scalable-text-input'}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1.5}
|
||||
placeholder="This text will scale up (max 1.5x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'scalable-text-input'}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Text Auto Complete',
|
||||
render: function (): React.Node {
|
||||
|
||||
@@ -730,6 +730,61 @@ const textInputExamples: Array<RNTesterModuleExample> = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function (): React.Node {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
By default, text will respect Text Size accessibility setting on
|
||||
iOS. It means that all font sizes will be increased or decreased
|
||||
depending on the value of Text Size setting in{' '}
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
Settings.app - Display & Brightness - Text Size
|
||||
</Text>
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={false}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
style={{marginTop: 10}}
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={true}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
placeholder="This text will not scale up (max 1x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'non-scalable-text-input'}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1.5}
|
||||
placeholder="This text will scale up (max 1.5x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'scalable-text-input'}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Auto-expanding',
|
||||
render: function (): React.Node {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/tester",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"private": true,
|
||||
"description": "React Native tester app.",
|
||||
"license": "MIT",
|
||||
@@ -27,8 +27,8 @@
|
||||
"e2e-test-ios": "./scripts/maestro-test-ios.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/oss-library-example": "0.77.0-main",
|
||||
"@react-native/popup-menu-android": "0.77.0-main",
|
||||
"@react-native/oss-library-example": "0.78.0",
|
||||
"@react-native/popup-menu-android": "0.78.0",
|
||||
"flow-enums-runtime": "^0.0.6",
|
||||
"invariant": "^2.2.4",
|
||||
"nullthrows": "^1.1.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/typescript-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Default TypeScript configuration for React Native apps",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/virtualized-lists",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.0",
|
||||
"description": "Virtualized lists for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -85,40 +85,66 @@ async function testRNTesterIOS(
|
||||
} version of RNTester iOS with the new Architecture enabled`,
|
||||
);
|
||||
|
||||
// if everything succeeded so far, we can launch Metro and the app
|
||||
// start the Metro server in a separate window
|
||||
launchPackagerInSeparateWindow(pwd().toString());
|
||||
|
||||
// remember that for this to be successful
|
||||
// you should have run bundle install once
|
||||
// in your local setup
|
||||
if (argv.hermes === true && ciArtifacts != null) {
|
||||
const hermesURL = await ciArtifacts.artifactURLHermesDebug();
|
||||
const hermesZipPath = path.join(ciArtifacts.baseTmpPath(), 'hermes.zip');
|
||||
// download hermes source code from manifold
|
||||
ciArtifacts.downloadArtifact(hermesURL, hermesZipPath);
|
||||
// GHA zips by default the artifacts.
|
||||
const outputFolder = path.join(ciArtifacts.baseTmpPath(), 'hermes');
|
||||
exec(`rm -rf ${outputFolder}`);
|
||||
exec(`unzip ${hermesZipPath} -d ${outputFolder}`);
|
||||
const hermesPath = path.join(outputFolder, 'hermes-ios-Debug.tar.gz');
|
||||
|
||||
console.info(`Downloaded Hermes in ${hermesPath}`);
|
||||
exec(
|
||||
`HERMES_ENGINE_TARBALL_PATH=${hermesPath} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`,
|
||||
if (ciArtifacts != null) {
|
||||
const appOutputFolder = path.join(
|
||||
ciArtifacts.baseTmpPath(),
|
||||
'RNTester.app',
|
||||
);
|
||||
exec(`rm -rf ${appOutputFolder}`);
|
||||
if (argv.hermes === true) {
|
||||
// download hermes App
|
||||
const hermesAppUrl = await ciArtifacts.artifactURLForHermesRNTesterApp();
|
||||
const hermesAppZipPath = path.join(
|
||||
ciArtifacts.baseTmpPath(),
|
||||
'RNTesterAppHermes.zip',
|
||||
);
|
||||
ciArtifacts.downloadArtifact(hermesAppUrl, hermesAppZipPath);
|
||||
exec(`unzip ${hermesAppZipPath} -d ${appOutputFolder}`);
|
||||
} else {
|
||||
// download JSC app
|
||||
const hermesAppUrl = await ciArtifacts.artifactURLForJSCRNTesterApp();
|
||||
const hermesAppZipPath = path.join(
|
||||
ciArtifacts.baseTmpPath(),
|
||||
'RNTesterAppJSC.zip',
|
||||
);
|
||||
ciArtifacts.downloadArtifact(hermesAppUrl, hermesAppZipPath);
|
||||
exec(`unzip ${hermesAppZipPath} -d ${appOutputFolder}`);
|
||||
}
|
||||
|
||||
// boot device
|
||||
const bootedDevice = String(
|
||||
exec('xcrun simctl list | grep "iPhone 16 Pro" | grep Booted', {
|
||||
silent: true,
|
||||
}),
|
||||
).trim();
|
||||
if (!bootedDevice || bootedDevice.length === 0) {
|
||||
exec('xcrun simctl boot "iPhone 16 Pro"');
|
||||
}
|
||||
|
||||
// install app on device
|
||||
exec(`xcrun simctl install booted ${appOutputFolder}`);
|
||||
|
||||
// launch the app on iOS simulator
|
||||
exec('xcrun simctl launch booted com.meta.RNTester.localDevelopment');
|
||||
} else {
|
||||
exec(
|
||||
`USE_HERMES=${
|
||||
argv.hermes === true ? 1 : 0
|
||||
} CI=${onReleaseBranch.toString()} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`,
|
||||
);
|
||||
|
||||
// launch the app on iOS simulator
|
||||
exec(
|
||||
'npx react-native run-ios --scheme RNTester --simulator "iPhone 15 Pro"',
|
||||
);
|
||||
}
|
||||
|
||||
// if everything succeeded so far, we can launch Metro and the app
|
||||
// start the Metro server in a separate window
|
||||
launchPackagerInSeparateWindow(pwd().toString());
|
||||
|
||||
// launch the app on iOS simulator
|
||||
exec(
|
||||
'npx react-native run-ios --scheme RNTester --simulator "iPhone 15 Pro"',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +227,7 @@ async function testRNTesterAndroid(
|
||||
* - @onReleaseBranch whether we are on a release branch or not
|
||||
*/
|
||||
async function testRNTester(
|
||||
circleCIArtifacts /*:Unwrap<ReturnType<typeof setupGHAArtifacts>> */,
|
||||
ciArtifacts /*:Unwrap<ReturnType<typeof setupGHAArtifacts>> */,
|
||||
onReleaseBranch /*: boolean */,
|
||||
) {
|
||||
// FIXME: make sure that the commands retains colors
|
||||
@@ -210,9 +236,9 @@ async function testRNTester(
|
||||
pushd('packages/rn-tester');
|
||||
|
||||
if (argv.platform === 'ios') {
|
||||
await testRNTesterIOS(circleCIArtifacts, onReleaseBranch);
|
||||
await testRNTesterIOS(ciArtifacts, onReleaseBranch);
|
||||
} else {
|
||||
await testRNTesterAndroid(circleCIArtifacts);
|
||||
await testRNTesterAndroid(ciArtifacts);
|
||||
}
|
||||
popd();
|
||||
}
|
||||
|
||||
@@ -214,6 +214,14 @@ async function artifactURLForHermesRNTesterAPK(
|
||||
return getArtifactURL('rntester-hermes-debug');
|
||||
}
|
||||
|
||||
async function artifactURLForJSCRNTesterApp() /*: Promise<string> */ {
|
||||
return getArtifactURL('RNTesterApp-NewArch-JSC-Debug');
|
||||
}
|
||||
|
||||
async function artifactURLForHermesRNTesterApp() /*: Promise<string> */ {
|
||||
return getArtifactURL('RNTesterApp-NewArch-Hermes-Debug');
|
||||
}
|
||||
|
||||
async function artifactURLForMavenLocal() /*: Promise<string> */ {
|
||||
return getArtifactURL('maven-local');
|
||||
}
|
||||
@@ -247,6 +255,8 @@ module.exports = {
|
||||
downloadArtifact,
|
||||
artifactURLForJSCRNTesterAPK,
|
||||
artifactURLForHermesRNTesterAPK,
|
||||
artifactURLForJSCRNTesterApp,
|
||||
artifactURLForHermesRNTesterApp,
|
||||
artifactURLForMavenLocal,
|
||||
artifactURLHermesDebug,
|
||||
artifactURLForReactNative,
|
||||
|
||||
Reference in New Issue
Block a user