Merge remote-tracking branch 'origin/master' into fb62merge
This commit is contained in:
Коммит
3a564e024b
|
@ -16,7 +16,7 @@ jobs:
|
|||
- job: AndroidRNPR
|
||||
displayName: Android React Native PR
|
||||
pool:
|
||||
vmImage: vs2017-win2016
|
||||
vmImage: ubuntu-18.04
|
||||
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
|
||||
steps:
|
||||
|
@ -27,18 +27,27 @@ jobs:
|
|||
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
|
||||
|
||||
- task: UseNode@1
|
||||
inputs:
|
||||
version: '12.x'
|
||||
|
||||
- template: templates/apple-droid-node-patching.yml
|
||||
parameters:
|
||||
apply_office_patches: true
|
||||
|
||||
- task: UseNode@1
|
||||
# Install NuGet
|
||||
- task: CmdLine@2
|
||||
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:
|
||||
versionSpec: '>=4.6.4'
|
||||
script: chmod -R +r .
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: "Rename package to react-native"
|
||||
|
@ -50,119 +59,41 @@ jobs:
|
|||
inputs:
|
||||
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
|
||||
displayName: Remove RNTesterApp.android.bundle
|
||||
inputs:
|
||||
script: del RNTesterApp.android.bundle
|
||||
script: rm -f RNTesterApp.android.bundle
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: Create RNTester bundle
|
||||
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
|
||||
env:
|
||||
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
|
||||
inputs:
|
||||
gradleWrapperFile: gradlew
|
||||
# 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
|
||||
script: ./gradlew installArchives -Pparam="excludeLibs"
|
||||
|
||||
- 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'
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
|
||||
packDestination: '$(System.DefaultWorkingDirectory)'
|
||||
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
|
||||
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)
|
||||
|
||||
- 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
|
||||
inputs:
|
||||
gradleWrapperFile: gradlew
|
||||
# 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
|
||||
script: ./gradlew clean
|
|
@ -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}`);
|
||||
|
||||
const {releaseVersion, branchVersionSuffix} = gatherVersionInfo()
|
||||
|
@ -27,7 +27,7 @@ function doPublish() {
|
|||
const onlyTagSource = !!branchVersionSuffix;
|
||||
if (!onlyTagSource) {
|
||||
// -------- Generating Android Artifacts with JavaDoc
|
||||
exec("gradlew installArchives");
|
||||
exec(path.join(process.env.BUILD_SOURCESDIRECTORY, "gradlew") + " installArchives");
|
||||
|
||||
// undo uncommenting javadoc setting
|
||||
exec("git checkout ReactAndroid/gradle.properties");
|
||||
|
@ -40,7 +40,19 @@ function doPublish() {
|
|||
const npmTarPath = path.resolve(__dirname, '..', npmTarFileName);
|
||||
const finalTarPath = path.join(process.env.BUILD_STAGINGDIRECTORY, 'final', npmTarFileName);
|
||||
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);
|
116
.ado/publish.yml
116
.ado/publish.yml
|
@ -39,10 +39,19 @@ jobs:
|
|||
script: node .ado/bumpFileVersions.js
|
||||
|
||||
- task: Npm@1
|
||||
displayName: "Publish react-native-macos to npmjs.org"
|
||||
displayName: "Publish latest react-native-macos to npmjs.org"
|
||||
inputs:
|
||||
command: 'publish'
|
||||
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
|
||||
displayName: 'Tag published release'
|
||||
|
@ -89,13 +98,12 @@ jobs:
|
|||
displayName: "Publish react-native-macos-init to npmjs.org"
|
||||
inputs:
|
||||
script: |
|
||||
cd packages/react-native-macos-init
|
||||
npx --no-install beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
|
||||
npx beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
|
||||
|
||||
- job: RNGithubOfficePublish
|
||||
displayName: React-Native GitHub Publish to Office
|
||||
pool:
|
||||
vmImage: vs2017-win2016
|
||||
vmImage: ubuntu-18.04
|
||||
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
|
||||
steps:
|
||||
|
@ -106,14 +114,27 @@ jobs:
|
|||
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
|
||||
|
||||
- task: UseNode@1
|
||||
inputs:
|
||||
version: '12.x'
|
||||
|
||||
- template: templates/apple-droid-node-patching.yml
|
||||
parameters:
|
||||
apply_office_patches: true
|
||||
|
||||
# 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:
|
||||
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
|
||||
displayName: "Rename package to react-native"
|
||||
|
@ -130,86 +151,18 @@ jobs:
|
|||
inputs:
|
||||
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
|
||||
displayName: Setup Build Dependencies
|
||||
inputs:
|
||||
script: .ado\setup_droid_deps.bat
|
||||
|
||||
- task: Gradle@1
|
||||
displayName: gradlew installArchives
|
||||
env:
|
||||
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
|
||||
inputs:
|
||||
gradleWrapperFile: gradlew
|
||||
# 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
|
||||
script: ./gradlew installArchives -Pparam="excludeLibs"
|
||||
|
||||
- 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'
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
|
||||
packDestination: '$(Build.StagingDirectory)\final'
|
||||
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
|
||||
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)
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Npm pack'
|
||||
|
@ -217,6 +170,7 @@ jobs:
|
|||
script: node .ado/npmOfficePack.js
|
||||
env:
|
||||
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
|
||||
BUILD_SOURCESDIRECTORY: $(Build.SourcesDirectory)
|
||||
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
githubApiToken: $(githubApiToken)
|
||||
|
@ -224,5 +178,5 @@ jobs:
|
|||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish final artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.StagingDirectory)\final'
|
||||
ArtifactName: 'ReactNative-Final'
|
||||
PathtoPublish: '$(Build.StagingDirectory)/final'
|
||||
ArtifactName: 'ReactNative-Final'
|
||||
|
|
|
@ -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
|
||||
displayName: Apply Android specific patches for Office consumption
|
||||
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: ''
|
||||
|
||||
steps:
|
||||
- script: 'brew update'
|
||||
displayName: 'brew update'
|
||||
|
||||
- script: 'brew bundle'
|
||||
displayName: 'brew bundle'
|
||||
|
||||
- script: brew link node@10 --overwrite --force
|
||||
displayName: 'ensure node 10'
|
||||
- script: brew link node@12 --overwrite --force
|
||||
displayName: 'ensure node 12'
|
||||
|
||||
- template: apple-xcode-select.yml
|
||||
|
||||
|
|
|
@ -15,10 +15,14 @@ steps:
|
|||
displayName: 'Clean DerivedData'
|
||||
|
||||
# Install the required components specified in the Brewfile file.
|
||||
- script: 'brew update'
|
||||
displayName: 'brew update'
|
||||
|
||||
- script: '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
|
||||
- template: apple-xcode-select.yml
|
||||
|
|
|
@ -70,8 +70,7 @@ steps:
|
|||
displayName: Publish react-native-macos to verdaccio
|
||||
|
||||
- script: |
|
||||
cd packages/react-native-macos-init
|
||||
npx --no-install beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
|
||||
npx beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
|
||||
displayName: Publish react-native-macos-init to verdaccio
|
||||
|
||||
- task: CmdLine@2
|
||||
|
@ -91,12 +90,6 @@ steps:
|
|||
script: npx react-native-macos-init --version latest --overwrite --prerelease
|
||||
workingDirectory: $(Agent.BuildDirectory)/testcli
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: Install pods
|
||||
inputs:
|
||||
script: pod install
|
||||
workingDirectory: $(Agent.BuildDirectory)/testcli/macos
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: Run macos
|
||||
inputs:
|
||||
|
|
2
Brewfile
2
Brewfile
|
@ -1,2 +1,2 @@
|
|||
brew "node@10"
|
||||
brew "node@12"
|
||||
brew "watchman"
|
||||
|
|
|
@ -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';
|
||||
|
||||
const Promise = require('../../Promise');
|
||||
const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter');
|
||||
|
||||
import NativeAccessibilityManager from './NativeAccessibilityManager';
|
||||
|
||||
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 = {
|
||||
/**
|
||||
* 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> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
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(
|
||||
eventName: ChangeEventName,
|
||||
handler: Function,
|
||||
): void {
|
||||
warning(false, 'AccessibilityInfo is not supported on this platform.');
|
||||
): Object {
|
||||
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(
|
||||
eventName: ChangeEventName,
|
||||
handler: Function,
|
||||
): 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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');
|
||||
|
||||
import type {PressEvent} from '../Types/CoreEventTypes';
|
||||
import type {FocusEvent, BlurEvent} from './TextInput/TextInput'; // TODO(OSS Candidate ISS#2710739)
|
||||
|
||||
type ButtonProps = $ReadOnly<{|
|
||||
/**
|
||||
|
@ -100,6 +101,18 @@ type ButtonProps = $ReadOnly<{|
|
|||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
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,
|
||||
disabled,
|
||||
testID,
|
||||
onFocus, // TODO(OSS Candidate ISS#2710739)
|
||||
onBlur, // TODO(OSS Candidate ISS#2710739)
|
||||
} = this.props;
|
||||
const buttonStyles = [styles.button];
|
||||
const textStyles = [styles.text];
|
||||
|
@ -189,6 +204,8 @@ class Button extends React.Component<ButtonProps> {
|
|||
testID={testID}
|
||||
disabled={disabled}
|
||||
onPress={onPress}
|
||||
onFocus={onFocus} // TODO(OSS Candidate ISS#2710739)
|
||||
onBlur={onBlur} // TODO(OSS Candidate ISS#2710739)
|
||||
touchSoundDisabled={touchSoundDisabled}>
|
||||
<View style={buttonStyles}>
|
||||
<Text style={textStyles} disabled={disabled}>
|
||||
|
|
|
@ -1129,6 +1129,8 @@ function InternalTextInput(props: Props): React.Node {
|
|||
<TouchableWithoutFeedback
|
||||
onLayout={props.onLayout}
|
||||
onPress={_onPress}
|
||||
onFocus={_onFocus} // TODO(macOS ISS#2323203)
|
||||
onBlur={_onBlur} // TODO(macOS ISS#2323203)
|
||||
accessible={props.accessible}
|
||||
accessibilityLabel={props.accessibilityLabel}
|
||||
accessibilityRole={props.accessibilityRole}
|
||||
|
|
|
@ -185,6 +185,8 @@ class TouchableBounce extends React.Component<Props, State> {
|
|||
onDragEnter={this.props.onDragEnter}
|
||||
onDragLeave={this.props.onDragLeave}
|
||||
onDrop={this.props.onDrop}
|
||||
onFocus={this.props.onFocus}
|
||||
onBlur={this.props.onBlur}
|
||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
||||
ref={this.props.hostRef}
|
||||
{...eventHandlersWithoutBlurAndFocus}>
|
||||
|
|
|
@ -339,6 +339,8 @@ class TouchableHighlight extends React.Component<Props, State> {
|
|||
onDragEnter={this.props.onDragEnter}
|
||||
onDragLeave={this.props.onDragLeave}
|
||||
onDrop={this.props.onDrop}
|
||||
onFocus={this.props.onFocus}
|
||||
onBlur={this.props.onBlur}
|
||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS/win ISS#2323203)
|
||||
nativeID={this.props.nativeID}
|
||||
testID={this.props.testID}
|
||||
|
|
|
@ -275,6 +275,8 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|||
onDragEnter={this.props.onDragEnter}
|
||||
onDragLeave={this.props.onDragLeave}
|
||||
onDrop={this.props.onDrop}
|
||||
onFocus={this.props.onFocus}
|
||||
onBlur={this.props.onBlur}
|
||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
||||
ref={this.props.hostRef}
|
||||
{...eventHandlersWithoutBlurAndFocus}>
|
||||
|
|
|
@ -16,22 +16,22 @@ const ReactNativeViewViewConfigMacOS = {
|
|||
uiViewClassName: 'RCTView',
|
||||
directEventTypes: {
|
||||
topDoubleClick: {
|
||||
registrationName: 'topDoubleClick',
|
||||
registrationName: 'onDoubleClick',
|
||||
},
|
||||
topDragEnter: {
|
||||
registrationName: 'topDragEnter',
|
||||
registrationName: 'onDragEnter',
|
||||
},
|
||||
topDragLeave: {
|
||||
registrationName: 'topDragLeave',
|
||||
registrationName: 'onDragLeave',
|
||||
},
|
||||
topDrop: {
|
||||
registrationName: 'topDrop',
|
||||
registrationName: 'onDrop',
|
||||
},
|
||||
topMouseEnter: {
|
||||
registrationName: 'topMouseEnter',
|
||||
registrationName: 'onMouseEnter',
|
||||
},
|
||||
topMouseLeave: {
|
||||
registrationName: 'topMouseLeave',
|
||||
registrationName: 'onMouseLeave',
|
||||
},
|
||||
},
|
||||
validAttributes: {
|
||||
|
|
|
@ -8,25 +8,19 @@
|
|||
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
||||
#if !TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
#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/RCTResizeMode.h>
|
||||
|
||||
@class RCTBridge;
|
||||
@class RCTImageSource;
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
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)
|
||||
@interface RCTImageView : RCTView
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
|
@ -38,15 +32,6 @@ typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
|
|||
@property (nonatomic, assign) RCTResizeMode resizeMode;
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
/**
|
||||
* 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;
|
||||
@property (nonatomic, copy) NSColor *tintColor;
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
@end
|
||||
|
|
|
@ -283,17 +283,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
_imageView.contentMode = UIViewContentModeScaleToFill;
|
||||
#else // [TODO(macOS ISS#2323203)
|
||||
self.imageScaling = NSImageScaleAxesIndependently;
|
||||
_imageView.imageScaling = NSImageScaleAxesIndependently;
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
} else {
|
||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
_imageView.contentMode = (UIViewContentMode)resizeMode;
|
||||
#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) {
|
||||
resizeMode = RCTResizeModeCenter;
|
||||
}
|
||||
self.imageScaling = (NSImageScaling)resizeMode;
|
||||
_imageView.imageScaling = (NSImageScaling)resizeMode;
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
}
|
||||
|
||||
|
@ -617,5 +617,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
{
|
||||
[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)
|
||||
@end
|
||||
|
|
|
@ -41,7 +41,6 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
|||
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
|
||||
RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>);
|
||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
|
||||
{
|
||||
// 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.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode;
|
||||
}
|
||||
#endif // TODO(macOS ISS#2323203)
|
||||
|
||||
RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request
|
||||
successBlock:(RCTResponseSenderBlock)successBlock
|
||||
|
|
|
@ -47,6 +47,7 @@ function nativeImageSource(spec: NativeImageSourceSpec): ImageURISource {
|
|||
android: spec.android,
|
||||
default: spec.default,
|
||||
ios: spec.ios,
|
||||
macos: spec.macos, // TODO(macOS ISS#2323203)
|
||||
});
|
||||
if (uri == null) {
|
||||
console.warn(
|
||||
|
|
|
@ -2163,6 +2163,7 @@ class CellRenderer extends React.Component<
|
|||
return renderItem({
|
||||
item,
|
||||
index,
|
||||
isSelected, // TODO(macOS ISS#2323203)
|
||||
separators: this._separators,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#import <React/RCTComponent.h>
|
||||
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
|
||||
|
||||
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
||||
|
||||
|
@ -13,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface RCTTextView : RCTUIView // TODO(macOS ISS#3536887)
|
||||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher; // TODO(OSS Candidate ISS#2710739)
|
||||
|
||||
@property (nonatomic, assign) BOOL selectable;
|
||||
|
||||
- (void)setTextStorage:(NSTextStorage *)textStorage
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#import <React/RCTAssert.h> // TODO(macOS ISS#2323203)
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/UIView+React.h>
|
||||
#import <React/RCTFocusChangeEvent.h> // TODO(OSS Candidate ISS#2710739)
|
||||
|
||||
#import <React/RCTTextShadowView.h>
|
||||
|
||||
|
@ -26,13 +27,26 @@
|
|||
CAShapeLayer *_highlightLayer;
|
||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
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)
|
||||
NSTextStorage *_Nullable _textStorage;
|
||||
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
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
|
@ -49,6 +63,25 @@
|
|||
}
|
||||
|
||||
#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
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
// On macOS when a large number of flex layouts are being performed, such
|
||||
// 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];
|
||||
}
|
||||
[self removeAllTextStorageLayoutManagers];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
_textStorage = textStorage;
|
||||
|
@ -273,6 +296,28 @@
|
|||
|
||||
#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 *superAccessibilityLabel = [super accessibilityLabel];
|
||||
|
@ -281,6 +326,7 @@
|
|||
}
|
||||
return _textStorage.string;
|
||||
}
|
||||
#endif // TODO(macOS ISS#2323203)
|
||||
|
||||
#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)
|
||||
|
||||
- (BOOL)canBecomeFirstResponder
|
||||
|
|
|
@ -54,7 +54,7 @@ RCT_EXPORT_VIEW_PROPERTY(selectable, BOOL)
|
|||
|
||||
- (RCTUIView *)view // TODO(macOS ISS#3536887)
|
||||
{
|
||||
return [RCTTextView new];
|
||||
return [[RCTTextView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
|
|
|
@ -191,6 +191,9 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
|||
// enter/return
|
||||
if (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:)) {
|
||||
[self textFieldDidEndEditingOnExit];
|
||||
if ([[_backedTextInputView textInputDelegate] textInputShouldReturn]) {
|
||||
[[_backedTextInputView window] makeFirstResponder:nil];
|
||||
}
|
||||
commandHandled = YES;
|
||||
//backspace
|
||||
} else if (commandSelector == @selector(deleteBackward:)) {
|
||||
|
@ -298,18 +301,16 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
|||
|
||||
- (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`.
|
||||
if (!_backedTextInputView.textWasPasted && [text isEqualToString:@"\n"]) {
|
||||
if ([_backedTextInputView.textInputDelegate textInputShouldReturn]) {
|
||||
[_backedTextInputView.textInputDelegate textInputDidReturn];
|
||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
[_backedTextInputView endEditing:NO];
|
||||
#else // [TODO(macOS ISS#2323203)
|
||||
[[_backedTextInputView window] endEditingFor:nil];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
NSString *newText =
|
||||
[_backedTextInputView.textInputDelegate textInputShouldChangeText:text inRange:range];
|
||||
|
@ -399,9 +400,11 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
|||
BOOL commandHandled = NO;
|
||||
id<RCTBackedTextInputDelegate> textInputDelegate = [_backedTextInputView textInputDelegate];
|
||||
// enter/return
|
||||
if (textInputDelegate.textInputShouldReturn && (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) {
|
||||
[_backedTextInputView.window makeFirstResponder:nil];
|
||||
commandHandled = YES;
|
||||
if ((commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) {
|
||||
if (textInputDelegate.textInputShouldReturn) {
|
||||
[_backedTextInputView.window makeFirstResponder:nil];
|
||||
commandHandled = YES;
|
||||
}
|
||||
//backspace
|
||||
} else if (commandSelector == @selector(deleteBackward:)) {
|
||||
commandHandled = textInputDelegate != nil && ![textInputDelegate textInputShouldHandleDeleteBackward:_backedTextInputView];
|
||||
|
|
|
@ -348,7 +348,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
||||
reactTag:self.reactTag
|
||||
text:self.backedTextInputView.attributedText.string
|
||||
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
@ -362,13 +362,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
{
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
|
||||
reactTag:self.reactTag
|
||||
text:self.backedTextInputView.attributedText.string
|
||||
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
||||
reactTag:self.reactTag
|
||||
text:self.backedTextInputView.attributedText.string
|
||||
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
@ -380,11 +380,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
// `onSubmitEditing` is called when "Submit" button
|
||||
// (the blue key on onscreen keyboard) did pressed
|
||||
// (no connection to any specific "submitting" process).
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
|
||||
reactTag:self.reactTag
|
||||
text:self.backedTextInputView.attributedText.string
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
|
||||
if (_blurOnSubmit) {
|
||||
#endif // ]TODO(macOS Candidate ISS#2710739)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
|
||||
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;
|
||||
}
|
||||
|
@ -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) {
|
||||
_predictedText = backedTextInputView.attributedText.string;
|
||||
|
@ -489,7 +495,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
|||
|
||||
if (_onChange) {
|
||||
_onChange(@{
|
||||
@"text": self.attributedText.string,
|
||||
@"text": [self.attributedText.string copy], // [TODO(macOS Candidate ISS#2710739)
|
||||
@"target": self.reactTag,
|
||||
@"eventCount": @(_nativeEventCount),
|
||||
});
|
||||
|
|
|
@ -37,9 +37,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (assign, getter=isEditable) BOOL editable;
|
||||
#endif
|
||||
#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) NSAttributedString *attributedText;
|
||||
@property (nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
|
||||
@property (nonatomic, assign) NSTextAlignment textAlignment;
|
||||
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
|
||||
@property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled;
|
||||
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor;
|
||||
|
|
|
@ -83,15 +83,9 @@
|
|||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
@dynamic delegate;
|
||||
|
||||
static UIFont *defaultPlaceholderFont()
|
||||
{
|
||||
return [UIFont systemFontOfSize:17];
|
||||
}
|
||||
|
||||
static RCTUIColor *defaultPlaceholderTextColor()
|
||||
{
|
||||
// Default placeholder color from UITextField.
|
||||
return [RCTUIColor colorWithRed:0 green:0 blue:0.0980392 alpha:0.22];
|
||||
return [NSColor placeholderTextColor];
|
||||
}
|
||||
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
@ -106,8 +100,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
|||
object:self];
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
self.bordered = NO;
|
||||
self.accessibilityRole = NSAccessibilityTextFieldRole;
|
||||
[self setBordered:NO];
|
||||
[self setAllowsEditingTextAttributes:YES];
|
||||
[self setAccessibilityRole:NSAccessibilityTextFieldRole];
|
||||
[self setBackgroundColor:[NSColor clearColor]];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
_textInputDelegateAdapter = [[RCTBackedTextFieldDelegateAdapter alloc] initWithTextField:self];
|
||||
|
@ -119,6 +115,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
|||
- (void)_textDidChange
|
||||
{
|
||||
_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
|
||||
|
@ -243,6 +243,11 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
|||
[super setDefaultTextAttributes:defaultTextAttributes];
|
||||
#endif // TODO(macOS ISS#2323203)
|
||||
[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
|
||||
|
|
|
@ -173,6 +173,13 @@ post_install do |installer|
|
|||
puts ' adding arm64e to ' + config.name
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -395,7 +395,7 @@ DEPENDENCIES:
|
|||
- Yoga (from `../ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://cdn.cocoapods.org/:
|
||||
trunk:
|
||||
- CocoaAsyncSocket
|
||||
- CocoaLibEvent
|
||||
- Flipper
|
||||
|
@ -501,7 +501,7 @@ SPEC CHECKSUMS:
|
|||
RCTTypeSafety: 4e66a550e8f4d69f045dc4180cb8cfea0b982ed6
|
||||
React: bacecd5320c8bb453aa396179b93061ebd9d34bf
|
||||
React-ART: 2f0eb928d7bc51e6262da595955b0e8fcf6c0a9e
|
||||
React-Core: c80d3cb695659d2b582b7068a2f451c90ac0e744
|
||||
React-Core: 5d95f89aa9cc03ef38e0bac9225ab0084a89f5f8
|
||||
React-CoreModules: 0d5bcd5a3cfd73e5ed5f9d5e7f8f2a733bf62be3
|
||||
React-cxxreact: b7826b0513bdb89e2ddb6b185a9f822069e7c540
|
||||
React-jsi: e6b9022a422abf5add4598413f9d8bddc5c98fec
|
||||
|
@ -522,6 +522,6 @@ SPEC CHECKSUMS:
|
|||
Yoga: 3ed3c35bb7c41fa8f5056b767bc048539f6526ad
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
PODFILE CHECKSUM: 3cfdde26e08d043498daa8442c611eb479f77fb0
|
||||
PODFILE CHECKSUM: dba3e89372dafdb3103dc904bc23601aaf239f68
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
|
|
|
@ -40,9 +40,7 @@
|
|||
RCT_TEST(ViewExample)
|
||||
RCT_TEST(LayoutExample)
|
||||
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)
|
||||
#endif
|
||||
#if !TARGET_OS_TV
|
||||
// No switch available on tvOS
|
||||
RCT_TEST(SwitchExample)
|
||||
|
|
|
@ -134,6 +134,15 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
descriptionText: {
|
||||
fontSize: 14,
|
||||
...Platform.select({
|
||||
macos: {
|
||||
color: {semantic: 'secondaryLabelColor'},
|
||||
},
|
||||
ios: {
|
||||
color: {semantic: 'secondaryLabelColor'},
|
||||
},
|
||||
default: undefined,
|
||||
}),
|
||||
},
|
||||
children: {
|
||||
margin: 10,
|
||||
|
|
|
@ -23,10 +23,19 @@ class RNTesterExampleContainer extends React.Component {
|
|||
const {description, platform} = example;
|
||||
let {title} = example;
|
||||
if (platform) {
|
||||
if (Platform.OS !== platform) {
|
||||
return null;
|
||||
}
|
||||
title += ' (' + platform + ' only)';
|
||||
// [TODO(macOS ISS#2323203)
|
||||
if (platform instanceof Array) {
|
||||
if (!platform.includes(Platform.OS)) {
|
||||
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 (
|
||||
<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<{}> {
|
||||
_handleOnPress = () =>
|
||||
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.description = 'Examples of using Accessibility APIs.';
|
||||
exports.examples = [
|
||||
|
@ -783,10 +897,24 @@ exports.examples = [
|
|||
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',
|
||||
render(): React.Element<typeof 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 ReactNative = require('react-native');
|
||||
import {Platform} from 'react-native';
|
||||
var {StyleSheet, Text, View, TextInput} = ReactNative;
|
||||
var {Button, StyleSheet, Text, View, TextInput} = ReactNative;
|
||||
|
||||
type State = {
|
||||
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
|
||||
Platform.OS === 'macos' ? (
|
||||
<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={() => {
|
||||
this.setState(prevState => ({
|
||||
eventStream: prevState.eventStream + '\nNested View Focus',
|
||||
eventStream:
|
||||
prevState.eventStream + '\nDescendent Button Focus',
|
||||
}));
|
||||
}}
|
||||
onBlur={() => {
|
||||
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>
|
||||
) : null}
|
||||
|
|
|
@ -15,6 +15,7 @@ const React = require('react');
|
|||
const {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
Platform, // TODO(OSS Candidate ISS#2710739)
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
|
@ -26,7 +27,7 @@ const base64Icon =
|
|||
|
||||
const ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
||||
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);
|
||||
|
||||
type ImageSource = $ReadOnly<{|
|
||||
|
@ -312,18 +313,17 @@ class MultipleSourcesExample extends React.Component<
|
|||
style={{flex: 1}}
|
||||
source={[
|
||||
{
|
||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
||||
uri: 'https://www.facebook.com/favicon.ico',
|
||||
width: 38,
|
||||
height: 38,
|
||||
},
|
||||
{
|
||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
||||
uri: 'https://www.facebook.com/favicon.ico',
|
||||
width: 76,
|
||||
height: 76,
|
||||
},
|
||||
{
|
||||
uri:
|
||||
'https://facebook.github.io/react-native/img/opengraph.png',
|
||||
uri: 'https://www.facebook.com/ads/pics/successstories.png',
|
||||
width: 400,
|
||||
height: 400,
|
||||
},
|
||||
|
@ -336,10 +336,10 @@ class MultipleSourcesExample extends React.Component<
|
|||
}
|
||||
|
||||
const fullImage = {
|
||||
uri: 'https://facebook.github.io/react-native/img/opengraph.png',
|
||||
uri: 'https://www.facebook.com/ads/pics/successstories.png',
|
||||
};
|
||||
const smallImage = {
|
||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
||||
uri: 'https://www.facebook.com/favicon.ico',
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -448,9 +448,7 @@ exports.examples = [
|
|||
return (
|
||||
<NetworkImageCallbackExample
|
||||
source={{
|
||||
uri:
|
||||
'http://origami.design/public/images/bird-logo.png?r=1&t=' +
|
||||
Date.now(),
|
||||
uri: 'https://www.facebook.com/favicon.ico?r=1&t=' + Date.now(),
|
||||
}}
|
||||
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
|
||||
/>
|
||||
|
@ -463,7 +461,7 @@ exports.examples = [
|
|||
return (
|
||||
<NetworkImageExample
|
||||
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 (
|
||||
<NetworkImageExample
|
||||
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
|
||||
defaultSource={require('../../assets/bunny.png')}
|
||||
source={{
|
||||
uri: 'https://facebook.github.io/origami/public/images/birds.jpg',
|
||||
uri: 'https://origami.design/public/images/bird-logo.png',
|
||||
}}
|
||||
style={styles.base}
|
||||
/>
|
||||
|
@ -888,7 +886,8 @@ exports.examples = [
|
|||
<Image
|
||||
source={{
|
||||
uri: 'ImageInBundle',
|
||||
bundle: 'RNTesterBundle',
|
||||
bundle:
|
||||
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
|
||||
width: 100,
|
||||
height: 100,
|
||||
}}
|
||||
|
@ -897,7 +896,8 @@ exports.examples = [
|
|||
<Image
|
||||
source={{
|
||||
uri: 'ImageInAssetCatalog',
|
||||
bundle: 'RNTesterBundle',
|
||||
bundle:
|
||||
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
|
||||
width: 100,
|
||||
height: 100,
|
||||
}}
|
||||
|
@ -906,7 +906,7 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: ['ios', 'macos'], // TODO(OSS Candidate ISS#2710739)
|
||||
},
|
||||
{
|
||||
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 = {
|
||||
uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small',
|
||||
};
|
||||
|
@ -611,4 +718,24 @@ exports.examples = [
|
|||
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)
|
||||
"**/macOS/*"
|
||||
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/RCTTV*.*",
|
||||
"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"
|
||||
#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";
|
||||
|
||||
@interface RCTUIManager (RCTRootView)
|
||||
|
@ -53,6 +57,11 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
|||
RCTRootContentView *_contentView;
|
||||
BOOL _passThroughTouches;
|
||||
CGSize _intrinsicContentSize;
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
NSDate *_lastLayout;
|
||||
BOOL _throttleLayout;
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
|
@ -80,6 +89,10 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
|||
_loadingViewFadeDuration = 0.25;
|
||||
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
_lastLayout = [NSDate new];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(bridgeDidReload)
|
||||
name:RCTJavaScriptWillStartLoadingNotification
|
||||
|
@ -174,6 +187,35 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||
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
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
|
|
@ -61,9 +61,9 @@ static NSString *const RCTDarkAquaColor = @"darkAquaColor";
|
|||
NSColor *effectiveColor = _aquaColor;
|
||||
if (@available(macOS 10.14, *)) {
|
||||
NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance];
|
||||
|
||||
|
||||
NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
||||
|
||||
|
||||
if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) {
|
||||
effectiveColor = _darkAquaColor;
|
||||
}
|
||||
|
@ -181,4 +181,37 @@ RCT_FORWARD_PROPERTY(localizedColorNameComponent, NSString *)
|
|||
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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
// `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];
|
||||
}
|
||||
|
||||
|
@ -66,7 +69,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)setColor: (RCTUIColor*)color
|
||||
- (void)setColor:(RCTUIColor*)color
|
||||
{
|
||||
if (_color != color) {
|
||||
_color = color;
|
||||
|
@ -77,19 +80,23 @@
|
|||
- (void)updateLayer
|
||||
{
|
||||
[super updateLayer];
|
||||
if (_color) {
|
||||
if (_color != nil) {
|
||||
CGFloat r, g, b, a;
|
||||
[[_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a];
|
||||
|
||||
CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"];
|
||||
[colorPoly setDefaults];
|
||||
|
||||
CIVector *redVector = [CIVector vectorWithX:r 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];
|
||||
[colorPoly setValue:redVector forKey:@"inputRedCoefficients"];
|
||||
[colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"];
|
||||
[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, 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;
|
||||
#endif // ]TODO(OSS Candidate ISS#2710739)
|
||||
@property (nonatomic, assign) NSTextAlignment textAlign;
|
||||
|
||||
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
|
||||
|
|
|
@ -23,16 +23,17 @@
|
|||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_color = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739)
|
||||
#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
|
||||
#else // [TODO(macOS ISS#2323203)
|
||||
_font = [UIFont systemFontOfSize:11];
|
||||
_color = [NSColor labelColor];
|
||||
[self setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
_selectedIndex = NSNotFound;
|
||||
_textAlign = NSTextAlignmentCenter;
|
||||
self.delegate = self;
|
||||
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
self.controlSize = NSControlSizeRegular;
|
||||
self.editable = NO;
|
||||
|
@ -63,7 +64,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||
NSMutableDictionary *mutableItem = item.mutableCopy;
|
||||
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[RCTConvert NSString:item[@"label"]]
|
||||
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}];
|
||||
NSSize size = attrString.size;
|
||||
if (size.height > maxHeight) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#import <React/RCTBorderStyle.h>
|
||||
#import <React/RCTComponent.h>
|
||||
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
|
||||
#import <React/RCTPointerEvents.h>
|
||||
|
||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
|
@ -22,6 +23,8 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
|
|||
@interface RCTView : RCTUIView // TODO(macOS ISS#3536887)
|
||||
|
||||
// [TODO(OSS Candidate ISS#2710739)
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
- (BOOL)becomeFirstResponder;
|
||||
- (BOOL)resignFirstResponder;
|
||||
// ]TODO(OSS Candidate ISS#2710739)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#import "RCTAutoInsetsProtocol.h"
|
||||
#import "RCTBorderDrawing.h"
|
||||
#import "RCTFocusChangeEvent.h" // TODO(OSS Candidate ISS#2710739)
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTRootContentView.h" // TODO(macOS ISS#2323203)
|
||||
|
@ -108,6 +109,7 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
|
|||
@implementation RCTView
|
||||
{
|
||||
RCTUIColor *_backgroundColor; // TODO(OSS Candidate ISS#2710739)
|
||||
RCTEventDispatcher *_eventDispatcher; // TODO(OSS Candidate ISS#2710739)
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
NSTrackingArea *_trackingArea;
|
||||
BOOL _hasMouseOver;
|
||||
|
@ -116,6 +118,16 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
|
|||
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
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
|
@ -724,21 +736,20 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
|
|||
}
|
||||
|
||||
// If we've gained focus, notify listeners
|
||||
if (self.onFocus != nil ) {
|
||||
self.onFocus(nil);
|
||||
}
|
||||
[_eventDispatcher sendEvent:[RCTFocusChangeEvent focusEventWithReactTag:self.reactTag]];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
if (![super resignFirstResponder]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// If we've gained focus, notify listeners
|
||||
if (self.onBlur != nil ) {
|
||||
self.onBlur(nil);
|
||||
}
|
||||
// If we've lost focus, notify listeners
|
||||
[_eventDispatcher sendEvent:[RCTFocusChangeEvent blurEventWithReactTag:self.reactTag]];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -911,6 +922,11 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) {
|
|||
}
|
||||
|
||||
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 UIEdgeInsets borderInsets = [self bordersAsInsets];
|
||||
|
|
|
@ -89,7 +89,7 @@ RCT_EXPORT_MODULE()
|
|||
#if TARGET_OS_TV
|
||||
return [RCTTVView new];
|
||||
#else
|
||||
return [RCTView new];
|
||||
return [[RCTView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
|
||||
#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>
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
#import "RCTScrollContentLocalData.h"
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@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
|
||||
layoutContext:(RCTLayoutContext)layoutContext
|
||||
{
|
||||
|
|
|
@ -10,9 +10,20 @@
|
|||
#import <React/RCTAssert.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"
|
||||
|
||||
@implementation RCTScrollContentView
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
{
|
||||
BOOL _hasHorizontalScroller;
|
||||
BOOL _hasVerticalScroller;
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
|
@ -21,25 +32,6 @@
|
|||
#else // [TODO(macOS ISS#2323203)
|
||||
// macOS also has a NSClipView in its hierarchy
|
||||
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)
|
||||
|
||||
[super reactSetFrame:frame];
|
||||
|
@ -52,6 +44,32 @@
|
|||
@"Unexpected view hierarchy of RCTScrollView component.");
|
||||
|
||||
[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
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, readonly) RCTBridge *bridge;
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
self.scrollEnabled = YES;
|
||||
self.hasHorizontalScroller = YES;
|
||||
self.hasVerticalScroller = YES;
|
||||
self.autohidesScrollers = YES;
|
||||
self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
|
||||
#else // ]TODO(macOS ISS#2323203)
|
||||
[self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)];
|
||||
|
@ -436,6 +435,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (RCTBridge *)bridge
|
||||
{
|
||||
return [_eventDispatcher bridge];
|
||||
}
|
||||
|
||||
- (RCTUIView *)contentView // TODO(macOS ISS#3536887)
|
||||
{
|
||||
return _scrollView.documentView;
|
||||
|
@ -621,6 +625,11 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
|||
[self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView];
|
||||
_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)
|
||||
|
@ -678,6 +687,13 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
|||
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
|
||||
{
|
||||
[self scrollToOffset:offset animated:YES];
|
||||
|
|
|
@ -294,7 +294,13 @@
|
|||
}
|
||||
|
||||
- (void)reactBlur {
|
||||
#if TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||
if (self == [[self window] firstResponder]) {
|
||||
[[self window] makeFirstResponder:[[self window] nextResponder]];
|
||||
}
|
||||
#else
|
||||
[self resignFirstResponder];
|
||||
#endif
|
||||
}
|
||||
|
||||
#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-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"?>
|
||||
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
+ <metadata>
|
||||
|
@ -45,11 +45,6 @@
|
|||
+ <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\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\armeabi-v7a\libyoga.so" target="lib\droidarm"/>
|
||||
+ <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\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\armeabi-v7a\libyoga.so" target="lib\droidarm\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\jsi\**\*.h" target="inc\jsi"/>
|
||||
+ <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="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
||||
+ </files>
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
|
||||
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
|
||||
+ <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="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
||||
+ </files>
|
||||
|
|
|
@ -52,6 +52,7 @@ function copyProjectTemplateAndReplace(
|
|||
|
||||
[
|
||||
{ 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, 'macOS')), to: srcDirPath(newProjectName, 'macOS') },
|
||||
{ from: path.join(srcRootPath, pbxprojPath(oldProjectName)), to: pbxprojPath(newProjectName) },
|
||||
|
@ -143,12 +144,18 @@ function installDependencies(options) {
|
|||
childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ verbose?: boolean }=} options
|
||||
*/
|
||||
function installPods(options) {
|
||||
const cwd = path.join(process.cwd(), macOSDir);
|
||||
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) {
|
||||
console.log(`
|
||||
${chalk.blue(`Run instructions for ${chalk.bold('macOS')}`)}:
|
||||
|
|
|
@ -683,7 +683,7 @@
|
|||
<scene sceneID="R2V-B0-nI4">
|
||||
<objects>
|
||||
<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"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<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",
|
||||
"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",
|
||||
"tag": "react-native-macos-init_v2.0.0",
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
# 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 -->
|
||||
|
||||
## 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
|
||||
|
||||
Sun, 05 Apr 2020 00:06:57 GMT
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"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",
|
||||
"main": "index.js",
|
||||
"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_NO_PACKAGE_JSON = 7;
|
||||
|
||||
const RNPKG = 'react-native';
|
||||
const MACOSPKG = 'react-native-macos';
|
||||
|
||||
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()],
|
||||
});
|
||||
}
|
||||
|
||||
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 pkgJsonPath = findUp.sync('package.json', {cwd});
|
||||
if (!pkgJsonPath) {
|
||||
console.error(
|
||||
'Unable to find package.json. This should be run from within an existing react-native app.',
|
||||
printError(
|
||||
`Unable to find package.json. This should be run from within an existing ${RNPKG} app.`,
|
||||
);
|
||||
process.exit(EXITCODE_NO_PACKAGE_JSON);
|
||||
}
|
||||
|
@ -67,36 +70,52 @@ function getReactNativeAppName() {
|
|||
if (!name) {
|
||||
const appJsonPath = findUp.sync('app.json', {cwd});
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function getReactNativeVersion() {
|
||||
console.log('Reading react-native version from node_modules...');
|
||||
const rnPkgJsonPath = require.resolve('react-native/package.json', {
|
||||
paths: [process.cwd()],
|
||||
});
|
||||
if (fs.existsSync(rnPkgJsonPath)) {
|
||||
return require(rnPkgJsonPath).version;
|
||||
}
|
||||
function getPackageVersion(
|
||||
packageName: string,
|
||||
exitOnError: boolean = true
|
||||
) {
|
||||
console.log(`Reading ${chalk.cyan(packageName)} version from node_modules…`);
|
||||
|
||||
console.error(
|
||||
'Error: Must be run from a project that already depends on react-native, and has react-native installed.',
|
||||
);
|
||||
process.exit(EXITCODE_NO_REACTNATIVE_FOUND);
|
||||
try {
|
||||
const pkgJsonPath = require.resolve(`${packageName}/package.json`, {
|
||||
paths: [process.cwd()],
|
||||
});
|
||||
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) {
|
||||
console.error(`Error: Unsupported version of react-native: ${chalk.cyan(
|
||||
printError(`Unsupported version of ${RNPKG}: ${chalk.cyan(
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -160,7 +179,7 @@ function getLatestMatchingVersion(
|
|||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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> {
|
||||
try {
|
||||
const version = await getLatestMatchingVersion(
|
||||
'react-native-macos',
|
||||
MACOSPKG,
|
||||
versionSemVer,
|
||||
);
|
||||
return version;
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Error: No version of react-native-macos@${versionSemVer} found`,
|
||||
printError(
|
||||
`No version of ${printPkg(MACOSPKG, versionSemVer)} found!`,
|
||||
);
|
||||
process.exit(EXITCODE_NO_MATCHING_RNMACOS);
|
||||
return "";
|
||||
|
@ -210,17 +229,33 @@ function isProjectUsingYarn(cwd: string) {
|
|||
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 () => {
|
||||
try {
|
||||
const name = getReactNativeAppName();
|
||||
const { overwrite, verbose } = argv;
|
||||
let version = argv.version;
|
||||
|
||||
const name = getReactNativeAppName();
|
||||
const reactNativeVersion = getReactNativeVersion();
|
||||
const reactNativeMacOSVersion = getReactNativeMacOSVersion();
|
||||
const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest');
|
||||
|
||||
if (!version) {
|
||||
const rnVersion = getReactNativeVersion();
|
||||
version = getDefaultReactNativeMacOSSemVerForReactNativeVersion(
|
||||
rnVersion,
|
||||
reactNativeVersion,
|
||||
reactNativeMacOSLatestVersion
|
||||
);
|
||||
}
|
||||
|
@ -229,33 +264,25 @@ function isProjectUsingYarn(cwd: string) {
|
|||
|
||||
if (!argv.version) {
|
||||
console.log(
|
||||
`Latest matching version of ${chalk.bold(
|
||||
'react-native-macos',
|
||||
)} for ${chalk.green('react-native')}@${chalk.cyan(
|
||||
getReactNativeVersion(),
|
||||
)} is ${chalk.green('react-native-macos')}@${chalk.cyan(
|
||||
reactNativeMacOSResolvedVersion,
|
||||
)}`,
|
||||
`Latest matching version of ${chalk.green(MACOSPKG)} for ${printPkg(
|
||||
RNPKG,
|
||||
reactNativeVersion
|
||||
)} is ${printPkg(
|
||||
MACOSPKG,
|
||||
reactNativeMacOSResolvedVersion
|
||||
)}.`,
|
||||
);
|
||||
|
||||
if (semver.prerelease(reactNativeMacOSResolvedVersion)) {
|
||||
console.warn(
|
||||
`
|
||||
${chalk.green('react-native-macos')}@${chalk.cyan(
|
||||
reactNativeMacOSResolvedVersion,
|
||||
)} is a ${chalk.yellow('pre-release')} version.
|
||||
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(
|
||||
${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)} is a ${chalk.bgYellow('pre-release')} version.
|
||||
The latest supported version is ${printPkg(MACOSPKG, reactNativeMacOSLatestVersion)}.
|
||||
You can either downgrade your version of ${chalk.yellow(RNPKG)} to ${chalk.cyan(
|
||||
getMatchingReactNativeSemVerForReactNativeMacOSVersion(
|
||||
reactNativeMacOSLatestVersion,
|
||||
),
|
||||
)}, or continue with a ${chalk.yellow(
|
||||
'pre-release',
|
||||
)} version of ${chalk.bold('react-native-macos')}.
|
||||
)}, or continue with a ${chalk.bgYellow('pre-release')} version of ${chalk.yellow(MACOSPKG)}.
|
||||
`,
|
||||
);
|
||||
|
||||
|
@ -263,9 +290,7 @@ You can either downgrade your version of ${chalk.green(
|
|||
const confirm = (await prompts({
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: `Do you wish to continue with ${chalk.green(
|
||||
'react-native-macos',
|
||||
)}@${chalk.cyan(reactNativeMacOSResolvedVersion)}?`,
|
||||
message: `Do you wish to continue with ${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)}?`,
|
||||
})).confirm;
|
||||
|
||||
if (!confirm) {
|
||||
|
@ -275,29 +300,29 @@ You can either downgrade your version of ${chalk.green(
|
|||
}
|
||||
}
|
||||
|
||||
const pkgmgr = isProjectUsingYarn(process.cwd())
|
||||
? 'yarn add'
|
||||
: 'npm install --save';
|
||||
const pkgLatest = printPkg(MACOSPKG, version);
|
||||
|
||||
const execOptions = argv.verbose ? {stdio: 'inherit' as 'inherit'} : {};
|
||||
console.log(
|
||||
`Installing ${chalk.green('react-native-macos')}@${chalk.cyan(
|
||||
version,
|
||||
)}...`,
|
||||
);
|
||||
execSync(`${pkgmgr} "react-native-macos@${version}"`, execOptions);
|
||||
console.log(
|
||||
chalk.green(`react-native-macos@${version} successfully installed.`),
|
||||
);
|
||||
if (reactNativeMacOSResolvedVersion !== reactNativeMacOSVersion) {
|
||||
console.log(`${reactNativeMacOSVersion ? 'Upgrading to' : 'Installing'} ${pkgLatest}…`);
|
||||
|
||||
const pkgmgr = isProjectUsingYarn(process.cwd())
|
||||
? `yarn add${verbose ? '' : ' -s'}`
|
||||
: `npm install --save${verbose ? '' : ' --silent'}`;
|
||||
const execOptions = verbose ? { stdio: 'inherit' as 'inherit' } : {};
|
||||
execSync(`${pkgmgr} "${MACOSPKG}@${version}"`, execOptions);
|
||||
|
||||
console.log(`${pkgLatest} ${chalk.green('successfully installed!')}`);
|
||||
} else {
|
||||
console.log(`${chalk.green('Latest version')} of ${pkgLatest} already installed.`);
|
||||
}
|
||||
|
||||
const generateMacOS = require(reactNativeMacOSGeneratePath());
|
||||
generateMacOS(process.cwd(), name, {
|
||||
overwrite: argv.overwrite,
|
||||
verbose: argv.verbose,
|
||||
overwrite,
|
||||
verbose,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(chalk.red(error.message));
|
||||
console.error(error);
|
||||
printError(error.message, error);
|
||||
process.exit(EXITCODE_UNKNOWN_ERROR);
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
|
Загрузка…
Ссылка в новой задаче