Merge remote-tracking branch 'origin/master' into fb62merge

This commit is contained in:
Tom Underhill 2020-07-30 18:15:53 -07:00
Родитель a76a07b884 3ea5e7d30b
Коммит 3a564e024b
67 изменённых файлов: 1469 добавлений и 458 удалений

Просмотреть файл

@ -16,7 +16,7 @@ jobs:
- job: AndroidRNPR - job: AndroidRNPR
displayName: Android React Native PR displayName: Android React Native PR
pool: pool:
vmImage: vs2017-win2016 vmImage: ubuntu-18.04
timeoutInMinutes: 90 # how long to run the job before automatically cancelling timeoutInMinutes: 90 # how long to run the job before automatically cancelling
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
steps: steps:
@ -27,18 +27,27 @@ jobs:
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
persistCredentials: false # set to 'true' to leave the OAuth token in the Git config after the initial fetch persistCredentials: false # set to 'true' to leave the OAuth token in the Git config after the initial fetch
- task: UseNode@1
inputs:
version: '12.x'
- template: templates/apple-droid-node-patching.yml - template: templates/apple-droid-node-patching.yml
parameters: parameters:
apply_office_patches: true apply_office_patches: true
- task: UseNode@1 # Install NuGet
- task: CmdLine@2
inputs: inputs:
version: '10.x' script: mkdir $(System.DefaultWorkingDirectory)/nuget-bin/ && curl -o $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
# Install NuGet v4.6.4+
- task: NuGetToolInstaller@1 # This is currently required as the command task (strangely) always runs elevated ..
# which makes all the files touched by the above patching step unreadable by following non-command tasks without sudo.
# This makes all the files readable.
- task: CmdLine@2
displayName: chmod
inputs: inputs:
versionSpec: '>=4.6.4' script: chmod -R +r .
- task: CmdLine@2 - task: CmdLine@2
displayName: "Rename package to react-native" displayName: "Rename package to react-native"
@ -50,119 +59,41 @@ jobs:
inputs: inputs:
script: npm install script: npm install
- task: NuGetCommand@2
displayName: NuGet restore
inputs:
command: restore
restoreSolution: ReactAndroid/packages.config
feedsToUse: config
#vstsFeed: # Required when feedsToUse == Select
#includeNuGetOrg: true # Required when feedsToUse == Select
nugetConfigPath: ReactAndroid/NuGet.Config
#externalFeedCredentials: # Optional
#noCache: false
#disableParallelProcessing: false
restoreDirectory: packages/
verbosityRestore: Detailed # Options: quiet, normal, detailed
#packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' # Required when command == Push
#nuGetFeedType: 'internal' # Required when command == Push# Options: internal, external
#publishVstsFeed: # Required when command == Push && NuGetFeedType == Internal
#publishPackageMetadata: true # Optional
#allowPackageConflicts: # Optional
#publishFeedCredentials: # Required when command == Push && NuGetFeedType == External
#verbosityPush: 'Detailed' # Options: quiet, normal, detailed
#packagesToPack: '**/*.csproj' # Required when command == Pack
#configuration: '$(BuildConfiguration)' # Optional
#packDestination: '$(Build.ArtifactStagingDirectory)' # Optional
#versioningScheme: 'off' # Options: off, byPrereleaseNumber, byEnvVar, byBuildNumber
#includeReferencedProjects: false # Optional
#versionEnvVar: # Required when versioningScheme == ByEnvVar
#majorVersion: '1' # Required when versioningScheme == ByPrereleaseNumber
#minorVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
#patchVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
#packTimezone: 'utc' # Required when versioningScheme == ByPrereleaseNumber# Options: utc, local
#includeSymbols: false # Optional
#toolPackage: # Optional
#buildProperties: # Optional
#basePath: # Optional
#verbosityPack: 'Detailed' # Options: quiet, normal, detailed
#arguments: # Required when command == Custom
- task: CmdLine@2
displayName: Setup Build Dependencies
inputs:
script: .ado\setup_droid_deps.bat
- task: CmdLine@2 - task: CmdLine@2
displayName: Remove RNTesterApp.android.bundle displayName: Remove RNTesterApp.android.bundle
inputs: inputs:
script: del RNTesterApp.android.bundle script: rm -f RNTesterApp.android.bundle
- task: CmdLine@2 - task: CmdLine@2
displayName: Create RNTester bundle displayName: Create RNTester bundle
inputs: inputs:
script: node cli.js bundle --entry-file .\RNTester\js\RNTesterApp.android.js --bundle-output RNTesterApp.android.bundle --platform android script: node cli.js bundle --entry-file ./RNTester/js/RNTesterApp.android.js --bundle-output RNTesterApp.android.bundle --platform android
- task: Gradle@1 - task: CmdLine@2
displayName: gradlew installArchives displayName: gradlew installArchives
env:
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
inputs: inputs:
gradleWrapperFile: gradlew script: ./gradlew installArchives -Pparam="excludeLibs"
# workingDirectory: src\react-native\
options: -Pparam="excludeLibs"
tasks: installArchives
publishJUnitResults: false
#testResultsFiles: '**/TEST-*.xml' # Required when publishJUnitResults == True
#testRunTitle: # Optional
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
#codeCoverageClassFilter: # Optional
#codeCoverageFailIfEmpty: false # Optional
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
#jdkDirectory: # Required when javaHomeOption == Path
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
#gradleOptions: '-Xmx1024m' # Optional
#sonarQubeRunAnalysis: false
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
#checkStyleRunAnalysis: false # Optional
#findBugsRunAnalysis: false # Optional
#pmdRunAnalysis: false # Optional
- template: templates\prep-android-nuget.yml - template: templates\prep-android-nuget.yml
- task: NuGetCommand@2 # Very similar to the default pack task .. but appends 'ndk21' to the nuget pack version
- task: CmdLine@2
displayName: 'Verify NuGet can be packed' displayName: 'Verify NuGet can be packed'
inputs: inputs:
command: pack script: NDK=ndk`cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | awk '{ print $3}' | awk -F. '{ print $1 }'`; mono $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe pack $(System.DefaultWorkingDirectory)/ReactAndroid/ReactAndroid.nuspec -OutputDirectory $(System.DefaultWorkingDirectory) -Properties buildNumber=$(buildNumber)-$NDK;commitId=$(Build.SourceVersion)
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
packDestination: '$(System.DefaultWorkingDirectory)'
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
- task: Gradle@1 - task: CmdLine@2
displayName: 'Npm pack'
inputs:
script: node .ado/npmOfficePack.js --fake
env:
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
BUILD_SOURCESDIRECTORY: $(Build.SourcesDirectory)
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
githubApiToken: $(githubApiToken)
- task: CmdLine@2
displayName: gradlew clean displayName: gradlew clean
inputs: inputs:
gradleWrapperFile: gradlew script: ./gradlew clean
# workingDirectory: src\
#options: # Optional
tasks: clean
publishJUnitResults: false
#testResultsFiles: '**/build/test-results/TEST-*.xml'
#testRunTitle: # Optional
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
#codeCoverageClassFilter: # Optional
#codeCoverageFailIfEmpty: false # Optional
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
#jdkDirectory: # Required when javaHomeOption == Path
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
#gradleOptions: '-Xmx1024m' # Optional
#sonarQubeRunAnalysis: false
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
#checkStyleRunAnalysis: false # Optional
#findBugsRunAnalysis: false # Optional
#pmdRunAnalysis: false # Optional

Просмотреть файл

@ -0,0 +1,28 @@
REM @if "%DEBUG%" == "" @echo off
REM Android tools doesn't support SDK/NDK paths containing space in it.
REM This scrip creates a symlink to Android NDK to work around the limitation.
REM We use the
set ANDROID_NDK_SYMLINK_PATH=c:\android_ndk_symlink__
REM 1. Try ANDROID_NDK environment variable
set ANDROID_NDK_PATH=%ANDROID_NDK%
REM 2. May be SDK has ndk-bundle in it.
IF "%ANDROID_NDK_PATH%"=="" set ANDROID_NDK_PATH=%ANDROID_home%\ndk-bundle
echo %ANDROID_NDK_PATH%
if exist %ANDROID_NDK_PATH% (
mklink /J %ANDROID_NDK_SYMLINK_PATH% "%ANDROID_NDK_PATH%"
goto :success
) else (
goto :error
)
:success
exit /b 0
:error
exit /b 1

Просмотреть файл

@ -19,7 +19,7 @@ function exec(command) {
} }
} }
function doPublish() { function doPublish(fakeMode) {
console.log(`Target branch to publish to: ${publishBranchName}`); console.log(`Target branch to publish to: ${publishBranchName}`);
const {releaseVersion, branchVersionSuffix} = gatherVersionInfo() const {releaseVersion, branchVersionSuffix} = gatherVersionInfo()
@ -27,7 +27,7 @@ function doPublish() {
const onlyTagSource = !!branchVersionSuffix; const onlyTagSource = !!branchVersionSuffix;
if (!onlyTagSource) { if (!onlyTagSource) {
// -------- Generating Android Artifacts with JavaDoc // -------- Generating Android Artifacts with JavaDoc
exec("gradlew installArchives"); exec(path.join(process.env.BUILD_SOURCESDIRECTORY, "gradlew") + " installArchives");
// undo uncommenting javadoc setting // undo uncommenting javadoc setting
exec("git checkout ReactAndroid/gradle.properties"); exec("git checkout ReactAndroid/gradle.properties");
@ -40,7 +40,19 @@ function doPublish() {
const npmTarPath = path.resolve(__dirname, '..', npmTarFileName); const npmTarPath = path.resolve(__dirname, '..', npmTarFileName);
const finalTarPath = path.join(process.env.BUILD_STAGINGDIRECTORY, 'final', npmTarFileName); const finalTarPath = path.join(process.env.BUILD_STAGINGDIRECTORY, 'final', npmTarFileName);
console.log(`Copying tar file ${npmTarPath} to: ${finalTarPath}`) console.log(`Copying tar file ${npmTarPath} to: ${finalTarPath}`)
fs.copyFileSync(npmTarPath, finalTarPath);
if(fakeMode) {
if (!fs.existsSync(npmTarPath))
throw "The final artefact to be published is missing.";
} else {
fs.copyFileSync(npmTarPath, finalTarPath);
}
} }
doPublish(); var args = process.argv.slice(2);
let fakeMode = false;
if (args.length > 0 && args[0] === '--fake')
fakeMode = true;
doPublish(fakeMode);

Просмотреть файл

@ -39,10 +39,19 @@ jobs:
script: node .ado/bumpFileVersions.js script: node .ado/bumpFileVersions.js
- task: Npm@1 - task: Npm@1
displayName: "Publish react-native-macos to npmjs.org" displayName: "Publish latest react-native-macos to npmjs.org"
inputs: inputs:
command: 'publish' command: 'publish'
publishEndpoint: 'npmjs' publishEndpoint: 'npmjs'
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
- task: Npm@1
displayName: "Publish stable react-native-macos to npmjs.org"
inputs:
command: 'custom'
customCommand: publish --tag $(Build.SourceBranchName)
publishEndpoint: 'npmjs'
condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Tag published release' displayName: 'Tag published release'
@ -89,13 +98,12 @@ jobs:
displayName: "Publish react-native-macos-init to npmjs.org" displayName: "Publish react-native-macos-init to npmjs.org"
inputs: inputs:
script: | script: |
cd packages/react-native-macos-init npx beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
npx --no-install beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
- job: RNGithubOfficePublish - job: RNGithubOfficePublish
displayName: React-Native GitHub Publish to Office displayName: React-Native GitHub Publish to Office
pool: pool:
vmImage: vs2017-win2016 vmImage: ubuntu-18.04
timeoutInMinutes: 90 # how long to run the job before automatically cancelling timeoutInMinutes: 90 # how long to run the job before automatically cancelling
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
steps: steps:
@ -106,14 +114,27 @@ jobs:
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
persistCredentials: true # set to 'true' to leave the OAuth token in the Git config after the initial fetch persistCredentials: true # set to 'true' to leave the OAuth token in the Git config after the initial fetch
- task: UseNode@1
inputs:
version: '12.x'
- template: templates/apple-droid-node-patching.yml - template: templates/apple-droid-node-patching.yml
parameters: parameters:
apply_office_patches: true apply_office_patches: true
# Install NuGet v4.6.4+ # This is currently required as the command task (strangely) always runs elevated ..
- task: NuGetToolInstaller@1 # which makes all the files touched by the above patching step unreadable by following non-command tasks without sudo.
# This makes all the files readable.
- task: CmdLine@2
displayName: chmod
inputs: inputs:
versionSpec: '>=4.6.4' script: chmod -R +r .
# Install NuGet
- task: CmdLine@2
inputs:
script: mkdir $(System.DefaultWorkingDirectory)/nuget-bin/ && curl -o $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
continueOnError: true
- task: CmdLine@2 - task: CmdLine@2
displayName: "Rename package to react-native" displayName: "Rename package to react-native"
@ -130,86 +151,18 @@ jobs:
inputs: inputs:
script: node .ado/bumpOfficeFileVersions.js script: node .ado/bumpOfficeFileVersions.js
- task: NuGetCommand@2
displayName: NuGet restore
inputs:
command: restore
restoreSolution: ReactAndroid/packages.config
feedsToUse: config
#vstsFeed: # Required when feedsToUse == Select
#includeNuGetOrg: true # Required when feedsToUse == Select
nugetConfigPath: ReactAndroid/NuGet.Config
#externalFeedCredentials: # Optional
#noCache: false
#disableParallelProcessing: false
restoreDirectory: packages/
verbosityRestore: Detailed # Options: quiet, normal, detailed
#packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' # Required when command == Push
#nuGetFeedType: 'internal' # Required when command == Push# Options: internal, external
#publishVstsFeed: # Required when command == Push && NuGetFeedType == Internal
#publishPackageMetadata: true # Optional
#allowPackageConflicts: # Optional
#publishFeedCredentials: # Required when command == Push && NuGetFeedType == External
#verbosityPush: 'Detailed' # Options: quiet, normal, detailed
#packagesToPack: '**/*.csproj' # Required when command == Pack
#configuration: '$(BuildConfiguration)' # Optional
#packDestination: '$(Build.ArtifactStagingDirectory)' # Optional
#versioningScheme: 'off' # Options: off, byPrereleaseNumber, byEnvVar, byBuildNumber
#includeReferencedProjects: false # Optional
#versionEnvVar: # Required when versioningScheme == ByEnvVar
#majorVersion: '1' # Required when versioningScheme == ByPrereleaseNumber
#minorVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
#patchVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
#packTimezone: 'utc' # Required when versioningScheme == ByPrereleaseNumber# Options: utc, local
#includeSymbols: false # Optional
#toolPackage: # Optional
#buildProperties: # Optional
#basePath: # Optional
#verbosityPack: 'Detailed' # Options: quiet, normal, detailed
#arguments: # Required when command == Custom
- task: CmdLine@2 - task: CmdLine@2
displayName: Setup Build Dependencies
inputs:
script: .ado\setup_droid_deps.bat
- task: Gradle@1
displayName: gradlew installArchives displayName: gradlew installArchives
env:
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
inputs: inputs:
gradleWrapperFile: gradlew script: ./gradlew installArchives -Pparam="excludeLibs"
# workingDirectory: src\react-native\
options: -Pparam="excludeLibs"
tasks: installArchives
publishJUnitResults: false
#testResultsFiles: '**/TEST-*.xml' # Required when publishJUnitResults == True
#testRunTitle: # Optional
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
#codeCoverageClassFilter: # Optional
#codeCoverageFailIfEmpty: false # Optional
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
#jdkDirectory: # Required when javaHomeOption == Path
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
#gradleOptions: '-Xmx1024m' # Optional
#sonarQubeRunAnalysis: false
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
#checkStyleRunAnalysis: false # Optional
#findBugsRunAnalysis: false # Optional
#pmdRunAnalysis: false # Optional
- template: templates\prep-android-nuget.yml - template: templates\prep-android-nuget.yml
- task: NuGetCommand@2 # Very similar to the default pack task .. but appends 'ndk21b' to the nuget pack version
- task: CmdLine@2
displayName: 'NuGet pack' displayName: 'NuGet pack'
inputs: inputs:
command: pack script: OUTPUT_DIR=$(Build.StagingDirectory)/final;NDK=ndk`cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | awk '{ print $3}' | awk -F. '{ print $1 }'`; mono $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe pack $(System.DefaultWorkingDirectory)/ReactAndroid/ReactAndroid.nuspec -OutputDirectory $OUTPUT_DIR -Properties buildNumber=$(buildNumber)-$NDK;commitId=$(Build.SourceVersion)
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
packDestination: '$(Build.StagingDirectory)\final'
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Npm pack' displayName: 'Npm pack'
@ -217,6 +170,7 @@ jobs:
script: node .ado/npmOfficePack.js script: node .ado/npmOfficePack.js
env: env:
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory) BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
BUILD_SOURCESDIRECTORY: $(Build.SourcesDirectory)
BUILD_SOURCEBRANCH: $(Build.SourceBranch) BUILD_SOURCEBRANCH: $(Build.SourceBranch)
SYSTEM_ACCESSTOKEN: $(System.AccessToken) SYSTEM_ACCESSTOKEN: $(System.AccessToken)
githubApiToken: $(githubApiToken) githubApiToken: $(githubApiToken)
@ -224,5 +178,5 @@ jobs:
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
displayName: 'Publish final artifacts' displayName: 'Publish final artifacts'
inputs: inputs:
PathtoPublish: '$(Build.StagingDirectory)\final' PathtoPublish: '$(Build.StagingDirectory)/final'
ArtifactName: 'ReactNative-Final' ArtifactName: 'ReactNative-Final'

11
.ado/setup_droid_deps.sh Executable file
Просмотреть файл

@ -0,0 +1,11 @@
#!/usr/bin/env bash
BUILD_DEPS_DIR=build_deps
rm -rf $BUILD_DEPS_DIR
mkdir $BUILD_DEPS_DIR
ln -s "$PWD/ReactAndroid/packages/boost.1.68.0.0/lib/native/include/boost" "$BUILD_DEPS_DIR/boost"
ln -s "$PWD/double-conversion/double-conversion" "$BUILD_DEPS_DIR/double-conversion"
ln -s "$PWD/Folly/" "$BUILD_DEPS_DIR/Folly"
ln -s "$PWD/glog/" "$BUILD_DEPS_DIR/glog"

Просмотреть файл

@ -5,4 +5,4 @@ steps:
- task: CmdLine@2 - task: CmdLine@2
displayName: Apply Android specific patches for Office consumption displayName: Apply Android specific patches for Office consumption
inputs: inputs:
script: node $(System.DefaultWorkingDirectory)/android-patches/bundle/bundle.js patch $(System.DefaultWorkingDirectory) BasicBuild V8Integration RNHostBase Dialog Typeface --patch-store $(System.DefaultWorkingDirectory)/android-patches/patches-0.62.2 --log-folder $(System.DefaultWorkingDirectory)/android-patches/logs --confirm ${{ parameters.apply_office_patches }} script: node $(System.DefaultWorkingDirectory)/android-patches/bundle/bundle.js patch $(System.DefaultWorkingDirectory) BasicBuild --patch-store $(System.DefaultWorkingDirectory)/android-patches/patches-0.61.5 --log-folder $(System.DefaultWorkingDirectory)/android-patches/logs --confirm ${{ parameters.apply_office_patches }}

Просмотреть файл

@ -2,11 +2,14 @@ parameters:
apply_office_patches: '' apply_office_patches: ''
steps: steps:
- script: 'brew update'
displayName: 'brew update'
- script: 'brew bundle' - script: 'brew bundle'
displayName: 'brew bundle' displayName: 'brew bundle'
- script: brew link node@10 --overwrite --force - script: brew link node@12 --overwrite --force
displayName: 'ensure node 10' displayName: 'ensure node 12'
- template: apple-xcode-select.yml - template: apple-xcode-select.yml

Просмотреть файл

@ -15,10 +15,14 @@ steps:
displayName: 'Clean DerivedData' displayName: 'Clean DerivedData'
# Install the required components specified in the Brewfile file. # Install the required components specified in the Brewfile file.
- script: 'brew update'
displayName: 'brew update'
- script: 'brew bundle' - script: 'brew bundle'
displayName: 'brew bundle' displayName: 'brew bundle'
- script: brew link node@10 --overwrite --force - script: brew link node@12 --overwrite --force
displayName: 'ensure node 12'
# Task Group: XCode select proper version # Task Group: XCode select proper version
- template: apple-xcode-select.yml - template: apple-xcode-select.yml

Просмотреть файл

@ -70,8 +70,7 @@ steps:
displayName: Publish react-native-macos to verdaccio displayName: Publish react-native-macos to verdaccio
- script: | - script: |
cd packages/react-native-macos-init npx beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
npx --no-install beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
displayName: Publish react-native-macos-init to verdaccio displayName: Publish react-native-macos-init to verdaccio
- task: CmdLine@2 - task: CmdLine@2
@ -91,12 +90,6 @@ steps:
script: npx react-native-macos-init --version latest --overwrite --prerelease script: npx react-native-macos-init --version latest --overwrite --prerelease
workingDirectory: $(Agent.BuildDirectory)/testcli workingDirectory: $(Agent.BuildDirectory)/testcli
- task: CmdLine@2
displayName: Install pods
inputs:
script: pod install
workingDirectory: $(Agent.BuildDirectory)/testcli/macos
- task: CmdLine@2 - task: CmdLine@2
displayName: Run macos displayName: Run macos
inputs: inputs:

Просмотреть файл

@ -1,2 +1,2 @@
brew "node@10" brew "node@12"
brew "watchman" brew "watchman"

60
Brewfile.lock.json Normal file
Просмотреть файл

@ -0,0 +1,60 @@
{
"entries": {
"brew": {
"node@12": {
"version": "12.18.3",
"bottle": {
"cellar": ":any",
"prefix": "/usr/local",
"files": {
"catalina": {
"url": "https://homebrew.bintray.com/bottles/node%4012-12.18.3.catalina.bottle.tar.gz",
"sha256": "8371625cae6cd2efa83e52a49d3c2e389e8d6be8261a0c80a710750e89ddf7d8"
},
"mojave": {
"url": "https://homebrew.bintray.com/bottles/node%4012-12.18.3.mojave.bottle.tar.gz",
"sha256": "f410b99756e3247145b43f2775d4ad00b99dcdf4366fac74c05daef7c771cb60"
},
"high_sierra": {
"url": "https://homebrew.bintray.com/bottles/node%4012-12.18.3.high_sierra.bottle.tar.gz",
"sha256": "5de456604c237daac3f9d3dd8b03cb13ce8d7c3efacf644093a4a3da4f8f1a53"
}
}
}
},
"watchman": {
"version": "4.9.0_4",
"bottle": {
"cellar": "/usr/local/Cellar",
"prefix": "/usr/local",
"files": {
"catalina": {
"url": "https://homebrew.bintray.com/bottles/watchman-4.9.0_4.catalina.bottle.tar.gz",
"sha256": "7840f564c11d33425c9eb8985f9156e782e66ef2a3578329dba83ee15a9bf0be"
},
"mojave": {
"url": "https://homebrew.bintray.com/bottles/watchman-4.9.0_4.mojave.bottle.tar.gz",
"sha256": "ba2338b0f23c8b8817fd7bfa92466b7a97ab416e93ec6c3a400041aef013de86"
},
"high_sierra": {
"url": "https://homebrew.bintray.com/bottles/watchman-4.9.0_4.high_sierra.bottle.tar.gz",
"sha256": "150468653b5c5a8e4eb92a3ecf420f157ed0e4772513ee93425bb3f635964dad"
}
}
}
}
}
},
"system": {
"macos": {
"catalina": {
"HOMEBREW_VERSION": "2.4.9",
"HOMEBREW_PREFIX": "/usr/local",
"Homebrew/homebrew-core": "8a19447722a5bd15a5ce806d5d35178f30990e4d",
"CLT": "",
"Xcode": "11.5",
"macOS": "10.15.6"
}
}
}
}

Просмотреть файл

@ -12,10 +12,29 @@
'use strict'; 'use strict';
const Promise = require('../../Promise');
const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter');
import NativeAccessibilityManager from './NativeAccessibilityManager';
const warning = require('fbjs/lib/warning'); const warning = require('fbjs/lib/warning');
type ChangeEventName = $Keys<{}>; const CHANGE_EVENT_NAME = {
invertColorsChanged: 'invertColorsChanged',
reduceMotionChanged: 'reduceMotionChanged',
reduceTransparencyChanged: 'reduceTransparencyChanged',
screenReaderChanged: 'screenReaderChanged',
};
type ChangeEventName = $Keys<{
change: string,
invertColorsChanged: string,
reduceMotionChanged: string,
reduceTransparencyChanged: string,
screenReaderChanged: string,
}>;
const _subscriptions = new Map();
const AccessibilityInfo = { const AccessibilityInfo = {
/** /**
* iOS only * iOS only
@ -32,31 +51,78 @@ const AccessibilityInfo = {
}, },
/** /**
* iOS only * Query whether inverted colors are currently enabled.
*
* Returns a promise which resolves to a boolean.
* The result is `true` when invert color is enabled and `false` otherwise.
*
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isInvertColorsEnabled
*/ */
isInvertColorsEnabled: function(): Promise<boolean> { isInvertColorsEnabled: function(): Promise<boolean> {
return Promise.resolve(false); return new Promise((resolve, reject) => {
if (NativeAccessibilityManager) {
NativeAccessibilityManager.getCurrentInvertColorsState(resolve, reject);
} else {
reject(reject);
}
});
}, },
/** /**
* Android and iOS only * Query whether reduced motion is currently enabled.
*
* Returns a promise which resolves to a boolean.
* The result is `true` when a reduce motion is enabled and `false` otherwise.
*
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceMotionEnabled
*/ */
isReduceMotionEnabled: function(): Promise<boolean> { isReduceMotionEnabled: function(): Promise<boolean> {
return Promise.resolve(false); return new Promise((resolve, reject) => {
if (NativeAccessibilityManager) {
NativeAccessibilityManager.getCurrentReduceMotionState(resolve, reject);
} else {
reject(reject);
}
});
}, },
/** /**
* iOS only * Query whether reduced transparency is currently enabled.
*
* Returns a promise which resolves to a boolean.
* The result is `true` when a reduce transparency is enabled and `false` otherwise.
*
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceTransparencyEnabled
*/ */
isReduceTransparencyEnabled: function(): Promise<boolean> { isReduceTransparencyEnabled: function(): Promise<boolean> {
return Promise.resolve(false); return new Promise((resolve, reject) => {
if (NativeAccessibilityManager) {
NativeAccessibilityManager.getCurrentReduceTransparencyState(
resolve,
reject,
);
} else {
reject(reject);
}
});
}, },
/** /**
* Android and iOS only * Query whether a screen reader is currently enabled.
*
* Returns a promise which resolves to a boolean.
* The result is `true` when a screen reader is enabled and `false` otherwise.
*
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isScreenReaderEnabled
*/ */
isScreenReaderEnabled: function(): Promise<boolean> { isScreenReaderEnabled: function(): Promise<boolean> {
return Promise.resolve(false); return new Promise((resolve, reject) => {
if (NativeAccessibilityManager) {
NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject);
} else {
reject(reject);
}
});
}, },
/** /**
@ -71,15 +137,38 @@ const AccessibilityInfo = {
addEventListener: function( addEventListener: function(
eventName: ChangeEventName, eventName: ChangeEventName,
handler: Function, handler: Function,
): void { ): Object {
warning(false, 'AccessibilityInfo is not supported on this platform.'); let listener;
if (eventName === 'change') {
listener = RCTDeviceEventEmitter.addListener(
CHANGE_EVENT_NAME.screenReaderChanged,
handler,
);
} else if (CHANGE_EVENT_NAME[eventName]) {
listener = RCTDeviceEventEmitter.addListener(eventName, handler);
}
_subscriptions.set(handler, listener);
return {
remove: AccessibilityInfo.removeEventListener.bind(
null,
eventName,
handler,
),
};
}, },
removeEventListener: function( removeEventListener: function(
eventName: ChangeEventName, eventName: ChangeEventName,
handler: Function, handler: Function,
): void { ): void {
warning(false, 'AccessibilityInfo is not supported on this platform.'); const listener = _subscriptions.get(handler);
if (!listener) {
return;
}
listener.remove();
_subscriptions.delete(handler);
}, },
/** /**
@ -88,7 +177,9 @@ const AccessibilityInfo = {
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus
*/ */
setAccessibilityFocus: function(reactTag: number): void { setAccessibilityFocus: function(reactTag: number): void {
warning(false, 'AccessibilityInfo is not supported on this platform.'); if (NativeAccessibilityManager) {
NativeAccessibilityManager.setAccessibilityFocus(reactTag);
}
}, },
/** /**
@ -97,7 +188,9 @@ const AccessibilityInfo = {
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility
*/ */
announceForAccessibility: function(announcement: string): void { announceForAccessibility: function(announcement: string): void {
warning(false, 'AccessibilityInfo is not supported on this platform.'); if (NativeAccessibilityManager) {
NativeAccessibilityManager.announceForAccessibility(announcement);
}
}, },
}; };

Просмотреть файл

@ -21,6 +21,7 @@ const View = require('./View/View');
const invariant = require('invariant'); const invariant = require('invariant');
import type {PressEvent} from '../Types/CoreEventTypes'; import type {PressEvent} from '../Types/CoreEventTypes';
import type {FocusEvent, BlurEvent} from './TextInput/TextInput'; // TODO(OSS Candidate ISS#2710739)
type ButtonProps = $ReadOnly<{| type ButtonProps = $ReadOnly<{|
/** /**
@ -100,6 +101,18 @@ type ButtonProps = $ReadOnly<{|
* Used to locate this view in end-to-end tests. * Used to locate this view in end-to-end tests.
*/ */
testID?: ?string, testID?: ?string,
// [TODO(OSS Candidate ISS#2710739)
/**
* Handler to be called when the button receives key focus
*/
onBlur?: ?(e: BlurEvent) => void,
/**
* Handler to be called when the button loses key focus
*/
onFocus?: ?(e: FocusEvent) => void,
// ]TODO(OSS Candidate ISS#2710739)
|}>; |}>;
/** /**
@ -147,6 +160,8 @@ class Button extends React.Component<ButtonProps> {
nextFocusUp, nextFocusUp,
disabled, disabled,
testID, testID,
onFocus, // TODO(OSS Candidate ISS#2710739)
onBlur, // TODO(OSS Candidate ISS#2710739)
} = this.props; } = this.props;
const buttonStyles = [styles.button]; const buttonStyles = [styles.button];
const textStyles = [styles.text]; const textStyles = [styles.text];
@ -189,6 +204,8 @@ class Button extends React.Component<ButtonProps> {
testID={testID} testID={testID}
disabled={disabled} disabled={disabled}
onPress={onPress} onPress={onPress}
onFocus={onFocus} // TODO(OSS Candidate ISS#2710739)
onBlur={onBlur} // TODO(OSS Candidate ISS#2710739)
touchSoundDisabled={touchSoundDisabled}> touchSoundDisabled={touchSoundDisabled}>
<View style={buttonStyles}> <View style={buttonStyles}>
<Text style={textStyles} disabled={disabled}> <Text style={textStyles} disabled={disabled}>

Просмотреть файл

@ -1129,6 +1129,8 @@ function InternalTextInput(props: Props): React.Node {
<TouchableWithoutFeedback <TouchableWithoutFeedback
onLayout={props.onLayout} onLayout={props.onLayout}
onPress={_onPress} onPress={_onPress}
onFocus={_onFocus} // TODO(macOS ISS#2323203)
onBlur={_onBlur} // TODO(macOS ISS#2323203)
accessible={props.accessible} accessible={props.accessible}
accessibilityLabel={props.accessibilityLabel} accessibilityLabel={props.accessibilityLabel}
accessibilityRole={props.accessibilityRole} accessibilityRole={props.accessibilityRole}

Просмотреть файл

@ -185,6 +185,8 @@ class TouchableBounce extends React.Component<Props, State> {
onDragEnter={this.props.onDragEnter} onDragEnter={this.props.onDragEnter}
onDragLeave={this.props.onDragLeave} onDragLeave={this.props.onDragLeave}
onDrop={this.props.onDrop} onDrop={this.props.onDrop}
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203) draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
ref={this.props.hostRef} ref={this.props.hostRef}
{...eventHandlersWithoutBlurAndFocus}> {...eventHandlersWithoutBlurAndFocus}>

Просмотреть файл

@ -339,6 +339,8 @@ class TouchableHighlight extends React.Component<Props, State> {
onDragEnter={this.props.onDragEnter} onDragEnter={this.props.onDragEnter}
onDragLeave={this.props.onDragLeave} onDragLeave={this.props.onDragLeave}
onDrop={this.props.onDrop} onDrop={this.props.onDrop}
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
draggedTypes={this.props.draggedTypes} // ]TODO(macOS/win ISS#2323203) draggedTypes={this.props.draggedTypes} // ]TODO(macOS/win ISS#2323203)
nativeID={this.props.nativeID} nativeID={this.props.nativeID}
testID={this.props.testID} testID={this.props.testID}

Просмотреть файл

@ -275,6 +275,8 @@ class TouchableOpacity extends React.Component<Props, State> {
onDragEnter={this.props.onDragEnter} onDragEnter={this.props.onDragEnter}
onDragLeave={this.props.onDragLeave} onDragLeave={this.props.onDragLeave}
onDrop={this.props.onDrop} onDrop={this.props.onDrop}
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203) draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
ref={this.props.hostRef} ref={this.props.hostRef}
{...eventHandlersWithoutBlurAndFocus}> {...eventHandlersWithoutBlurAndFocus}>

Просмотреть файл

@ -16,22 +16,22 @@ const ReactNativeViewViewConfigMacOS = {
uiViewClassName: 'RCTView', uiViewClassName: 'RCTView',
directEventTypes: { directEventTypes: {
topDoubleClick: { topDoubleClick: {
registrationName: 'topDoubleClick', registrationName: 'onDoubleClick',
}, },
topDragEnter: { topDragEnter: {
registrationName: 'topDragEnter', registrationName: 'onDragEnter',
}, },
topDragLeave: { topDragLeave: {
registrationName: 'topDragLeave', registrationName: 'onDragLeave',
}, },
topDrop: { topDrop: {
registrationName: 'topDrop', registrationName: 'onDrop',
}, },
topMouseEnter: { topMouseEnter: {
registrationName: 'topMouseEnter', registrationName: 'onMouseEnter',
}, },
topMouseLeave: { topMouseLeave: {
registrationName: 'topMouseLeave', registrationName: 'onMouseLeave',
}, },
}, },
validAttributes: { validAttributes: {

Просмотреть файл

@ -8,25 +8,19 @@
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203) #import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
#if !TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // [TODO(macOS ISS#2323203)
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#endif // [TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
UIImageRenderingModeAlwaysOriginal,
UIImageRenderingModeAlwaysTemplate,
};
#endif // ]TODO(macOS ISS#2323203)
#import <React/RCTView.h> #import <React/RCTView.h>
#import <React/RCTResizeMode.h> #import <React/RCTResizeMode.h>
@class RCTBridge; @class RCTBridge;
@class RCTImageSource; @class RCTImageSource;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) @interface RCTImageView : RCTView
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
UIImageRenderingModeAlwaysOriginal,
UIImageRenderingModeAlwaysTemplate,
};
#endif
#if !TARGET_OS_OSX // ]TODO(macOS ISS#2323203)
@interface RCTImageView : UIImageView
#else // [TODO(macOS ISS#2323203)
@interface RCTImageView : NSImageView
#endif // ]TODO(macOS ISS#2323203)
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
@ -38,15 +32,6 @@ typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
@property (nonatomic, assign) RCTResizeMode resizeMode; @property (nonatomic, assign) RCTResizeMode resizeMode;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
/** @property (nonatomic, copy) NSColor *tintColor;
* macOS Properties
*/
@property (nonatomic, copy) RCTDirectEventBlock onDoubleClick;
@property (nonatomic, copy) RCTDirectEventBlock onClick;
@property (nonatomic, copy) RCTDirectEventBlock onMouseEnter;
@property (nonatomic, copy) RCTDirectEventBlock onMouseLeave;
@property (nonatomic, copy) RCTDirectEventBlock onDragEnter;
@property (nonatomic, copy) RCTDirectEventBlock onDragLeave;
@property (nonatomic, copy) RCTDirectEventBlock onDrop;
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
@end @end

Просмотреть файл

@ -283,17 +283,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_imageView.contentMode = UIViewContentModeScaleToFill; _imageView.contentMode = UIViewContentModeScaleToFill;
#else // [TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
self.imageScaling = NSImageScaleAxesIndependently; _imageView.imageScaling = NSImageScaleAxesIndependently;
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
} else { } else {
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_imageView.contentMode = (UIViewContentMode)resizeMode; _imageView.contentMode = (UIViewContentMode)resizeMode;
#else // [TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
// This relies on having previously resampled the image to a size that exceeds the iamge view. // This relies on having previously resampled the image to a size that exceeds the image view.
if (resizeMode == RCTResizeModeCover) { if (resizeMode == RCTResizeModeCover) {
resizeMode = RCTResizeModeCenter; resizeMode = RCTResizeModeCenter;
} }
self.imageScaling = (NSImageScaling)resizeMode; _imageView.imageScaling = (NSImageScaling)resizeMode;
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
} }
@ -617,5 +617,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
{ {
[self reloadImage]; [self reloadImage];
} }
- (RCTPlatformView *)reactAccessibilityElement
{
return (RCTPlatformView *)_imageView.cell;
}
- (NSColor *)tintColor
{
NSColor *tintColor = nil;
if (@available(macOS 10.14, *)) {
tintColor = _imageView.contentTintColor;
}
return tintColor;
}
- (void)setTintColor:(NSColor *)tintColor
{
if (@available(macOS 10.14, *)) {
_imageView.contentTintColor = tintColor;
}
}
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
@end @end

Просмотреть файл

@ -41,7 +41,6 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode) RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>); RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>);
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView) RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
{ {
// Default tintColor isn't nil - it's inherited from the superView - but we // Default tintColor isn't nil - it's inherited from the superView - but we
@ -50,7 +49,6 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
view.tintColor = [RCTConvert UIColor:json] ?: defaultView.tintColor; view.tintColor = [RCTConvert UIColor:json] ?: defaultView.tintColor;
view.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode; view.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode;
} }
#endif // TODO(macOS ISS#2323203)
RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request
successBlock:(RCTResponseSenderBlock)successBlock successBlock:(RCTResponseSenderBlock)successBlock

Просмотреть файл

@ -47,6 +47,7 @@ function nativeImageSource(spec: NativeImageSourceSpec): ImageURISource {
android: spec.android, android: spec.android,
default: spec.default, default: spec.default,
ios: spec.ios, ios: spec.ios,
macos: spec.macos, // TODO(macOS ISS#2323203)
}); });
if (uri == null) { if (uri == null) {
console.warn( console.warn(

Просмотреть файл

@ -2163,6 +2163,7 @@ class CellRenderer extends React.Component<
return renderItem({ return renderItem({
item, item,
index, index,
isSelected, // TODO(macOS ISS#2323203)
separators: this._separators, separators: this._separators,
}); });
} }

Просмотреть файл

@ -6,6 +6,7 @@
*/ */
#import <React/RCTComponent.h> #import <React/RCTComponent.h>
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203) #import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
@ -13,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface RCTTextView : RCTUIView // TODO(macOS ISS#3536887) @interface RCTTextView : RCTUIView // TODO(macOS ISS#3536887)
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher; // TODO(OSS Candidate ISS#2710739)
@property (nonatomic, assign) BOOL selectable; @property (nonatomic, assign) BOOL selectable;
- (void)setTextStorage:(NSTextStorage *)textStorage - (void)setTextStorage:(NSTextStorage *)textStorage

Просмотреть файл

@ -16,6 +16,7 @@
#import <React/RCTAssert.h> // TODO(macOS ISS#2323203) #import <React/RCTAssert.h> // TODO(macOS ISS#2323203)
#import <React/RCTUtils.h> #import <React/RCTUtils.h>
#import <React/UIView+React.h> #import <React/UIView+React.h>
#import <React/RCTFocusChangeEvent.h> // TODO(OSS Candidate ISS#2710739)
#import <React/RCTTextShadowView.h> #import <React/RCTTextShadowView.h>
@ -26,13 +27,26 @@
CAShapeLayer *_highlightLayer; CAShapeLayer *_highlightLayer;
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
UILongPressGestureRecognizer *_longPressGestureRecognizer; UILongPressGestureRecognizer *_longPressGestureRecognizer;
#endif // TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
NSString * _accessibilityLabel;
#endif // ]TODO(macOS ISS#2323203)
RCTEventDispatcher *_eventDispatcher; // TODO(OSS Candidate ISS#2710739)
NSArray<RCTUIView *> *_Nullable _descendantViews; // TODO(macOS ISS#3536887) NSArray<RCTUIView *> *_Nullable _descendantViews; // TODO(macOS ISS#3536887)
NSTextStorage *_Nullable _textStorage; NSTextStorage *_Nullable _textStorage;
CGRect _contentFrame; CGRect _contentFrame;
} }
// [TODO(OSS Candidate ISS#2710739)
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if ((self = [self initWithFrame:CGRectZero])) {
_eventDispatcher = eventDispatcher;
}
return self;
}
// ]TODO(OSS Candidate ISS#2710739)
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
@ -49,6 +63,25 @@
} }
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
- (void)dealloc
{
[self removeAllTextStorageLayoutManagers];
}
- (void)removeAllTextStorageLayoutManagers
{
// On macOS AppKit can throw an uncaught exception
// (-[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index ...)
// during the dealloc of NSLayoutManager. The _textStorage and its
// associated NSLayoutManager dealloc later in an autorelease pool.
// Manually removing the layout managers from _textStorage prior to release
// works around this issue in AppKit.
NSArray<NSLayoutManager *> *managers = [[_textStorage layoutManagers] copy];
for (NSLayoutManager *manager in managers) {
[_textStorage removeLayoutManager:manager];
}
}
- (BOOL)canBecomeKeyView - (BOOL)canBecomeKeyView
{ {
// RCTText should not get any keyboard focus unless its `selectable` prop is true // RCTText should not get any keyboard focus unless its `selectable` prop is true
@ -118,17 +151,7 @@
descendantViews:(NSArray<RCTUIView *> *)descendantViews // TODO(macOS ISS#3536887) descendantViews:(NSArray<RCTUIView *> *)descendantViews // TODO(macOS ISS#3536887)
{ {
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
// On macOS when a large number of flex layouts are being performed, such [self removeAllTextStorageLayoutManagers];
// as when a window is being resized, AppKit can throw an uncaught exception
// (-[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index ...)
// during the dealloc of NSLayoutManager. The _textStorage and its
// associated NSLayoutManager dealloc later in an autorelease pool.
// Manually removing the layout manager from _textStorage prior to release
// works around this issue in AppKit.
NSArray<NSLayoutManager *> *managers = [_textStorage layoutManagers];
for (NSLayoutManager *manager in managers) {
[_textStorage removeLayoutManager:manager];
}
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
_textStorage = textStorage; _textStorage = textStorage;
@ -273,6 +296,28 @@
#pragma mark - Accessibility #pragma mark - Accessibility
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
// This code is here to cover for a mismatch in the what accessibilityLabels and accessibilityValues mean in iOS versus macOS.
// In macOS a text element will always read its accessibilityValue, but will only read it's accessibilityLabel if it's value is set.
// In iOS a text element will only read it's accessibilityValue if it has no accessibilityLabel, and will always read its accessibilityLabel.
// This code replicates the expected behavior in macOS by:
// 1) Setting the accessibilityValue = the react-native accessibilityLabel prop if one exists and setting it equal to the text's contents otherwise.
// 2) Making sure that its accessibilityLabel is always nil, so that it doesn't read out the label twice.
- (void)setAccessibilityLabel:(NSString *)label
{
_accessibilityLabel = [label copy];
}
- (NSString *)accessibilityValue
{
if (_accessibilityLabel) {
return _accessibilityLabel;
}
return _textStorage.string;
}
#else // ]TODO(macOS ISS#2323203)
- (NSString *)accessibilityLabel - (NSString *)accessibilityLabel
{ {
NSString *superAccessibilityLabel = [super accessibilityLabel]; NSString *superAccessibilityLabel = [super accessibilityLabel];
@ -281,6 +326,7 @@
} }
return _textStorage.string; return _textStorage.string;
} }
#endif // TODO(macOS ISS#2323203)
#pragma mark - Context Menu #pragma mark - Context Menu
@ -349,6 +395,31 @@
} }
} }
} }
- (BOOL)becomeFirstResponder
{
if (![super becomeFirstResponder]) {
return NO;
}
// If we've gained focus, notify listeners
[_eventDispatcher sendEvent:[RCTFocusChangeEvent focusEventWithReactTag:self.reactTag]];
return YES;
}
- (BOOL)resignFirstResponder
{
if (![super resignFirstResponder]) {
return NO;
}
// If we've lost focus, notify listeners
[_eventDispatcher sendEvent:[RCTFocusChangeEvent blurEventWithReactTag:self.reactTag]];
return YES;
}
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
- (BOOL)canBecomeFirstResponder - (BOOL)canBecomeFirstResponder

Просмотреть файл

@ -54,7 +54,7 @@ RCT_EXPORT_VIEW_PROPERTY(selectable, BOOL)
- (RCTUIView *)view // TODO(macOS ISS#3536887) - (RCTUIView *)view // TODO(macOS ISS#3536887)
{ {
return [RCTTextView new]; return [[RCTTextView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
} }
- (RCTShadowView *)shadowView - (RCTShadowView *)shadowView

Просмотреть файл

@ -191,6 +191,9 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
// enter/return // enter/return
if (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:)) { if (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:)) {
[self textFieldDidEndEditingOnExit]; [self textFieldDidEndEditingOnExit];
if ([[_backedTextInputView textInputDelegate] textInputShouldReturn]) {
[[_backedTextInputView window] makeFirstResponder:nil];
}
commandHandled = YES; commandHandled = YES;
//backspace //backspace
} else if (commandSelector == @selector(deleteBackward:)) { } else if (commandSelector == @selector(deleteBackward:)) {
@ -298,18 +301,16 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
- (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text - (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{ {
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
// Custom implementation of `textInputShouldReturn` and `textInputDidReturn` pair for `UITextView`. // Custom implementation of `textInputShouldReturn` and `textInputDidReturn` pair for `UITextView`.
if (!_backedTextInputView.textWasPasted && [text isEqualToString:@"\n"]) { if (!_backedTextInputView.textWasPasted && [text isEqualToString:@"\n"]) {
if ([_backedTextInputView.textInputDelegate textInputShouldReturn]) { if ([_backedTextInputView.textInputDelegate textInputShouldReturn]) {
[_backedTextInputView.textInputDelegate textInputDidReturn]; [_backedTextInputView.textInputDelegate textInputDidReturn];
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
[_backedTextInputView endEditing:NO]; [_backedTextInputView endEditing:NO];
#else // [TODO(macOS ISS#2323203)
[[_backedTextInputView window] endEditingFor:nil];
#endif // ]TODO(macOS ISS#2323203)
return NO; return NO;
} }
} }
#endif // ]TODO(macOS ISS#2323203)
NSString *newText = NSString *newText =
[_backedTextInputView.textInputDelegate textInputShouldChangeText:text inRange:range]; [_backedTextInputView.textInputDelegate textInputShouldChangeText:text inRange:range];
@ -399,9 +400,11 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
BOOL commandHandled = NO; BOOL commandHandled = NO;
id<RCTBackedTextInputDelegate> textInputDelegate = [_backedTextInputView textInputDelegate]; id<RCTBackedTextInputDelegate> textInputDelegate = [_backedTextInputView textInputDelegate];
// enter/return // enter/return
if (textInputDelegate.textInputShouldReturn && (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) { if ((commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) {
[_backedTextInputView.window makeFirstResponder:nil]; if (textInputDelegate.textInputShouldReturn) {
commandHandled = YES; [_backedTextInputView.window makeFirstResponder:nil];
commandHandled = YES;
}
//backspace //backspace
} else if (commandSelector == @selector(deleteBackward:)) { } else if (commandSelector == @selector(deleteBackward:)) {
commandHandled = textInputDelegate != nil && ![textInputDelegate textInputShouldHandleDeleteBackward:_backedTextInputView]; commandHandled = textInputDelegate != nil && ![textInputDelegate textInputShouldHandleDeleteBackward:_backedTextInputView];

Просмотреть файл

@ -348,7 +348,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus [_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
reactTag:self.reactTag reactTag:self.reactTag
text:self.backedTextInputView.attributedText.string text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
key:nil key:nil
eventCount:_nativeEventCount]; eventCount:_nativeEventCount];
} }
@ -362,13 +362,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
{ {
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd [_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
reactTag:self.reactTag reactTag:self.reactTag
text:self.backedTextInputView.attributedText.string text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
key:nil key:nil
eventCount:_nativeEventCount]; eventCount:_nativeEventCount];
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur [_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
reactTag:self.reactTag reactTag:self.reactTag
text:self.backedTextInputView.attributedText.string text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
key:nil key:nil
eventCount:_nativeEventCount]; eventCount:_nativeEventCount];
} }
@ -380,11 +380,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
// `onSubmitEditing` is called when "Submit" button // `onSubmitEditing` is called when "Submit" button
// (the blue key on onscreen keyboard) did pressed // (the blue key on onscreen keyboard) did pressed
// (no connection to any specific "submitting" process). // (no connection to any specific "submitting" process).
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit #if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
reactTag:self.reactTag if (_blurOnSubmit) {
text:self.backedTextInputView.attributedText.string #endif // ]TODO(macOS Candidate ISS#2710739)
key:nil [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
eventCount:_nativeEventCount]; reactTag:self.reactTag
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
key:nil
eventCount:_nativeEventCount];
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
}
#endif // ]TODO(macOS Candidate ISS#2710739)
return _blurOnSubmit; return _blurOnSubmit;
} }
@ -442,7 +448,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
} }
} }
NSString *previousText = backedTextInputView.attributedText.string ?: @""; NSString *previousText = [backedTextInputView.attributedText.string copy] ?: @""; // TODO(OSS Candidate ISS#2710739)
if (range.location + range.length > backedTextInputView.attributedText.string.length) { if (range.location + range.length > backedTextInputView.attributedText.string.length) {
_predictedText = backedTextInputView.attributedText.string; _predictedText = backedTextInputView.attributedText.string;
@ -489,7 +495,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
if (_onChange) { if (_onChange) {
_onChange(@{ _onChange(@{
@"text": self.attributedText.string, @"text": [self.attributedText.string copy], // [TODO(macOS Candidate ISS#2710739)
@"target": self.reactTag, @"target": self.reactTag,
@"eventCount": @(_nativeEventCount), @"eventCount": @(_nativeEventCount),
}); });

Просмотреть файл

@ -37,9 +37,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (assign, getter=isEditable) BOOL editable; @property (assign, getter=isEditable) BOOL editable;
#endif #endif
#if TARGET_OS_OSX #if TARGET_OS_OSX
@property (nonatomic, assign) NSTextAlignment textAlignment;
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
@property (nonatomic, copy, nullable) NSString *text; @property (nonatomic, copy, nullable) NSString *text;
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
@property (nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
@property (nonatomic, assign) NSTextAlignment textAlignment;
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled; @property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
@property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled; @property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled;
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor; @property (nonatomic, strong, nullable) RCTUIColor *selectionColor;

Просмотреть файл

@ -83,15 +83,9 @@
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
@dynamic delegate; @dynamic delegate;
static UIFont *defaultPlaceholderFont()
{
return [UIFont systemFontOfSize:17];
}
static RCTUIColor *defaultPlaceholderTextColor() static RCTUIColor *defaultPlaceholderTextColor()
{ {
// Default placeholder color from UITextField. return [NSColor placeholderTextColor];
return [RCTUIColor colorWithRed:0 green:0 blue:0.0980392 alpha:0.22];
} }
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
@ -106,8 +100,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
object:self]; object:self];
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
self.bordered = NO; [self setBordered:NO];
self.accessibilityRole = NSAccessibilityTextFieldRole; [self setAllowsEditingTextAttributes:YES];
[self setAccessibilityRole:NSAccessibilityTextFieldRole];
[self setBackgroundColor:[NSColor clearColor]];
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
_textInputDelegateAdapter = [[RCTBackedTextFieldDelegateAdapter alloc] initWithTextField:self]; _textInputDelegateAdapter = [[RCTBackedTextFieldDelegateAdapter alloc] initWithTextField:self];
@ -119,6 +115,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
- (void)_textDidChange - (void)_textDidChange
{ {
_textWasPasted = NO; _textWasPasted = NO;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
[self setAttributedText:[[NSAttributedString alloc] initWithString:[self text]
attributes:[self defaultTextAttributes]]];
#endif // ]TODO(macOS ISS#2323203)
} }
#pragma mark - Accessibility #pragma mark - Accessibility
@ -243,6 +243,11 @@ static RCTUIColor *defaultPlaceholderTextColor()
[super setDefaultTextAttributes:defaultTextAttributes]; [super setDefaultTextAttributes:defaultTextAttributes];
#endif // TODO(macOS ISS#2323203) #endif // TODO(macOS ISS#2323203)
[self _updatePlaceholder]; [self _updatePlaceholder];
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
[self setAttributedText:[[NSAttributedString alloc] initWithString:[self text]
attributes:[self defaultTextAttributes]]];
#endif // ]TODO(macOS ISS#2323203)
} }
- (NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes - (NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes

Просмотреть файл

@ -173,6 +173,13 @@ post_install do |installer|
puts ' adding arm64e to ' + config.name puts ' adding arm64e to ' + config.name
end end
end end
# TODO(macOS ISS#2323203): the internal Microsoft build pipeline needs macOS arm64 slices
if target.platform_name == :osx
target.build_configurations.each do |config|
(config.build_settings['ARCHS'] ||= ['$(ARCHS_STANDARD)']) << 'arm64'
puts ' adding arm64 to ' + config.name
end
end
# ]TODO(macOS ISS#2323203) # ]TODO(macOS ISS#2323203)
end end
end end

Просмотреть файл

@ -395,7 +395,7 @@ DEPENDENCIES:
- Yoga (from `../ReactCommon/yoga`) - Yoga (from `../ReactCommon/yoga`)
SPEC REPOS: SPEC REPOS:
https://cdn.cocoapods.org/: trunk:
- CocoaAsyncSocket - CocoaAsyncSocket
- CocoaLibEvent - CocoaLibEvent
- Flipper - Flipper
@ -501,7 +501,7 @@ SPEC CHECKSUMS:
RCTTypeSafety: 4e66a550e8f4d69f045dc4180cb8cfea0b982ed6 RCTTypeSafety: 4e66a550e8f4d69f045dc4180cb8cfea0b982ed6
React: bacecd5320c8bb453aa396179b93061ebd9d34bf React: bacecd5320c8bb453aa396179b93061ebd9d34bf
React-ART: 2f0eb928d7bc51e6262da595955b0e8fcf6c0a9e React-ART: 2f0eb928d7bc51e6262da595955b0e8fcf6c0a9e
React-Core: c80d3cb695659d2b582b7068a2f451c90ac0e744 React-Core: 5d95f89aa9cc03ef38e0bac9225ab0084a89f5f8
React-CoreModules: 0d5bcd5a3cfd73e5ed5f9d5e7f8f2a733bf62be3 React-CoreModules: 0d5bcd5a3cfd73e5ed5f9d5e7f8f2a733bf62be3
React-cxxreact: b7826b0513bdb89e2ddb6b185a9f822069e7c540 React-cxxreact: b7826b0513bdb89e2ddb6b185a9f822069e7c540
React-jsi: e6b9022a422abf5add4598413f9d8bddc5c98fec React-jsi: e6b9022a422abf5add4598413f9d8bddc5c98fec
@ -522,6 +522,6 @@ SPEC CHECKSUMS:
Yoga: 3ed3c35bb7c41fa8f5056b767bc048539f6526ad Yoga: 3ed3c35bb7c41fa8f5056b767bc048539f6526ad
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 3cfdde26e08d043498daa8442c611eb479f77fb0 PODFILE CHECKSUM: dba3e89372dafdb3103dc904bc23601aaf239f68
COCOAPODS: 1.9.3 COCOAPODS: 1.9.3

Просмотреть файл

@ -40,9 +40,7 @@
RCT_TEST(ViewExample) RCT_TEST(ViewExample)
RCT_TEST(LayoutExample) RCT_TEST(LayoutExample)
RCT_TEST(ScrollViewExample) RCT_TEST(ScrollViewExample)
#if !TARGET_OS_OSX // Reason: Intermittent failure: crash deallocating NSTextStorage of a TextView: tracked by https://github.com/microsoft/react-native-macos/issues/357
RCT_TEST(TextExample) RCT_TEST(TextExample)
#endif
#if !TARGET_OS_TV #if !TARGET_OS_TV
// No switch available on tvOS // No switch available on tvOS
RCT_TEST(SwitchExample) RCT_TEST(SwitchExample)

Просмотреть файл

@ -134,6 +134,15 @@ const styles = StyleSheet.create({
}, },
descriptionText: { descriptionText: {
fontSize: 14, fontSize: 14,
...Platform.select({
macos: {
color: {semantic: 'secondaryLabelColor'},
},
ios: {
color: {semantic: 'secondaryLabelColor'},
},
default: undefined,
}),
}, },
children: { children: {
margin: 10, margin: 10,

Просмотреть файл

@ -23,10 +23,19 @@ class RNTesterExampleContainer extends React.Component {
const {description, platform} = example; const {description, platform} = example;
let {title} = example; let {title} = example;
if (platform) { if (platform) {
if (Platform.OS !== platform) { // [TODO(macOS ISS#2323203)
return null; if (platform instanceof Array) {
} if (!platform.includes(Platform.OS)) {
title += ' (' + platform + ' only)'; return null;
}
title += ' (' + platform.join() + ' only)';
} else {
// ]TODO(macOS ISS#2323203)
if (Platform.OS !== platform) {
return null;
}
title += ' (' + platform + ' only)';
} // TODO(macOS ISS#2323203)
} }
return ( return (
<RNTesterBlock key={i} title={title} description={description}> <RNTesterBlock key={i} title={title} description={description}>

Просмотреть файл

@ -733,7 +733,101 @@ class ScreenReaderStatusExample extends React.Component<{}> {
); );
} }
} }
// [TODO(OSS Candidate ISS#2710739)
class DisplayOptionsStatusExample extends React.Component<{}> {
state = {};
componentDidMount() {
AccessibilityInfo.addEventListener(
'invertColorsChanged',
this._handleInvertColorsToggled,
);
AccessibilityInfo.isInvertColorsEnabled().done(isEnabled => {
this.setState({
invertColorsEnabled: isEnabled,
});
});
AccessibilityInfo.addEventListener(
'reduceMotionChanged',
this._handleReduceMotionToggled,
);
AccessibilityInfo.isReduceMotionEnabled().done(isEnabled => {
this.setState({
reduceMotionEnabled: isEnabled,
});
});
AccessibilityInfo.addEventListener(
'reduceTransparencyChanged',
this._handleReduceTransparencyToggled,
);
AccessibilityInfo.isReduceTransparencyEnabled().done(isEnabled => {
this.setState({
reduceTransparencyEnabled: isEnabled,
});
});
}
componentWillUnmount() {
AccessibilityInfo.removeEventListener(
'invertColorsChanged',
this._handleInvertColorsToggled,
);
AccessibilityInfo.removeEventListener(
'reduceMotionChanged',
this._handleReduceMotionToggled,
);
AccessibilityInfo.removeEventListener(
'reduceTransparencyChanged',
this._handleReduceTransparencyToggled,
);
}
_handleInvertColorsToggled = isEnabled => {
this.setState({
invertColorsEnabled: isEnabled,
});
};
_handleReduceMotionToggled = isEnabled => {
this.setState({
reduceMotionEnabled: isEnabled,
});
};
_handleReduceTransparencyToggled = isEnabled => {
this.setState({
reduceTransparencyEnabled: isEnabled,
});
};
render() {
return (
<View>
<View>
<Text>
Invert colors is{' '}
{this.state.invertColorsEnabled ? 'enabled' : 'disabled'}.
</Text>
</View>
<View>
<Text>
Reduce motion is{' '}
{this.state.reduceMotionEnabled ? 'enabled' : 'disabled'}.
</Text>
</View>
<View>
<Text>
Reduce transparency is{' '}
{this.state.reduceTransparencyEnabled ? 'enabled' : 'disabled'}.
</Text>
</View>
</View>
);
}
}
// ]TODO(OSS Candidate ISS#2710739)
class AnnounceForAccessibility extends React.Component<{}> { class AnnounceForAccessibility extends React.Component<{}> {
_handleOnPress = () => _handleOnPress = () =>
AccessibilityInfo.announceForAccessibility('Announcement Test'); AccessibilityInfo.announceForAccessibility('Announcement Test');
@ -750,6 +844,26 @@ class AnnounceForAccessibility extends React.Component<{}> {
} }
} }
class SetAccessibilityFocus extends React.Component<{}> {
_handleOnPress = () => {
if (findNodeHandle(this.focusRef.current)) {
const reactTag = findNodeHandle(this.focusRef.current);
AccessibilityInfo.setAccessibilityFocus(reactTag);
}
};
render() {
this.focusRef = React.createRef();
return (
<View>
<Button onPress={this._handleOnPress} title="Set Accessibility Focus" />
<Text ref={this.focusRef} accessible={true}>
Move focus here on button press.
</Text>
</View>
);
}
}
exports.title = 'Accessibility'; exports.title = 'Accessibility';
exports.description = 'Examples of using Accessibility APIs.'; exports.description = 'Examples of using Accessibility APIs.';
exports.examples = [ exports.examples = [
@ -783,10 +897,24 @@ exports.examples = [
return <ScreenReaderStatusExample />; return <ScreenReaderStatusExample />;
}, },
}, },
// [TODO(OSS Candidate ISS#2710739)
{
title: 'Check if the display options are enabled',
render(): React.Element<typeof DisplayOptionsStatusExample> {
return <DisplayOptionsStatusExample />;
},
},
// ]TODO(OSS Candidate ISS#2710739)
{ {
title: 'Check if the screen reader announces', title: 'Check if the screen reader announces',
render(): React.Element<typeof AnnounceForAccessibility> { render(): React.Element<typeof AnnounceForAccessibility> {
return <AnnounceForAccessibility />; return <AnnounceForAccessibility />;
}, },
}, },
{
title: 'Check if the screen reader focus sets ',
render(): React.Element<typeof SetAccessibilityFocus> {
return <SetAccessibilityFocus />;
},
},
]; ];

Просмотреть файл

@ -13,7 +13,7 @@
var React = require('react'); var React = require('react');
var ReactNative = require('react-native'); var ReactNative = require('react-native');
import {Platform} from 'react-native'; import {Platform} from 'react-native';
var {StyleSheet, Text, View, TextInput} = ReactNative; var {Button, StyleSheet, Text, View, TextInput} = ReactNative;
type State = { type State = {
eventStream: string, eventStream: string,
@ -110,33 +110,103 @@ class FocusEventExample extends React.Component<{}, State> {
{// Only test View on MacOS, since canBecomeFirstResponder is false on all iOS, therefore we can't focus {// Only test View on MacOS, since canBecomeFirstResponder is false on all iOS, therefore we can't focus
Platform.OS === 'macos' ? ( Platform.OS === 'macos' ? (
<View <View>
onFocus={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nNested View Parent Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nNested View Parent Blur',
}));
}}>
<View <View
acceptsKeyboardFocus={true}
enableFocusRing={true}
onFocus={() => { onFocus={() => {
this.setState(prevState => ({ this.setState(prevState => ({
eventStream: prevState.eventStream + '\nNested View Focus', eventStream:
prevState.eventStream + '\nDescendent Button Focus',
})); }));
}} }}
onBlur={() => { onBlur={() => {
this.setState(prevState => ({ this.setState(prevState => ({
eventStream: prevState.eventStream + '\nNested View Blur', eventStream:
prevState.eventStream + '\nDescendent Button Blur',
})); }));
}}> }}>
<Text>Nested Focusable View</Text> <View>
<Button
title="Button whose ancestor has onFocus/onBlur"
onPress={() => {}}
/>
</View>
</View>
<View
onFocus={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nDescendent Button Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nDescendent Button Blur',
}));
}}>
<View>
<Button
title="Button with onFocus/onBlur and ancestor has onFocus/onBlur"
onPress={() => {}}
onFocus={() => {
this.setState(prevState => ({
eventStream: prevState.eventStream + '\nButton Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream: prevState.eventStream + '\nButton Blur',
}));
}}
/>
</View>
</View>
<View
onFocus={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nDescendent Text Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nDescendent Text Blur',
}));
}}>
<View>
<Text selectable={true}>Selectable text</Text>
</View>
</View>
<View
onFocus={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nNested View Parent Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nNested View Parent Blur',
}));
}}>
<View
acceptsKeyboardFocus={true}
enableFocusRing={true}
onFocus={() => {
this.setState(prevState => ({
eventStream:
prevState.eventStream + '\nNested View Focus',
}));
}}
onBlur={() => {
this.setState(prevState => ({
eventStream: prevState.eventStream + '\nNested View Blur',
}));
}}>
<Text>Nested Focusable View</Text>
</View>
</View> </View>
</View> </View>
) : null} ) : null}

Просмотреть файл

@ -15,6 +15,7 @@ const React = require('react');
const { const {
ActivityIndicator, ActivityIndicator,
Image, Image,
Platform, // TODO(OSS Candidate ISS#2710739)
StyleSheet, StyleSheet,
Text, Text,
View, View,
@ -26,7 +27,7 @@ const base64Icon =
const ImageCapInsetsExample = require('./ImageCapInsetsExample'); const ImageCapInsetsExample = require('./ImageCapInsetsExample');
const IMAGE_PREFETCH_URL = const IMAGE_PREFETCH_URL =
'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now(); 'https://www.facebook.com/favicon.ico?r=1&t=' + Date.now();
const prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL); const prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
type ImageSource = $ReadOnly<{| type ImageSource = $ReadOnly<{|
@ -312,18 +313,17 @@ class MultipleSourcesExample extends React.Component<
style={{flex: 1}} style={{flex: 1}}
source={[ source={[
{ {
uri: 'https://facebook.github.io/react-native/img/favicon.png', uri: 'https://www.facebook.com/favicon.ico',
width: 38, width: 38,
height: 38, height: 38,
}, },
{ {
uri: 'https://facebook.github.io/react-native/img/favicon.png', uri: 'https://www.facebook.com/favicon.ico',
width: 76, width: 76,
height: 76, height: 76,
}, },
{ {
uri: uri: 'https://www.facebook.com/ads/pics/successstories.png',
'https://facebook.github.io/react-native/img/opengraph.png',
width: 400, width: 400,
height: 400, height: 400,
}, },
@ -336,10 +336,10 @@ class MultipleSourcesExample extends React.Component<
} }
const fullImage = { const fullImage = {
uri: 'https://facebook.github.io/react-native/img/opengraph.png', uri: 'https://www.facebook.com/ads/pics/successstories.png',
}; };
const smallImage = { const smallImage = {
uri: 'https://facebook.github.io/react-native/img/favicon.png', uri: 'https://www.facebook.com/favicon.ico',
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -448,9 +448,7 @@ exports.examples = [
return ( return (
<NetworkImageCallbackExample <NetworkImageCallbackExample
source={{ source={{
uri: uri: 'https://www.facebook.com/favicon.ico?r=1&t=' + Date.now(),
'http://origami.design/public/images/bird-logo.png?r=1&t=' +
Date.now(),
}} }}
prefetchedSource={{uri: IMAGE_PREFETCH_URL}} prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
/> />
@ -463,7 +461,7 @@ exports.examples = [
return ( return (
<NetworkImageExample <NetworkImageExample
source={{ source={{
uri: 'https://TYPO_ERROR_facebook.github.io/react/logo-og.png', uri: 'https://www.facebook.com/favicon_TYPO.ico',
}} }}
/> />
); );
@ -476,7 +474,7 @@ exports.examples = [
return ( return (
<NetworkImageExample <NetworkImageExample
source={{ source={{
uri: 'http://origami.design/public/images/bird-logo.png?r=1', uri: 'https://www.facebook.com/favicon.ico?r=1',
}} }}
/> />
); );
@ -491,7 +489,7 @@ exports.examples = [
<Image <Image
defaultSource={require('../../assets/bunny.png')} defaultSource={require('../../assets/bunny.png')}
source={{ source={{
uri: 'https://facebook.github.io/origami/public/images/birds.jpg', uri: 'https://origami.design/public/images/bird-logo.png',
}} }}
style={styles.base} style={styles.base}
/> />
@ -888,7 +886,8 @@ exports.examples = [
<Image <Image
source={{ source={{
uri: 'ImageInBundle', uri: 'ImageInBundle',
bundle: 'RNTesterBundle', bundle:
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
width: 100, width: 100,
height: 100, height: 100,
}} }}
@ -897,7 +896,8 @@ exports.examples = [
<Image <Image
source={{ source={{
uri: 'ImageInAssetCatalog', uri: 'ImageInAssetCatalog',
bundle: 'RNTesterBundle', bundle:
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
width: 100, width: 100,
height: 100, height: 100,
}} }}
@ -906,7 +906,7 @@ exports.examples = [
</View> </View>
); );
}, },
platform: 'ios', platform: ['ios', 'macos'], // TODO(OSS Candidate ISS#2710739)
}, },
{ {
title: 'Blur Radius', title: 'Blur Radius',

Просмотреть файл

@ -430,6 +430,113 @@ class TouchableDisabled extends React.Component<{...}> {
} }
} }
// [TODO(macOS ISS#2323203)
class TouchableHover extends React.Component<{}, $FlowFixMeState> {
state = {
hoverOver: false,
};
render() {
return (
<View>
<TouchableOpacity
onMouseEnter={this._handlePress}
onMouseLeave={this._handlePress}
style={[styles.row, styles.block]}>
<Text style={this.state.hoverOver ? {color: 'red'} : {color: 'blue'}}>
Touchable Opacity with mouse enter/exit events
</Text>
</TouchableOpacity>
<TouchableHighlight
onMouseEnter={() => console.log('Mouse Enter')}
onMouseLeave={() => console.log('Mouse Exit')}
activeOpacity={1}
disabled={true}
underlayColor="rgb(210, 230, 255)"
style={[styles.row, styles.block]}
onPress={() => console.log('custom THW text - highlight')}>
<Text style={styles.disabledButton}>
Touchable Highlight with mouse event logging
</Text>
</TouchableHighlight>
</View>
);
}
_handlePress = () => {
this.setState({hoverOver: !this.state.hoverOver});
};
}
class TouchableMouseEvents extends React.Component<{}, $FlowFixMeState> {
state = {
eventLog: [],
};
render() {
return (
<View testID="touchable_feedback_mouse_events">
<View style={[styles.row, {justifyContent: 'center'}]}>
<TouchableOpacity
style={styles.wrapper}
testID="touchable_feedback_mouse_events_button"
accessibilityLabel="touchable feedback mouse events"
onPressIn={e => this._appendEvent('MouseIn', e.nativeEvent)}
onPressOut={e => this._appendEvent('MouseOut', e.nativeEvent)}
draggedTypes={'fileUrl'}
onDragEnter={e =>
this._appendEvent('MouseDragEnter', e.nativeEvent)
}
onDragLeave={e =>
this._appendEvent('MouseDragLeave', e.nativeEvent)
}
onDrop={e => this._appendEvent('MouseDrop', e.nativeEvent)}>
<Text style={styles.button}>Click Me</Text>
</TouchableOpacity>
</View>
<View
testID="touchable_feedback_mouse_events_console"
style={styles.eventLogBox}>
{this.state.eventLog.map((e, ii) => (
<Text key={ii}>{e}</Text>
))}
</View>
</View>
);
}
_appendEvent = (eventName, nativeEvent) => {
var limit = 6;
var eventLog = this.state.eventLog.slice(0, limit - 1);
var eventType = '';
if (nativeEvent.button === 0) {
eventType = 'left';
} else if (nativeEvent.button === 2) {
eventType = 'right';
}
var modifier = '';
if (nativeEvent.shiftKey) {
modifier += 'shift, ';
}
if (nativeEvent.ctrlKey) {
modifier += 'ctrl, ';
}
if (nativeEvent.altKey) {
modifier += 'alt, ';
}
if (nativeEvent.metaKey) {
modifier += 'meta, ';
}
if (modifier.length > 0) {
modifier = ' - ' + modifier.slice(0, -2) + ' pressed';
}
eventLog.unshift(eventType + eventName + modifier);
this.setState({eventLog});
};
}
// ]TODO(macOS ISS#2323203)
const heartImage = { const heartImage = {
uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small', uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small',
}; };
@ -611,4 +718,24 @@ exports.examples = [
return <TouchableDisabled />; return <TouchableDisabled />;
}, },
}, },
{
// [TODO(macOS ISS#2323203)
title: 'Touchable Hover',
description:
('<Touchable*> components reacts to mouse events ' +
'onMouseEnter and onMouseLeave': string),
render: function(): React.Element<any> {
return <TouchableHover />;
},
},
{
title: 'Touchable feedback mouse events',
description:
('<Touchable*> components reacts to mouse events ' +
'onPressIn, onPressOut, onDragEnter, onDragLeave, and onDrop': string),
render: function(): React.Element<any> {
return <TouchableMouseEvents />;
},
platform: 'macos',
}, // ]TODO(macOS ISS#2323203)
]; ];

Просмотреть файл

@ -64,7 +64,9 @@ Pod::Spec.new do |s|
# [TODO(macOS ISS#2323203) # [TODO(macOS ISS#2323203)
"**/macOS/*" "**/macOS/*"
ss.osx.exclude_files = "React/Modules/RCTRedBoxExtraDataViewController.{h,m}", ss.osx.exclude_files = "React/Modules/RCTRedBoxExtraDataViewController.{h,m}",
"React/Profiler/RCTProfileTrampoline-{arm,arm64,i386}.S", "React/Modules/RCTAccessibilityManager.m",
"React/Profiler/{RCTFPSGraph,RCTPerfMonitor}.*",
"React/Profiler/RCTProfileTrampoline-{arm,i386}.S",
"React/Base/RCTKeyCommands.*", "React/Base/RCTKeyCommands.*",
"React/Base/RCTTV*.*", "React/Base/RCTTV*.*",
"React/Views/{RCTModal*,RCTMasked*,RCTTV*,RCTWrapperViewController}.*", "React/Views/{RCTModal*,RCTMasked*,RCTTV*,RCTWrapperViewController}.*",

Просмотреть файл

@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import <React/RCTComponentEvent.h>
/**
* Represents a focus change event meaning that a view that can become first responder has become or resigned being first responder.
*/
@interface RCTFocusChangeEvent : RCTComponentEvent
+ (instancetype)focusEventWithReactTag:(NSNumber *)reactTag;
+ (instancetype)blurEventWithReactTag:(NSNumber *)reactTag;
@end

Просмотреть файл

@ -0,0 +1,30 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTFocusChangeEvent.h"
#import "RCTAssert.h"
@implementation RCTFocusChangeEvent
+ (instancetype)focusEventWithReactTag:(NSNumber *)reactTag
{
RCTFocusChangeEvent *event = [[self alloc] initWithName:@"focus"
viewTag:reactTag
body:@{}];
return event;
}
+ (instancetype)blurEventWithReactTag:(NSNumber *)reactTag
{
RCTFocusChangeEvent *event = [[self alloc] initWithName:@"blur"
viewTag:reactTag
body:@{}];
return event;
}
@end

Просмотреть файл

@ -38,6 +38,10 @@
#import "RCTDevMenu.h" #import "RCTDevMenu.h"
#endif // ]TODO(OSS Candidate ISS#2710739) #endif // ]TODO(OSS Candidate ISS#2710739)
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
#define RCT_LAYOUT_THROTTLE 0.25
#endif // ]TODO(macOS ISS#2323203)
NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification"; NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification";
@interface RCTUIManager (RCTRootView) @interface RCTUIManager (RCTRootView)
@ -53,6 +57,11 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
RCTRootContentView *_contentView; RCTRootContentView *_contentView;
BOOL _passThroughTouches; BOOL _passThroughTouches;
CGSize _intrinsicContentSize; CGSize _intrinsicContentSize;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
NSDate *_lastLayout;
BOOL _throttleLayout;
#endif // ]TODO(macOS ISS#2323203)
} }
- (instancetype)initWithBridge:(RCTBridge *)bridge - (instancetype)initWithBridge:(RCTBridge *)bridge
@ -80,6 +89,10 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
_loadingViewFadeDuration = 0.25; _loadingViewFadeDuration = 0.25;
_sizeFlexibility = RCTRootViewSizeFlexibilityNone; _sizeFlexibility = RCTRootViewSizeFlexibilityNone;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
_lastLayout = [NSDate new];
#endif // ]TODO(macOS ISS#2323203)
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bridgeDidReload) selector:@selector(bridgeDidReload)
name:RCTJavaScriptWillStartLoadingNotification name:RCTJavaScriptWillStartLoadingNotification
@ -174,6 +187,35 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
return fitSize; return fitSize;
} }
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
// TODO: https://github.com/microsoft/react-native-macos/issues/459
// This is a workaround for window resizing events overloading the shadow queue:
// - https://github.com/microsoft/react-native-macos/issues/322
// - https://github.com/microsoft/react-native-macos/issues/422
// We should revisit this issue when we switch over to Fabric.
- (void)layout
{
if (self.window != nil && !_throttleLayout) {
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:_lastLayout];
if (interval >= RCT_LAYOUT_THROTTLE) {
_lastLayout = [NSDate new];
[self layoutSubviews];
} else {
_throttleLayout = YES;
__weak typeof(self) weakSelf = self;
int64_t delta = (RCT_LAYOUT_THROTTLE - interval) * NSEC_PER_SEC;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta), dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf != nil) {
strongSelf->_throttleLayout = NO;
[strongSelf setNeedsLayout];
}
});
}
}
}
#endif // ]TODO(macOS ISS#2323203)
- (void)layoutSubviews - (void)layoutSubviews
{ {
[super layoutSubviews]; [super layoutSubviews];

Просмотреть файл

@ -61,9 +61,9 @@ static NSString *const RCTDarkAquaColor = @"darkAquaColor";
NSColor *effectiveColor = _aquaColor; NSColor *effectiveColor = _aquaColor;
if (@available(macOS 10.14, *)) { if (@available(macOS 10.14, *)) {
NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance]; NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance];
NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]]; NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) { if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) {
effectiveColor = _darkAquaColor; effectiveColor = _darkAquaColor;
} }
@ -181,4 +181,37 @@ RCT_FORWARD_PROPERTY(localizedColorNameComponent, NSString *)
return [[self effectiveColor] colorWithSystemEffect:systemEffect]; return [[self effectiveColor] colorWithSystemEffect:systemEffect];
} }
- (NSUInteger)hash
{
const NSUInteger prime = 31;
NSUInteger result = 1;
result = prime * result + [_aquaColor hash];
result = prime * result + [_darkAquaColor hash];
return result;
}
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
}
return other != nil && [other isKindOfClass:[self class]] && [self isEqualToDynamicColor:other];
}
- (BOOL)isEqualToDynamicColor:(RCTDynamicColor *)other {
if (self == other) {
return YES;
}
if ([_aquaColor isNotEqualTo:other->_aquaColor]) {
return NO;
}
if ([_darkAquaColor isNotEqualTo:other->_darkAquaColor]) {
return NO;
}
return YES;
}
@end @end

Просмотреть файл

@ -0,0 +1,147 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTAccessibilityManager.h"
#import "RCTBridge.h"
#import "RCTConvert.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTUIManager.h"
NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification =
@"RCTAccessibilityManagerDidUpdateMultiplierNotification";
@implementation RCTAccessibilityManager
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
static void *AccessibilityVoiceOverChangeContext = &AccessibilityVoiceOverChangeContext;
+ (BOOL)requiresMainQueueSetup
{
return NO;
}
- (instancetype)init
{
if (self = [super init]) {
[[NSWorkspace sharedWorkspace] addObserver:self
forKeyPath:@"voiceOverEnabled"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:AccessibilityVoiceOverChangeContext];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(accessibilityDisplayOptionsChange:)
name:NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
object:nil];
_isInvertColorsEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldInvertColors];
_isReduceMotionEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
_isReduceTransparencyEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
_isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
}
return self;
}
- (void)dealloc
{
[[NSWorkspace sharedWorkspace] removeObserver:self
forKeyPath:@"voiceOverEnabled"
context:AccessibilityVoiceOverChangeContext];
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
}
RCT_EXPORT_METHOD(announceForAccessibility:(NSString *)announcement)
{
NSAccessibilityPostNotificationWithUserInfo(
NSApp,
NSAccessibilityAnnouncementRequestedNotification,
@{NSAccessibilityAnnouncementKey : announcement,
NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh)
}
);
}
RCT_EXPORT_METHOD(getCurrentInvertColorsState:(RCTResponseSenderBlock)callback
error:(__unused RCTResponseSenderBlock)error)
{
callback(@[@(_isInvertColorsEnabled)]);
}
RCT_EXPORT_METHOD(getCurrentReduceMotionState:(RCTResponseSenderBlock)callback
error:(__unused RCTResponseSenderBlock)error)
{
callback(@[@(_isReduceMotionEnabled)]);
}
RCT_EXPORT_METHOD(getCurrentReduceTransparencyState:(RCTResponseSenderBlock)callback
error:(__unused RCTResponseSenderBlock)error)
{
callback(@[@(_isReduceTransparencyEnabled)]);
}
RCT_EXPORT_METHOD(getCurrentVoiceOverState:(RCTResponseSenderBlock)callback
error:(__unused RCTResponseSenderBlock)error)
{
BOOL isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
callback(@[ @(isVoiceOverEnabled) ]);
}
RCT_EXPORT_METHOD(setAccessibilityFocus:(nonnull NSNumber *)reactTag)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSView *view = [self.bridge.uiManager viewForReactTag:reactTag];
[[view window] makeFirstResponder:view];
});
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == AccessibilityVoiceOverChangeContext) {
BOOL newIsVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
_isVoiceOverEnabled = newIsVoiceOverEnabled;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"screenReaderChanged"
body:@(_isVoiceOverEnabled)];
#pragma clang diagnostic pop
}
} else {
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
- (void)accessibilityDisplayOptionsChange:(NSNotification *)notification
{
BOOL newInvertColorsEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldInvertColors];
BOOL newReduceMotionEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
BOOL newReduceTransparencyEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
if (_isInvertColorsEnabled != newInvertColorsEnabled) {
_isInvertColorsEnabled = newInvertColorsEnabled;
[_bridge.eventDispatcher sendDeviceEventWithName:@"invertColorsChanged"
body:@(_isInvertColorsEnabled)];
}
if (_isReduceMotionEnabled != newReduceMotionEnabled) {
_isReduceMotionEnabled = newReduceMotionEnabled;
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceMotionChanged"
body:@(_isReduceMotionEnabled)];
}
if (_isReduceTransparencyEnabled != newReduceTransparencyEnabled) {
_isReduceTransparencyEnabled = newReduceTransparencyEnabled;
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceTransparencyChanged"
body:@(_isReduceTransparencyEnabled)];
}
}
@end

Просмотреть файл

@ -30,6 +30,9 @@
- (void)startAnimating - (void)startAnimating
{ {
// `wantsLayer` gets reset after the animation is stopped. We have to
// reset it in order for CALayer filters to take effect.
[self setWantsLayer:YES];
[self startAnimation:self]; [self startAnimation:self];
} }
@ -66,7 +69,7 @@
} }
} }
- (void)setColor: (RCTUIColor*)color - (void)setColor:(RCTUIColor*)color
{ {
if (_color != color) { if (_color != color) {
_color = color; _color = color;
@ -77,19 +80,23 @@
- (void)updateLayer - (void)updateLayer
{ {
[super updateLayer]; [super updateLayer];
if (_color) { if (_color != nil) {
CGFloat r, g, b, a; CGFloat r, g, b, a;
[[_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a]; [[_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a];
CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"]; CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"];
[colorPoly setDefaults]; [colorPoly setDefaults];
CIVector *redVector = [CIVector vectorWithX:r Y:0 Z:0 W:0]; CIVector *redVector = [CIVector vectorWithX:r Y:0 Z:0 W:0];
CIVector *greenVector = [CIVector vectorWithX:g Y:0 Z:0 W:0]; CIVector *greenVector = [CIVector vectorWithX:g Y:0 Z:0 W:0];
CIVector *blueVector = [CIVector vectorWithX:b Y:0 Z:0 W:0]; CIVector *blueVector = [CIVector vectorWithX:b Y:0 Z:0 W:0];
[colorPoly setValue:redVector forKey:@"inputRedCoefficients"]; [colorPoly setValue:redVector forKey:@"inputRedCoefficients"];
[colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"]; [colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"];
[colorPoly setValue:blueVector forKey:@"inputBlueCoefficients"]; [colorPoly setValue:blueVector forKey:@"inputBlueCoefficients"];
self.contentFilters = @[colorPoly];
[[self layer] setFilters:@[colorPoly]];
} else {
[[self layer] setFilters:nil];
} }
} }

Просмотреть файл

@ -18,7 +18,9 @@
@property (nonatomic, assign) NSInteger selectedIndex; @property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, strong) RCTUIColor *color; // TODO(OSS Candidate ISS#2710739) @property (nonatomic, strong) RCTUIColor *color; // TODO(OSS Candidate ISS#2710739)
#if !TARGET_OS_OSX // [TODO(OSS Candidate ISS#2710739) // NSControl defines font prop for macOS, but iOS superviews don't
@property (nonatomic, strong) UIFont *font; @property (nonatomic, strong) UIFont *font;
#endif // ]TODO(OSS Candidate ISS#2710739)
@property (nonatomic, assign) NSTextAlignment textAlign; @property (nonatomic, assign) NSTextAlignment textAlign;
@property (nonatomic, copy) RCTBubblingEventBlock onChange; @property (nonatomic, copy) RCTBubblingEventBlock onChange;

Просмотреть файл

@ -23,16 +23,17 @@
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if ((self = [super initWithFrame:frame])) { if ((self = [super initWithFrame:frame])) {
_color = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739)
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_color = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739)
_font = [UIFont systemFontOfSize:21]; // TODO: selected title default should be 23.5 _font = [UIFont systemFontOfSize:21]; // TODO: selected title default should be 23.5
#else // [TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
_font = [UIFont systemFontOfSize:11]; _color = [NSColor labelColor];
[self setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
_selectedIndex = NSNotFound; _selectedIndex = NSNotFound;
_textAlign = NSTextAlignmentCenter; _textAlign = NSTextAlignmentCenter;
self.delegate = self; self.delegate = self;
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
self.controlSize = NSControlSizeRegular; self.controlSize = NSControlSizeRegular;
self.editable = NO; self.editable = NO;
@ -63,7 +64,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
NSMutableDictionary *mutableItem = item.mutableCopy; NSMutableDictionary *mutableItem = item.mutableCopy;
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[RCTConvert NSString:item[@"label"]] NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[RCTConvert NSString:item[@"label"]]
attributes:@{NSForegroundColorAttributeName : [RCTConvert UIColor:item[@"textColor"]] ?: _color, attributes:@{NSForegroundColorAttributeName : [RCTConvert UIColor:item[@"textColor"]] ?: _color,
NSFontAttributeName: _font, NSFontAttributeName: [self font] /* Use the font prop instead of the ivar so it's compatible on iOS and macOS TODO(OSS Candidate ISS#2710739) */,
NSParagraphStyleAttributeName: paragraphStyle}]; NSParagraphStyleAttributeName: paragraphStyle}];
NSSize size = attrString.size; NSSize size = attrString.size;
if (size.height > maxHeight) { if (size.height > maxHeight) {

Просмотреть файл

@ -9,6 +9,7 @@
#import <React/RCTBorderStyle.h> #import <React/RCTBorderStyle.h>
#import <React/RCTComponent.h> #import <React/RCTComponent.h>
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
#import <React/RCTPointerEvents.h> #import <React/RCTPointerEvents.h>
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
@ -22,6 +23,8 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
@interface RCTView : RCTUIView // TODO(macOS ISS#3536887) @interface RCTView : RCTUIView // TODO(macOS ISS#3536887)
// [TODO(OSS Candidate ISS#2710739) // [TODO(OSS Candidate ISS#2710739)
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
- (BOOL)becomeFirstResponder; - (BOOL)becomeFirstResponder;
- (BOOL)resignFirstResponder; - (BOOL)resignFirstResponder;
// ]TODO(OSS Candidate ISS#2710739) // ]TODO(OSS Candidate ISS#2710739)

Просмотреть файл

@ -9,6 +9,7 @@
#import "RCTAutoInsetsProtocol.h" #import "RCTAutoInsetsProtocol.h"
#import "RCTBorderDrawing.h" #import "RCTBorderDrawing.h"
#import "RCTFocusChangeEvent.h" // TODO(OSS Candidate ISS#2710739)
#import "RCTConvert.h" #import "RCTConvert.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTRootContentView.h" // TODO(macOS ISS#2323203) #import "RCTRootContentView.h" // TODO(macOS ISS#2323203)
@ -108,6 +109,7 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
@implementation RCTView @implementation RCTView
{ {
RCTUIColor *_backgroundColor; // TODO(OSS Candidate ISS#2710739) RCTUIColor *_backgroundColor; // TODO(OSS Candidate ISS#2710739)
RCTEventDispatcher *_eventDispatcher; // TODO(OSS Candidate ISS#2710739)
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
NSTrackingArea *_trackingArea; NSTrackingArea *_trackingArea;
BOOL _hasMouseOver; BOOL _hasMouseOver;
@ -116,6 +118,16 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap; NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap;
} }
// [TODO(OSS Candidate ISS#2710739)
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if ((self = [self initWithFrame:CGRectZero])) {
_eventDispatcher = eventDispatcher;
}
return self;
}
// ]TODO(OSS Candidate ISS#2710739)
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if ((self = [super initWithFrame:frame])) { if ((self = [super initWithFrame:frame])) {
@ -724,21 +736,20 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
} }
// If we've gained focus, notify listeners // If we've gained focus, notify listeners
if (self.onFocus != nil ) { [_eventDispatcher sendEvent:[RCTFocusChangeEvent focusEventWithReactTag:self.reactTag]];
self.onFocus(nil);
}
return YES; return YES;
} }
- (BOOL)resignFirstResponder - (BOOL)resignFirstResponder
{ {
if (![super resignFirstResponder]) { if (![super resignFirstResponder]) {
return NO; return NO;
} }
// If we've gained focus, notify listeners // If we've lost focus, notify listeners
if (self.onBlur != nil ) { [_eventDispatcher sendEvent:[RCTFocusChangeEvent blurEventWithReactTag:self.reactTag]];
self.onBlur(nil);
}
return YES; return YES;
} }
@ -911,6 +922,11 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) {
} }
RCTUpdateShadowPathForView(self); RCTUpdateShadowPathForView(self);
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
// clipsToBounds is stubbed out on macOS because it's not part of NSView
layer.masksToBounds = self.clipsToBounds;
#endif // ]TODO(macOS ISS#2323203)
const RCTCornerRadii cornerRadii = [self cornerRadii]; const RCTCornerRadii cornerRadii = [self cornerRadii];
const UIEdgeInsets borderInsets = [self bordersAsInsets]; const UIEdgeInsets borderInsets = [self bordersAsInsets];

Просмотреть файл

@ -89,7 +89,7 @@ RCT_EXPORT_MODULE()
#if TARGET_OS_TV #if TARGET_OS_TV
return [RCTTVView new]; return [RCTTVView new];
#else #else
return [RCTView new]; return [[RCTView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
#endif #endif
} }

Просмотреть файл

@ -0,0 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTScrollContentLocalData : NSObject
@property (nonatomic, assign) CGFloat horizontalScrollerHeight;
@property (nonatomic, assign) CGFloat verticalScrollerWidth;
- (instancetype)initWithVerticalScroller:(nullable NSScroller *)verticalScroller
horizontalScroller:(nullable NSScroller *)horizontalScroller;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -0,0 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTScrollContentLocalData.h"
@implementation RCTScrollContentLocalData
- (instancetype)initWithVerticalScroller:(NSScroller *)verticalScroller
horizontalScroller:(NSScroller *)horizontalScroller
{
if (self = [super init]) {
_verticalScrollerWidth = NSWidth([verticalScroller frame]);
_horizontalScrollerHeight = NSHeight([horizontalScroller frame]);
}
return self;
}
@end

Просмотреть файл

@ -9,10 +9,28 @@
#import <yoga/Yoga.h> #import <yoga/Yoga.h>
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
#import "RCTScrollContentLocalData.h"
#endif // ]TODO(macOS ISS#2323203)
#import "RCTUtils.h" #import "RCTUtils.h"
@implementation RCTScrollContentShadowView @implementation RCTScrollContentShadowView
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
- (void)setLocalData:(RCTScrollContentLocalData *)localData
{
RCTAssert(
[localData isKindOfClass:[RCTScrollContentLocalData class]],
@"Local data object for `RCTScrollContentView` must be `RCTScrollContentLocalData` instance.");
super.marginEnd = (YGValue){localData.verticalScrollerWidth, YGUnitPoint};
super.marginBottom = (YGValue){localData.horizontalScrollerHeight, YGUnitPoint};
[self didSetProps:@[@"marginEnd", @"marginBottom"]];
}
#endif // ]TODO(macOS ISS#2323203)
- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics - (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
layoutContext:(RCTLayoutContext)layoutContext layoutContext:(RCTLayoutContext)layoutContext
{ {

Просмотреть файл

@ -10,9 +10,20 @@
#import <React/RCTAssert.h> #import <React/RCTAssert.h>
#import <React/UIView+React.h> #import <React/UIView+React.h>
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
#import <React/RCTUIManager.h>
#import "RCTScrollContentLocalData.h"
#endif // ]TODO(macOS ISS#2323203)
#import "RCTScrollView.h" #import "RCTScrollView.h"
@implementation RCTScrollContentView @implementation RCTScrollContentView
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
{
BOOL _hasHorizontalScroller;
BOOL _hasVerticalScroller;
}
#endif // ]TODO(macOS ISS#2323203)
- (void)reactSetFrame:(CGRect)frame - (void)reactSetFrame:(CGRect)frame
{ {
@ -21,25 +32,6 @@
#else // [TODO(macOS ISS#2323203) #else // [TODO(macOS ISS#2323203)
// macOS also has a NSClipView in its hierarchy // macOS also has a NSClipView in its hierarchy
RCTScrollView *scrollView = (RCTScrollView *)self.superview.superview.superview; RCTScrollView *scrollView = (RCTScrollView *)self.superview.superview.superview;
if (scrollView != nil) {
// On macOS scroll indicators may float over the content view like they do in iOS
// or depending on system preferences they may be outside of the content view
// which means the clip view will be smaller than the scroll view itself.
// In such cases the content view layout must shrink accordingly otherwise
// the contents will overflow causing the scroll indicators to appear unnecessarily.
NSScrollView *platformScrollView = scrollView.scrollView;
if (platformScrollView.scrollerStyle == NSScrollerStyleLegacy) {
NSScroller *verticalScroller = platformScrollView.verticalScroller;
if (!verticalScroller.isHidden) {
frame.size.width -= verticalScroller.frame.size.width;
}
NSScroller *horizontalScroller = platformScrollView.horizontalScroller;
if (!horizontalScroller.isHidden) {
frame.size.height -= horizontalScroller.frame.size.height;
}
}
}
#endif // ]TODO(macOS ISS#2323203) #endif // ]TODO(macOS ISS#2323203)
[super reactSetFrame:frame]; [super reactSetFrame:frame];
@ -52,6 +44,32 @@
@"Unexpected view hierarchy of RCTScrollView component."); @"Unexpected view hierarchy of RCTScrollView component.");
[scrollView updateContentOffsetIfNeeded]; [scrollView updateContentOffsetIfNeeded];
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
// On macOS scroll indicators may float over the content view like they do in iOS
// or depending on system preferences they may be outside of the content view
// which means the clip view will be smaller than the scroll view itself.
// In such cases the content view layout must shrink accordingly otherwise
// the contents will overflow causing the scroll indicators to appear unnecessarily.
NSScrollView *platformScrollView = [scrollView scrollView];
if ([platformScrollView scrollerStyle] == NSScrollerStyleLegacy) {
const BOOL nextHasHorizontalScroller = [platformScrollView hasHorizontalScroller];
const BOOL nextHasVerticalScroller = [platformScrollView hasVerticalScroller];
if (_hasHorizontalScroller != nextHasHorizontalScroller ||
_hasVerticalScroller != nextHasVerticalScroller) {
_hasHorizontalScroller = nextHasHorizontalScroller;
_hasVerticalScroller = nextHasVerticalScroller;
RCTScrollContentLocalData *localData =
[[RCTScrollContentLocalData alloc]
initWithVerticalScroller:[platformScrollView verticalScroller]
horizontalScroller:[platformScrollView horizontalScroller]];
[[[scrollView bridge] uiManager] setLocalData:localData forView:self];
}
}
#endif // ]TODO(macOS ISS#2323203)
} }
@end @end

Просмотреть файл

@ -23,6 +23,8 @@
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
@property (nonatomic, readonly) RCTBridge *bridge;
/** /**
* The `RCTScrollView` may have at most one single subview. This will ensure * The `RCTScrollView` may have at most one single subview. This will ensure
* that the scroll view's `contentSize` will be efficiently set to the size of * that the scroll view's `contentSize` will be efficiently set to the size of

Просмотреть файл

@ -57,7 +57,6 @@
self.scrollEnabled = YES; self.scrollEnabled = YES;
self.hasHorizontalScroller = YES; self.hasHorizontalScroller = YES;
self.hasVerticalScroller = YES; self.hasVerticalScroller = YES;
self.autohidesScrollers = YES;
self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)]; self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
#else // ]TODO(macOS ISS#2323203) #else // ]TODO(macOS ISS#2323203)
[self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)]; [self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)];
@ -436,6 +435,11 @@
} }
} }
- (RCTBridge *)bridge
{
return [_eventDispatcher bridge];
}
- (RCTUIView *)contentView // TODO(macOS ISS#3536887) - (RCTUIView *)contentView // TODO(macOS ISS#3536887)
{ {
return _scrollView.documentView; return _scrollView.documentView;
@ -621,6 +625,11 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
[self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView]; [self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView];
_lastClippedToRect = bounds; _lastClippedToRect = bounds;
} }
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
[[self scrollView] setHasHorizontalScroller:[self isHorizontal:_scrollView]];
[[self scrollView] setHasVerticalScroller:[self isVertical:_scrollView]];
#endif // ]TODO(macOS ISS#2323203)
} }
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203) #if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
@ -678,6 +687,13 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
return scrollView.contentSize.width > self.frame.size.width; return scrollView.contentSize.width > self.frame.size.width;
} }
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
- (BOOL)isVertical:(RCTCustomScrollView *)scrollView
{
return scrollView.contentSize.height > self.frame.size.height;
}
#endif // ]TODO(macOS Candidate ISS#2710739)
- (void)scrollToOffset:(CGPoint)offset - (void)scrollToOffset:(CGPoint)offset
{ {
[self scrollToOffset:offset animated:YES]; [self scrollToOffset:offset animated:YES];

Просмотреть файл

@ -294,7 +294,13 @@
} }
- (void)reactBlur { - (void)reactBlur {
#if TARGET_OS_OSX // TODO(macOS ISS#2323203)
if (self == [[self window] firstResponder]) {
[[self window] makeFirstResponder:[[self window] nextResponder]];
}
#else
[self resignFirstResponder]; [self resignFirstResponder];
#endif
} }
#pragma mark - Layout #pragma mark - Layout

Просмотреть файл

@ -1,6 +1,6 @@
--- "D:\\code\\work\\react-native-v0.61.5\\ReactAndroid\\ReactAndroid.nuspec" 1969-12-31 16:00:00.000000000 -0800 --- "D:\\code\\work\\react-native-v0.61.5\\ReactAndroid\\ReactAndroid.nuspec" 1969-12-31 16:00:00.000000000 -0800
+++ "D:\\code\\work\\react-native-fb61merge\\ReactAndroid\\ReactAndroid.nuspec" 2020-03-30 21:05:08.615724600 -0700 +++ "D:\\code\\work\\react-native-fb61merge\\ReactAndroid\\ReactAndroid.nuspec" 2020-03-30 21:05:08.615724600 -0700
@@ -0,0 +1,120 @@ @@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?>
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> +<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
+ <metadata> + <metadata>
@ -45,11 +45,6 @@
+ <file src="build\react-ndk\all\x86\libreactnativejni.so" target="lib\droidx86"/> + <file src="build\react-ndk\all\x86\libreactnativejni.so" target="lib\droidx86"/>
+ <file src="build\react-ndk\all\arm64-v8a\libreactnativejni.so" target="lib\droidarm64"/> + <file src="build\react-ndk\all\arm64-v8a\libreactnativejni.so" target="lib\droidarm64"/>
+ +
+ <file src="build\react-ndk\all\x86_64\libv8executor.so" target="lib\droidx64"/>
+ <file src="build\react-ndk\all\armeabi-v7a\libv8executor.so" target="lib\droidarm"/>
+ <file src="build\react-ndk\all\x86\libv8executor.so" target="lib\droidx86"/>
+ <file src="build\react-ndk\all\arm64-v8a\libv8executor.so" target="lib\droidarm64"/>
+
+ <file src="build\react-ndk\all\x86_64\libyoga.so" target="lib\droidx64"/> + <file src="build\react-ndk\all\x86_64\libyoga.so" target="lib\droidx64"/>
+ <file src="build\react-ndk\all\armeabi-v7a\libyoga.so" target="lib\droidarm"/> + <file src="build\react-ndk\all\armeabi-v7a\libyoga.so" target="lib\droidarm"/>
+ <file src="build\react-ndk\all\x86\libyoga.so" target="lib\droidx86"/> + <file src="build\react-ndk\all\x86\libyoga.so" target="lib\droidx86"/>
@ -91,11 +86,6 @@
+ <file src="build\tmp\buildReactNdkLib\local\x86\libreactnativejni.so" target="lib\droidx86\unstripped"/> + <file src="build\tmp\buildReactNdkLib\local\x86\libreactnativejni.so" target="lib\droidx86\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libreactnativejni.so" target="lib\droidarm64\unstripped"/> + <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libreactnativejni.so" target="lib\droidarm64\unstripped"/>
+ +
+ <file src="build\tmp\buildReactNdkLib\local\x86_64\libv8executor.so" target="lib\droidx64\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libv8executor.so" target="lib\droidarm\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\x86\libv8executor.so" target="lib\droidx86\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libv8executor.so" target="lib\droidarm64\unstripped"/>
+
+ <file src="build\tmp\buildReactNdkLib\local\x86_64\libyoga.so" target="lib\droidx64\unstripped"/> + <file src="build\tmp\buildReactNdkLib\local\x86_64\libyoga.so" target="lib\droidx64\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libyoga.so" target="lib\droidarm\unstripped"/> + <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libyoga.so" target="lib\droidarm\unstripped"/>
+ <file src="build\tmp\buildReactNdkLib\local\x86\libyoga.so" target="lib\droidx86\unstripped"/> + <file src="build\tmp\buildReactNdkLib\local\x86\libyoga.so" target="lib\droidx86\unstripped"/>
@ -115,7 +105,7 @@
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/> + <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/> + <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/> + <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
+ <file src="..\folly\**\*.*" target="inc" /> + <file src="..\Folly\**\*.*" target="inc" />
+ <file src="..\glog\src\glog\*.h" target="inc\glog" /> + <file src="..\glog\src\glog\*.h" target="inc\glog" />
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/> + <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
+ </files> + </files>

Просмотреть файл

@ -115,7 +115,7 @@
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/> + <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/> + <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/> + <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
+ <file src="..\folly\**\*.*" target="inc" /> + <file src="..\Folly\**\*.*" target="inc" />
+ <file src="..\glog\src\glog\*.h" target="inc\glog" /> + <file src="..\glog\src\glog\*.h" target="inc\glog" />
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/> + <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
+ </files> + </files>

Просмотреть файл

@ -52,6 +52,7 @@ function copyProjectTemplateAndReplace(
[ [
{ from: path.join(srcRootPath, macOSDir, 'Podfile'), to: path.join(macOSDir, 'Podfile') }, { from: path.join(srcRootPath, macOSDir, 'Podfile'), to: path.join(macOSDir, 'Podfile') },
{ from: path.join(srcRootPath, macOSDir, '_gitignore'), to: path.join(macOSDir, '.gitignore') },
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'iOS')), to: srcDirPath(newProjectName, 'iOS') }, { from: path.join(srcRootPath, srcDirPath(oldProjectName, 'iOS')), to: srcDirPath(newProjectName, 'iOS') },
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'macOS')), to: srcDirPath(newProjectName, 'macOS') }, { from: path.join(srcRootPath, srcDirPath(oldProjectName, 'macOS')), to: srcDirPath(newProjectName, 'macOS') },
{ from: path.join(srcRootPath, pbxprojPath(oldProjectName)), to: pbxprojPath(newProjectName) }, { from: path.join(srcRootPath, pbxprojPath(oldProjectName)), to: pbxprojPath(newProjectName) },
@ -143,12 +144,18 @@ function installDependencies(options) {
childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions); childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions);
} }
/**
* @param {{ verbose?: boolean }=} options
*/
function installPods(options) { function installPods(options) {
const cwd = path.join(process.cwd(), macOSDir); const cwd = path.join(process.cwd(), macOSDir);
const quietFlag = options && options.verbose ? '' : '--quiet'; const quietFlag = options && options.verbose ? '' : '--quiet';
childProcess.execSync(`npx pod-install --non-interactive ${quietFlag}`, { stdio: 'inherit', cwd }); childProcess.execSync(`npx ${quietFlag} pod-install --non-interactive ${quietFlag}`, { stdio: 'inherit', cwd });
} }
/**
* @param {string} newProjectName
*/
function printFinishMessage(newProjectName) { function printFinishMessage(newProjectName) {
console.log(` console.log(`
${chalk.blue(`Run instructions for ${chalk.bold('macOS')}`)}: ${chalk.blue(`Run instructions for ${chalk.bold('macOS')}`)}:

Просмотреть файл

@ -683,7 +683,7 @@
<scene sceneID="R2V-B0-nI4"> <scene sceneID="R2V-B0-nI4">
<objects> <objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController"> <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="HelloWorld" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA"> <window key="window" title="HelloWorld" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/> <rect key="contentRect" x="196" y="240" width="480" height="270"/>

Просмотреть файл

@ -0,0 +1,2 @@
# CocoaPods
Pods/

Просмотреть файл

@ -1,6 +1,21 @@
{ {
"name": "react-native-macos-init", "name": "react-native-macos-init",
"entries": [ "entries": [
{
"date": "Mon, 18 May 2020 23:31:12 GMT",
"tag": "react-native-macos-init_v2.1.0",
"version": "2.1.0",
"comments": {
"minor": [
{
"comment": "check the currently installed version of RNmacOS + CLI display tweaks",
"author": "gosimek@gmail.com",
"commit": "1f640ad99a98c7731a5c210b0dd92673d6a7a230",
"package": "react-native-macos-init"
}
]
}
},
{ {
"date": "Sun, 05 Apr 2020 00:06:57 GMT", "date": "Sun, 05 Apr 2020 00:06:57 GMT",
"tag": "react-native-macos-init_v2.0.0", "tag": "react-native-macos-init_v2.0.0",

Просмотреть файл

@ -1,9 +1,17 @@
# Change Log - react-native-macos-init # Change Log - react-native-macos-init
This log was last generated on Sun, 05 Apr 2020 00:06:57 GMT and should not be manually modified. This log was last generated on Mon, 18 May 2020 23:31:12 GMT and should not be manually modified.
<!-- Start content --> <!-- Start content -->
## 2.1.0
Mon, 18 May 2020 23:31:12 GMT
### Minor changes
- check the currently installed version of RNmacOS + CLI display tweaks (gosimek@gmail.com)
## 2.0.0 ## 2.0.0
Sun, 05 Apr 2020 00:06:57 GMT Sun, 05 Apr 2020 00:06:57 GMT

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"name": "react-native-macos-init", "name": "react-native-macos-init",
"version": "2.0.0", "version": "2.1.0",
"description": "CLI to add react-native-macos to an existing react-native project", "description": "CLI to add react-native-macos to an existing react-native project",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/microsoft/react-native-macos", "repository": "https://github.com/microsoft/react-native-macos",

Просмотреть файл

@ -47,19 +47,22 @@ const EXITCODE_NO_REACTNATIVE_FOUND = 5;
const EXITCODE_UNKNOWN_ERROR = 6; const EXITCODE_UNKNOWN_ERROR = 6;
const EXITCODE_NO_PACKAGE_JSON = 7; const EXITCODE_NO_PACKAGE_JSON = 7;
const RNPKG = 'react-native';
const MACOSPKG = 'react-native-macos';
function reactNativeMacOSGeneratePath() { function reactNativeMacOSGeneratePath() {
return require.resolve('react-native-macos/local-cli/generate-macos.js', { return require.resolve(`${MACOSPKG}/local-cli/generate-macos.js`, {
paths: [process.cwd()], paths: [process.cwd()],
}); });
} }
function getReactNativeAppName() { function getReactNativeAppName() {
console.log('Reading application name from package.json...'); console.log(`Reading ${chalk.cyan('application name')} from package.json…`);
const cwd = process.cwd(); const cwd = process.cwd();
const pkgJsonPath = findUp.sync('package.json', {cwd}); const pkgJsonPath = findUp.sync('package.json', {cwd});
if (!pkgJsonPath) { if (!pkgJsonPath) {
console.error( printError(
'Unable to find package.json. This should be run from within an existing react-native app.', `Unable to find package.json. This should be run from within an existing ${RNPKG} app.`,
); );
process.exit(EXITCODE_NO_PACKAGE_JSON); process.exit(EXITCODE_NO_PACKAGE_JSON);
} }
@ -67,36 +70,52 @@ function getReactNativeAppName() {
if (!name) { if (!name) {
const appJsonPath = findUp.sync('app.json', {cwd}); const appJsonPath = findUp.sync('app.json', {cwd});
if (appJsonPath) { if (appJsonPath) {
console.log('Reading application name from app.json...'); console.log(`Reading ${chalk.cyan('application name')} from app.json…`);
name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name; name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name;
} }
} }
if (!name) { if (!name) {
console.error('Please specify name in package.json or app.json'); printError('Please specify name in package.json or app.json.');
} }
return name; return name;
} }
function getReactNativeVersion() { function getPackageVersion(
console.log('Reading react-native version from node_modules...'); packageName: string,
const rnPkgJsonPath = require.resolve('react-native/package.json', { exitOnError: boolean = true
paths: [process.cwd()], ) {
}); console.log(`Reading ${chalk.cyan(packageName)} version from node_modules…`);
if (fs.existsSync(rnPkgJsonPath)) {
return require(rnPkgJsonPath).version;
}
console.error( try {
'Error: Must be run from a project that already depends on react-native, and has react-native installed.', const pkgJsonPath = require.resolve(`${packageName}/package.json`, {
); paths: [process.cwd()],
process.exit(EXITCODE_NO_REACTNATIVE_FOUND); });
if (fs.existsSync(pkgJsonPath)) {
return require(pkgJsonPath).version;
}
} catch (error) {
if (exitOnError) {
printError(
`Must be run from a project that already depends on ${packageName}, and has ${packageName} installed.`,
);
process.exit(EXITCODE_NO_REACTNATIVE_FOUND);
}
}
}
function getReactNativeVersion() {
return getPackageVersion(RNPKG);
}
function getReactNativeMacOSVersion() {
return getPackageVersion(MACOSPKG, false);
} }
function errorOutOnUnsupportedVersionOfReactNative(rnVersion: string) { function errorOutOnUnsupportedVersionOfReactNative(rnVersion: string) {
console.error(`Error: Unsupported version of react-native: ${chalk.cyan( printError(`Unsupported version of ${RNPKG}: ${chalk.cyan(
rnVersion, rnVersion,
)} )}
react-native-macos supports react-native versions ${chalk.cyan('>=0.60')}`); ${MACOSPKG} supports ${RNPKG} versions ${chalk.cyan('>=0.60')}`);
process.exit(EXITCODE_UNSUPPORTED_VERION_RN); process.exit(EXITCODE_UNSUPPORTED_VERION_RN);
} }
@ -160,7 +179,7 @@ function getLatestMatchingVersion(
} }
} }
reject( reject(
new Error(`No matching version of ${pkg}@${versionSemVer} found`), new Error(`No matching version of ${pkg}@${versionSemVer} found!`),
); );
}, },
); );
@ -177,7 +196,7 @@ function getLatestMatchingVersion(
return; return;
} }
reject( reject(
new Error(`No matching version of ${pkg}@${versionSemVer} found`), new Error(`No matching version of ${pkg}@${versionSemVer} found!`),
); );
}, },
); );
@ -190,13 +209,13 @@ async function getLatestMatchingReactNativeMacOSVersion(
): Promise<string> { ): Promise<string> {
try { try {
const version = await getLatestMatchingVersion( const version = await getLatestMatchingVersion(
'react-native-macos', MACOSPKG,
versionSemVer, versionSemVer,
); );
return version; return version;
} catch (err) { } catch (err) {
console.error( printError(
`Error: No version of react-native-macos@${versionSemVer} found`, `No version of ${printPkg(MACOSPKG, versionSemVer)} found!`,
); );
process.exit(EXITCODE_NO_MATCHING_RNMACOS); process.exit(EXITCODE_NO_MATCHING_RNMACOS);
return ""; return "";
@ -210,17 +229,33 @@ function isProjectUsingYarn(cwd: string) {
return findUp.sync('yarn.lock', {cwd}); return findUp.sync('yarn.lock', {cwd});
} }
/**
* Outputs decorated version of the package for the CLI
*/
function printPkg(name: string, version?: string) {
return `${chalk.yellow(name)}${version ? `${chalk.grey('@')}${chalk.cyan(version)}` : ''}`;
}
/**
* Prints decorated version of console.error to the CLI
*/
function printError(message: string, ...optionalParams: any[]) {
console.error(chalk.red(chalk.bold(message)), ...optionalParams);
}
(async () => { (async () => {
try { try {
const name = getReactNativeAppName(); const { overwrite, verbose } = argv;
let version = argv.version; let version = argv.version;
const name = getReactNativeAppName();
const reactNativeVersion = getReactNativeVersion();
const reactNativeMacOSVersion = getReactNativeMacOSVersion();
const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest'); const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest');
if (!version) { if (!version) {
const rnVersion = getReactNativeVersion();
version = getDefaultReactNativeMacOSSemVerForReactNativeVersion( version = getDefaultReactNativeMacOSSemVerForReactNativeVersion(
rnVersion, reactNativeVersion,
reactNativeMacOSLatestVersion reactNativeMacOSLatestVersion
); );
} }
@ -229,33 +264,25 @@ function isProjectUsingYarn(cwd: string) {
if (!argv.version) { if (!argv.version) {
console.log( console.log(
`Latest matching version of ${chalk.bold( `Latest matching version of ${chalk.green(MACOSPKG)} for ${printPkg(
'react-native-macos', RNPKG,
)} for ${chalk.green('react-native')}@${chalk.cyan( reactNativeVersion
getReactNativeVersion(), )} is ${printPkg(
)} is ${chalk.green('react-native-macos')}@${chalk.cyan( MACOSPKG,
reactNativeMacOSResolvedVersion, reactNativeMacOSResolvedVersion
)}`, )}.`,
); );
if (semver.prerelease(reactNativeMacOSResolvedVersion)) { if (semver.prerelease(reactNativeMacOSResolvedVersion)) {
console.warn( console.warn(
` `
${chalk.green('react-native-macos')}@${chalk.cyan( ${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)} is a ${chalk.bgYellow('pre-release')} version.
reactNativeMacOSResolvedVersion, The latest supported version is ${printPkg(MACOSPKG, reactNativeMacOSLatestVersion)}.
)} is a ${chalk.yellow('pre-release')} version. You can either downgrade your version of ${chalk.yellow(RNPKG)} to ${chalk.cyan(
The latest supported version is ${chalk.green(
'react-native-macos',
)}@${chalk.cyan(reactNativeMacOSLatestVersion)}.
You can either downgrade your version of ${chalk.green(
'react-native',
)} to ${chalk.cyan(
getMatchingReactNativeSemVerForReactNativeMacOSVersion( getMatchingReactNativeSemVerForReactNativeMacOSVersion(
reactNativeMacOSLatestVersion, reactNativeMacOSLatestVersion,
), ),
)}, or continue with a ${chalk.yellow( )}, or continue with a ${chalk.bgYellow('pre-release')} version of ${chalk.yellow(MACOSPKG)}.
'pre-release',
)} version of ${chalk.bold('react-native-macos')}.
`, `,
); );
@ -263,9 +290,7 @@ You can either downgrade your version of ${chalk.green(
const confirm = (await prompts({ const confirm = (await prompts({
type: 'confirm', type: 'confirm',
name: 'confirm', name: 'confirm',
message: `Do you wish to continue with ${chalk.green( message: `Do you wish to continue with ${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)}?`,
'react-native-macos',
)}@${chalk.cyan(reactNativeMacOSResolvedVersion)}?`,
})).confirm; })).confirm;
if (!confirm) { if (!confirm) {
@ -275,29 +300,29 @@ You can either downgrade your version of ${chalk.green(
} }
} }
const pkgmgr = isProjectUsingYarn(process.cwd()) const pkgLatest = printPkg(MACOSPKG, version);
? 'yarn add'
: 'npm install --save';
const execOptions = argv.verbose ? {stdio: 'inherit' as 'inherit'} : {}; if (reactNativeMacOSResolvedVersion !== reactNativeMacOSVersion) {
console.log( console.log(`${reactNativeMacOSVersion ? 'Upgrading to' : 'Installing'} ${pkgLatest}`);
`Installing ${chalk.green('react-native-macos')}@${chalk.cyan(
version, const pkgmgr = isProjectUsingYarn(process.cwd())
)}...`, ? `yarn add${verbose ? '' : ' -s'}`
); : `npm install --save${verbose ? '' : ' --silent'}`;
execSync(`${pkgmgr} "react-native-macos@${version}"`, execOptions); const execOptions = verbose ? { stdio: 'inherit' as 'inherit' } : {};
console.log( execSync(`${pkgmgr} "${MACOSPKG}@${version}"`, execOptions);
chalk.green(`react-native-macos@${version} successfully installed.`),
); console.log(`${pkgLatest} ${chalk.green('successfully installed!')}`);
} else {
console.log(`${chalk.green('Latest version')} of ${pkgLatest} already installed.`);
}
const generateMacOS = require(reactNativeMacOSGeneratePath()); const generateMacOS = require(reactNativeMacOSGeneratePath());
generateMacOS(process.cwd(), name, { generateMacOS(process.cwd(), name, {
overwrite: argv.overwrite, overwrite,
verbose: argv.verbose, verbose,
}); });
} catch (error) { } catch (error) {
console.error(chalk.red(error.message)); printError(error.message, error);
console.error(error);
process.exit(EXITCODE_UNKNOWN_ERROR); process.exit(EXITCODE_UNKNOWN_ERROR);
} }
})(); })();