Merge remote-tracking branch 'origin/master' into fb62merge
This commit is contained in:
Коммит
3a564e024b
|
@ -16,7 +16,7 @@ jobs:
|
||||||
- job: AndroidRNPR
|
- job: AndroidRNPR
|
||||||
displayName: Android React Native PR
|
displayName: Android React Native PR
|
||||||
pool:
|
pool:
|
||||||
vmImage: vs2017-win2016
|
vmImage: ubuntu-18.04
|
||||||
timeoutInMinutes: 90 # how long to run the job before automatically cancelling
|
timeoutInMinutes: 90 # how long to run the job before automatically cancelling
|
||||||
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
|
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
|
||||||
steps:
|
steps:
|
||||||
|
@ -27,18 +27,27 @@ jobs:
|
||||||
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
|
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
|
||||||
persistCredentials: false # set to 'true' to leave the OAuth token in the Git config after the initial fetch
|
persistCredentials: false # set to 'true' to leave the OAuth token in the Git config after the initial fetch
|
||||||
|
|
||||||
|
- task: UseNode@1
|
||||||
|
inputs:
|
||||||
|
version: '12.x'
|
||||||
|
|
||||||
- template: templates/apple-droid-node-patching.yml
|
- template: templates/apple-droid-node-patching.yml
|
||||||
parameters:
|
parameters:
|
||||||
apply_office_patches: true
|
apply_office_patches: true
|
||||||
|
|
||||||
- task: UseNode@1
|
# Install NuGet
|
||||||
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
version: '10.x'
|
script: mkdir $(System.DefaultWorkingDirectory)/nuget-bin/ && curl -o $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
|
||||||
|
|
||||||
# Install NuGet v4.6.4+
|
|
||||||
- task: NuGetToolInstaller@1
|
# This is currently required as the command task (strangely) always runs elevated ..
|
||||||
|
# which makes all the files touched by the above patching step unreadable by following non-command tasks without sudo.
|
||||||
|
# This makes all the files readable.
|
||||||
|
- task: CmdLine@2
|
||||||
|
displayName: chmod
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '>=4.6.4'
|
script: chmod -R +r .
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: "Rename package to react-native"
|
displayName: "Rename package to react-native"
|
||||||
|
@ -50,119 +59,41 @@ jobs:
|
||||||
inputs:
|
inputs:
|
||||||
script: npm install
|
script: npm install
|
||||||
|
|
||||||
- task: NuGetCommand@2
|
|
||||||
displayName: NuGet restore
|
|
||||||
inputs:
|
|
||||||
command: restore
|
|
||||||
restoreSolution: ReactAndroid/packages.config
|
|
||||||
feedsToUse: config
|
|
||||||
#vstsFeed: # Required when feedsToUse == Select
|
|
||||||
#includeNuGetOrg: true # Required when feedsToUse == Select
|
|
||||||
nugetConfigPath: ReactAndroid/NuGet.Config
|
|
||||||
#externalFeedCredentials: # Optional
|
|
||||||
#noCache: false
|
|
||||||
#disableParallelProcessing: false
|
|
||||||
restoreDirectory: packages/
|
|
||||||
verbosityRestore: Detailed # Options: quiet, normal, detailed
|
|
||||||
#packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' # Required when command == Push
|
|
||||||
#nuGetFeedType: 'internal' # Required when command == Push# Options: internal, external
|
|
||||||
#publishVstsFeed: # Required when command == Push && NuGetFeedType == Internal
|
|
||||||
#publishPackageMetadata: true # Optional
|
|
||||||
#allowPackageConflicts: # Optional
|
|
||||||
#publishFeedCredentials: # Required when command == Push && NuGetFeedType == External
|
|
||||||
#verbosityPush: 'Detailed' # Options: quiet, normal, detailed
|
|
||||||
#packagesToPack: '**/*.csproj' # Required when command == Pack
|
|
||||||
#configuration: '$(BuildConfiguration)' # Optional
|
|
||||||
#packDestination: '$(Build.ArtifactStagingDirectory)' # Optional
|
|
||||||
#versioningScheme: 'off' # Options: off, byPrereleaseNumber, byEnvVar, byBuildNumber
|
|
||||||
#includeReferencedProjects: false # Optional
|
|
||||||
#versionEnvVar: # Required when versioningScheme == ByEnvVar
|
|
||||||
#majorVersion: '1' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#minorVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#patchVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#packTimezone: 'utc' # Required when versioningScheme == ByPrereleaseNumber# Options: utc, local
|
|
||||||
#includeSymbols: false # Optional
|
|
||||||
#toolPackage: # Optional
|
|
||||||
#buildProperties: # Optional
|
|
||||||
#basePath: # Optional
|
|
||||||
#verbosityPack: 'Detailed' # Options: quiet, normal, detailed
|
|
||||||
#arguments: # Required when command == Custom
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: Setup Build Dependencies
|
|
||||||
inputs:
|
|
||||||
script: .ado\setup_droid_deps.bat
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: Remove RNTesterApp.android.bundle
|
displayName: Remove RNTesterApp.android.bundle
|
||||||
inputs:
|
inputs:
|
||||||
script: del RNTesterApp.android.bundle
|
script: rm -f RNTesterApp.android.bundle
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: Create RNTester bundle
|
displayName: Create RNTester bundle
|
||||||
inputs:
|
inputs:
|
||||||
script: node cli.js bundle --entry-file .\RNTester\js\RNTesterApp.android.js --bundle-output RNTesterApp.android.bundle --platform android
|
script: node cli.js bundle --entry-file ./RNTester/js/RNTesterApp.android.js --bundle-output RNTesterApp.android.bundle --platform android
|
||||||
|
|
||||||
- task: Gradle@1
|
- task: CmdLine@2
|
||||||
displayName: gradlew installArchives
|
displayName: gradlew installArchives
|
||||||
env:
|
|
||||||
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
|
|
||||||
inputs:
|
inputs:
|
||||||
gradleWrapperFile: gradlew
|
script: ./gradlew installArchives -Pparam="excludeLibs"
|
||||||
# workingDirectory: src\react-native\
|
|
||||||
options: -Pparam="excludeLibs"
|
|
||||||
tasks: installArchives
|
|
||||||
publishJUnitResults: false
|
|
||||||
#testResultsFiles: '**/TEST-*.xml' # Required when publishJUnitResults == True
|
|
||||||
#testRunTitle: # Optional
|
|
||||||
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
|
|
||||||
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
|
|
||||||
#codeCoverageClassFilter: # Optional
|
|
||||||
#codeCoverageFailIfEmpty: false # Optional
|
|
||||||
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
|
|
||||||
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
|
|
||||||
#jdkDirectory: # Required when javaHomeOption == Path
|
|
||||||
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
|
|
||||||
#gradleOptions: '-Xmx1024m' # Optional
|
|
||||||
#sonarQubeRunAnalysis: false
|
|
||||||
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
|
|
||||||
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
|
|
||||||
#checkStyleRunAnalysis: false # Optional
|
|
||||||
#findBugsRunAnalysis: false # Optional
|
|
||||||
#pmdRunAnalysis: false # Optional
|
|
||||||
|
|
||||||
- template: templates\prep-android-nuget.yml
|
- template: templates\prep-android-nuget.yml
|
||||||
|
|
||||||
- task: NuGetCommand@2
|
# Very similar to the default pack task .. but appends 'ndk21' to the nuget pack version
|
||||||
|
- task: CmdLine@2
|
||||||
displayName: 'Verify NuGet can be packed'
|
displayName: 'Verify NuGet can be packed'
|
||||||
inputs:
|
inputs:
|
||||||
command: pack
|
script: NDK=ndk`cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | awk '{ print $3}' | awk -F. '{ print $1 }'`; mono $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe pack $(System.DefaultWorkingDirectory)/ReactAndroid/ReactAndroid.nuspec -OutputDirectory $(System.DefaultWorkingDirectory) -Properties buildNumber=$(buildNumber)-$NDK;commitId=$(Build.SourceVersion)
|
||||||
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
|
|
||||||
packDestination: '$(System.DefaultWorkingDirectory)'
|
|
||||||
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
|
|
||||||
|
|
||||||
- task: Gradle@1
|
- task: CmdLine@2
|
||||||
|
displayName: 'Npm pack'
|
||||||
|
inputs:
|
||||||
|
script: node .ado/npmOfficePack.js --fake
|
||||||
|
env:
|
||||||
|
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
|
||||||
|
BUILD_SOURCESDIRECTORY: $(Build.SourcesDirectory)
|
||||||
|
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
|
githubApiToken: $(githubApiToken)
|
||||||
|
|
||||||
|
- task: CmdLine@2
|
||||||
displayName: gradlew clean
|
displayName: gradlew clean
|
||||||
inputs:
|
inputs:
|
||||||
gradleWrapperFile: gradlew
|
script: ./gradlew clean
|
||||||
# workingDirectory: src\
|
|
||||||
#options: # Optional
|
|
||||||
tasks: clean
|
|
||||||
publishJUnitResults: false
|
|
||||||
#testResultsFiles: '**/build/test-results/TEST-*.xml'
|
|
||||||
#testRunTitle: # Optional
|
|
||||||
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
|
|
||||||
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
|
|
||||||
#codeCoverageClassFilter: # Optional
|
|
||||||
#codeCoverageFailIfEmpty: false # Optional
|
|
||||||
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
|
|
||||||
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
|
|
||||||
#jdkDirectory: # Required when javaHomeOption == Path
|
|
||||||
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
|
|
||||||
#gradleOptions: '-Xmx1024m' # Optional
|
|
||||||
#sonarQubeRunAnalysis: false
|
|
||||||
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
|
|
||||||
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
|
|
||||||
#checkStyleRunAnalysis: false # Optional
|
|
||||||
#findBugsRunAnalysis: false # Optional
|
|
||||||
#pmdRunAnalysis: false # Optional
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
REM @if "%DEBUG%" == "" @echo off
|
||||||
|
|
||||||
|
REM Android tools doesn't support SDK/NDK paths containing space in it.
|
||||||
|
REM This scrip creates a symlink to Android NDK to work around the limitation.
|
||||||
|
REM We use the
|
||||||
|
|
||||||
|
set ANDROID_NDK_SYMLINK_PATH=c:\android_ndk_symlink__
|
||||||
|
|
||||||
|
REM 1. Try ANDROID_NDK environment variable
|
||||||
|
set ANDROID_NDK_PATH=%ANDROID_NDK%
|
||||||
|
|
||||||
|
REM 2. May be SDK has ndk-bundle in it.
|
||||||
|
IF "%ANDROID_NDK_PATH%"=="" set ANDROID_NDK_PATH=%ANDROID_home%\ndk-bundle
|
||||||
|
|
||||||
|
echo %ANDROID_NDK_PATH%
|
||||||
|
|
||||||
|
if exist %ANDROID_NDK_PATH% (
|
||||||
|
mklink /J %ANDROID_NDK_SYMLINK_PATH% "%ANDROID_NDK_PATH%"
|
||||||
|
goto :success
|
||||||
|
) else (
|
||||||
|
goto :error
|
||||||
|
)
|
||||||
|
|
||||||
|
:success
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:error
|
||||||
|
exit /b 1
|
|
@ -19,7 +19,7 @@ function exec(command) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doPublish() {
|
function doPublish(fakeMode) {
|
||||||
console.log(`Target branch to publish to: ${publishBranchName}`);
|
console.log(`Target branch to publish to: ${publishBranchName}`);
|
||||||
|
|
||||||
const {releaseVersion, branchVersionSuffix} = gatherVersionInfo()
|
const {releaseVersion, branchVersionSuffix} = gatherVersionInfo()
|
||||||
|
@ -27,7 +27,7 @@ function doPublish() {
|
||||||
const onlyTagSource = !!branchVersionSuffix;
|
const onlyTagSource = !!branchVersionSuffix;
|
||||||
if (!onlyTagSource) {
|
if (!onlyTagSource) {
|
||||||
// -------- Generating Android Artifacts with JavaDoc
|
// -------- Generating Android Artifacts with JavaDoc
|
||||||
exec("gradlew installArchives");
|
exec(path.join(process.env.BUILD_SOURCESDIRECTORY, "gradlew") + " installArchives");
|
||||||
|
|
||||||
// undo uncommenting javadoc setting
|
// undo uncommenting javadoc setting
|
||||||
exec("git checkout ReactAndroid/gradle.properties");
|
exec("git checkout ReactAndroid/gradle.properties");
|
||||||
|
@ -40,7 +40,19 @@ function doPublish() {
|
||||||
const npmTarPath = path.resolve(__dirname, '..', npmTarFileName);
|
const npmTarPath = path.resolve(__dirname, '..', npmTarFileName);
|
||||||
const finalTarPath = path.join(process.env.BUILD_STAGINGDIRECTORY, 'final', npmTarFileName);
|
const finalTarPath = path.join(process.env.BUILD_STAGINGDIRECTORY, 'final', npmTarFileName);
|
||||||
console.log(`Copying tar file ${npmTarPath} to: ${finalTarPath}`)
|
console.log(`Copying tar file ${npmTarPath} to: ${finalTarPath}`)
|
||||||
fs.copyFileSync(npmTarPath, finalTarPath);
|
|
||||||
|
if(fakeMode) {
|
||||||
|
if (!fs.existsSync(npmTarPath))
|
||||||
|
throw "The final artefact to be published is missing.";
|
||||||
|
} else {
|
||||||
|
fs.copyFileSync(npmTarPath, finalTarPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doPublish();
|
var args = process.argv.slice(2);
|
||||||
|
|
||||||
|
let fakeMode = false;
|
||||||
|
if (args.length > 0 && args[0] === '--fake')
|
||||||
|
fakeMode = true;
|
||||||
|
|
||||||
|
doPublish(fakeMode);
|
116
.ado/publish.yml
116
.ado/publish.yml
|
@ -39,10 +39,19 @@ jobs:
|
||||||
script: node .ado/bumpFileVersions.js
|
script: node .ado/bumpFileVersions.js
|
||||||
|
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
displayName: "Publish react-native-macos to npmjs.org"
|
displayName: "Publish latest react-native-macos to npmjs.org"
|
||||||
inputs:
|
inputs:
|
||||||
command: 'publish'
|
command: 'publish'
|
||||||
publishEndpoint: 'npmjs'
|
publishEndpoint: 'npmjs'
|
||||||
|
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
|
||||||
|
|
||||||
|
- task: Npm@1
|
||||||
|
displayName: "Publish stable react-native-macos to npmjs.org"
|
||||||
|
inputs:
|
||||||
|
command: 'custom'
|
||||||
|
customCommand: publish --tag $(Build.SourceBranchName)
|
||||||
|
publishEndpoint: 'npmjs'
|
||||||
|
condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: 'Tag published release'
|
displayName: 'Tag published release'
|
||||||
|
@ -89,13 +98,12 @@ jobs:
|
||||||
displayName: "Publish react-native-macos-init to npmjs.org"
|
displayName: "Publish react-native-macos-init to npmjs.org"
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
cd packages/react-native-macos-init
|
npx beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
|
||||||
npx --no-install beachball publish --branch origin/$(Build.SourceBranchName) -n $(npmAuthToken) -yes -m "applying package updates ***NO_CI***" --access public
|
|
||||||
|
|
||||||
- job: RNGithubOfficePublish
|
- job: RNGithubOfficePublish
|
||||||
displayName: React-Native GitHub Publish to Office
|
displayName: React-Native GitHub Publish to Office
|
||||||
pool:
|
pool:
|
||||||
vmImage: vs2017-win2016
|
vmImage: ubuntu-18.04
|
||||||
timeoutInMinutes: 90 # how long to run the job before automatically cancelling
|
timeoutInMinutes: 90 # how long to run the job before automatically cancelling
|
||||||
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
|
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
|
||||||
steps:
|
steps:
|
||||||
|
@ -106,14 +114,27 @@ jobs:
|
||||||
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
|
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
|
||||||
persistCredentials: true # set to 'true' to leave the OAuth token in the Git config after the initial fetch
|
persistCredentials: true # set to 'true' to leave the OAuth token in the Git config after the initial fetch
|
||||||
|
|
||||||
|
- task: UseNode@1
|
||||||
|
inputs:
|
||||||
|
version: '12.x'
|
||||||
|
|
||||||
- template: templates/apple-droid-node-patching.yml
|
- template: templates/apple-droid-node-patching.yml
|
||||||
parameters:
|
parameters:
|
||||||
apply_office_patches: true
|
apply_office_patches: true
|
||||||
|
|
||||||
# Install NuGet v4.6.4+
|
# This is currently required as the command task (strangely) always runs elevated ..
|
||||||
- task: NuGetToolInstaller@1
|
# which makes all the files touched by the above patching step unreadable by following non-command tasks without sudo.
|
||||||
|
# This makes all the files readable.
|
||||||
|
- task: CmdLine@2
|
||||||
|
displayName: chmod
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '>=4.6.4'
|
script: chmod -R +r .
|
||||||
|
|
||||||
|
# Install NuGet
|
||||||
|
- task: CmdLine@2
|
||||||
|
inputs:
|
||||||
|
script: mkdir $(System.DefaultWorkingDirectory)/nuget-bin/ && curl -o $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
|
||||||
|
continueOnError: true
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: "Rename package to react-native"
|
displayName: "Rename package to react-native"
|
||||||
|
@ -130,86 +151,18 @@ jobs:
|
||||||
inputs:
|
inputs:
|
||||||
script: node .ado/bumpOfficeFileVersions.js
|
script: node .ado/bumpOfficeFileVersions.js
|
||||||
|
|
||||||
- task: NuGetCommand@2
|
|
||||||
displayName: NuGet restore
|
|
||||||
inputs:
|
|
||||||
command: restore
|
|
||||||
restoreSolution: ReactAndroid/packages.config
|
|
||||||
feedsToUse: config
|
|
||||||
#vstsFeed: # Required when feedsToUse == Select
|
|
||||||
#includeNuGetOrg: true # Required when feedsToUse == Select
|
|
||||||
nugetConfigPath: ReactAndroid/NuGet.Config
|
|
||||||
#externalFeedCredentials: # Optional
|
|
||||||
#noCache: false
|
|
||||||
#disableParallelProcessing: false
|
|
||||||
restoreDirectory: packages/
|
|
||||||
verbosityRestore: Detailed # Options: quiet, normal, detailed
|
|
||||||
#packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' # Required when command == Push
|
|
||||||
#nuGetFeedType: 'internal' # Required when command == Push# Options: internal, external
|
|
||||||
#publishVstsFeed: # Required when command == Push && NuGetFeedType == Internal
|
|
||||||
#publishPackageMetadata: true # Optional
|
|
||||||
#allowPackageConflicts: # Optional
|
|
||||||
#publishFeedCredentials: # Required when command == Push && NuGetFeedType == External
|
|
||||||
#verbosityPush: 'Detailed' # Options: quiet, normal, detailed
|
|
||||||
#packagesToPack: '**/*.csproj' # Required when command == Pack
|
|
||||||
#configuration: '$(BuildConfiguration)' # Optional
|
|
||||||
#packDestination: '$(Build.ArtifactStagingDirectory)' # Optional
|
|
||||||
#versioningScheme: 'off' # Options: off, byPrereleaseNumber, byEnvVar, byBuildNumber
|
|
||||||
#includeReferencedProjects: false # Optional
|
|
||||||
#versionEnvVar: # Required when versioningScheme == ByEnvVar
|
|
||||||
#majorVersion: '1' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#minorVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#patchVersion: '0' # Required when versioningScheme == ByPrereleaseNumber
|
|
||||||
#packTimezone: 'utc' # Required when versioningScheme == ByPrereleaseNumber# Options: utc, local
|
|
||||||
#includeSymbols: false # Optional
|
|
||||||
#toolPackage: # Optional
|
|
||||||
#buildProperties: # Optional
|
|
||||||
#basePath: # Optional
|
|
||||||
#verbosityPack: 'Detailed' # Options: quiet, normal, detailed
|
|
||||||
#arguments: # Required when command == Custom
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: Setup Build Dependencies
|
|
||||||
inputs:
|
|
||||||
script: .ado\setup_droid_deps.bat
|
|
||||||
|
|
||||||
- task: Gradle@1
|
|
||||||
displayName: gradlew installArchives
|
displayName: gradlew installArchives
|
||||||
env:
|
|
||||||
REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps
|
|
||||||
inputs:
|
inputs:
|
||||||
gradleWrapperFile: gradlew
|
script: ./gradlew installArchives -Pparam="excludeLibs"
|
||||||
# workingDirectory: src\react-native\
|
|
||||||
options: -Pparam="excludeLibs"
|
|
||||||
tasks: installArchives
|
|
||||||
publishJUnitResults: false
|
|
||||||
#testResultsFiles: '**/TEST-*.xml' # Required when publishJUnitResults == True
|
|
||||||
#testRunTitle: # Optional
|
|
||||||
#codeCoverageToolOption: 'None' # Optional. Options: none, cobertura, jaCoCo
|
|
||||||
#codeCoverageClassFilesDirectories: 'build/classes/main/' # Required when codeCoverageToolOption == False
|
|
||||||
#codeCoverageClassFilter: # Optional
|
|
||||||
#codeCoverageFailIfEmpty: false # Optional
|
|
||||||
#javaHomeOption: 'JDKVersion' # Options: jDKVersion, path
|
|
||||||
#jdkVersionOption: 'default' # Optional. Options: default, 1.11, 1.10, 1.9, 1.8, 1.7, 1.6
|
|
||||||
#jdkDirectory: # Required when javaHomeOption == Path
|
|
||||||
#jdkArchitectureOption: 'x64' # Optional. Options: x86, x64
|
|
||||||
#gradleOptions: '-Xmx1024m' # Optional
|
|
||||||
#sonarQubeRunAnalysis: false
|
|
||||||
#sqGradlePluginVersionChoice: 'specify' # Required when sonarQubeRunAnalysis == True# Options: specify, build
|
|
||||||
#sonarQubeGradlePluginVersion: '2.6.1' # Required when sonarQubeRunAnalysis == True && SqGradlePluginVersionChoice == Specify
|
|
||||||
#checkStyleRunAnalysis: false # Optional
|
|
||||||
#findBugsRunAnalysis: false # Optional
|
|
||||||
#pmdRunAnalysis: false # Optional
|
|
||||||
|
|
||||||
- template: templates\prep-android-nuget.yml
|
- template: templates\prep-android-nuget.yml
|
||||||
|
|
||||||
- task: NuGetCommand@2
|
# Very similar to the default pack task .. but appends 'ndk21b' to the nuget pack version
|
||||||
|
- task: CmdLine@2
|
||||||
displayName: 'NuGet pack'
|
displayName: 'NuGet pack'
|
||||||
inputs:
|
inputs:
|
||||||
command: pack
|
script: OUTPUT_DIR=$(Build.StagingDirectory)/final;NDK=ndk`cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | awk '{ print $3}' | awk -F. '{ print $1 }'`; mono $(System.DefaultWorkingDirectory)/nuget-bin/nuget.exe pack $(System.DefaultWorkingDirectory)/ReactAndroid/ReactAndroid.nuspec -OutputDirectory $OUTPUT_DIR -Properties buildNumber=$(buildNumber)-$NDK;commitId=$(Build.SourceVersion)
|
||||||
packagesToPack: 'ReactAndroid/ReactAndroid.nuspec'
|
|
||||||
packDestination: '$(Build.StagingDirectory)\final'
|
|
||||||
buildProperties: buildNumber=$(buildNumber);commitId=$(Build.SourceVersion)
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: 'Npm pack'
|
displayName: 'Npm pack'
|
||||||
|
@ -217,6 +170,7 @@ jobs:
|
||||||
script: node .ado/npmOfficePack.js
|
script: node .ado/npmOfficePack.js
|
||||||
env:
|
env:
|
||||||
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
|
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
|
||||||
|
BUILD_SOURCESDIRECTORY: $(Build.SourcesDirectory)
|
||||||
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
|
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
|
||||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
githubApiToken: $(githubApiToken)
|
githubApiToken: $(githubApiToken)
|
||||||
|
@ -224,5 +178,5 @@ jobs:
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: 'Publish final artifacts'
|
displayName: 'Publish final artifacts'
|
||||||
inputs:
|
inputs:
|
||||||
PathtoPublish: '$(Build.StagingDirectory)\final'
|
PathtoPublish: '$(Build.StagingDirectory)/final'
|
||||||
ArtifactName: 'ReactNative-Final'
|
ArtifactName: 'ReactNative-Final'
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
BUILD_DEPS_DIR=build_deps
|
||||||
|
|
||||||
|
rm -rf $BUILD_DEPS_DIR
|
||||||
|
mkdir $BUILD_DEPS_DIR
|
||||||
|
|
||||||
|
ln -s "$PWD/ReactAndroid/packages/boost.1.68.0.0/lib/native/include/boost" "$BUILD_DEPS_DIR/boost"
|
||||||
|
ln -s "$PWD/double-conversion/double-conversion" "$BUILD_DEPS_DIR/double-conversion"
|
||||||
|
ln -s "$PWD/Folly/" "$BUILD_DEPS_DIR/Folly"
|
||||||
|
ln -s "$PWD/glog/" "$BUILD_DEPS_DIR/glog"
|
|
@ -5,4 +5,4 @@ steps:
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: Apply Android specific patches for Office consumption
|
displayName: Apply Android specific patches for Office consumption
|
||||||
inputs:
|
inputs:
|
||||||
script: node $(System.DefaultWorkingDirectory)/android-patches/bundle/bundle.js patch $(System.DefaultWorkingDirectory) BasicBuild V8Integration RNHostBase Dialog Typeface --patch-store $(System.DefaultWorkingDirectory)/android-patches/patches-0.62.2 --log-folder $(System.DefaultWorkingDirectory)/android-patches/logs --confirm ${{ parameters.apply_office_patches }}
|
script: node $(System.DefaultWorkingDirectory)/android-patches/bundle/bundle.js patch $(System.DefaultWorkingDirectory) BasicBuild --patch-store $(System.DefaultWorkingDirectory)/android-patches/patches-0.61.5 --log-folder $(System.DefaultWorkingDirectory)/android-patches/logs --confirm ${{ parameters.apply_office_patches }}
|
||||||
|
|
|
@ -2,11 +2,14 @@ parameters:
|
||||||
apply_office_patches: ''
|
apply_office_patches: ''
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- script: 'brew update'
|
||||||
|
displayName: 'brew update'
|
||||||
|
|
||||||
- script: 'brew bundle'
|
- script: 'brew bundle'
|
||||||
displayName: 'brew bundle'
|
displayName: 'brew bundle'
|
||||||
|
|
||||||
- script: brew link node@10 --overwrite --force
|
- script: brew link node@12 --overwrite --force
|
||||||
displayName: 'ensure node 10'
|
displayName: 'ensure node 12'
|
||||||
|
|
||||||
- template: apple-xcode-select.yml
|
- template: apple-xcode-select.yml
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,14 @@ steps:
|
||||||
displayName: 'Clean DerivedData'
|
displayName: 'Clean DerivedData'
|
||||||
|
|
||||||
# Install the required components specified in the Brewfile file.
|
# Install the required components specified in the Brewfile file.
|
||||||
|
- script: 'brew update'
|
||||||
|
displayName: 'brew update'
|
||||||
|
|
||||||
- script: 'brew bundle'
|
- script: 'brew bundle'
|
||||||
displayName: 'brew bundle'
|
displayName: 'brew bundle'
|
||||||
|
|
||||||
- script: brew link node@10 --overwrite --force
|
- script: brew link node@12 --overwrite --force
|
||||||
|
displayName: 'ensure node 12'
|
||||||
|
|
||||||
# Task Group: XCode select proper version
|
# Task Group: XCode select proper version
|
||||||
- template: apple-xcode-select.yml
|
- template: apple-xcode-select.yml
|
||||||
|
|
|
@ -70,8 +70,7 @@ steps:
|
||||||
displayName: Publish react-native-macos to verdaccio
|
displayName: Publish react-native-macos to verdaccio
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
cd packages/react-native-macos-init
|
npx beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
|
||||||
npx --no-install beachball publish --branch origin/$(System.PullRequest.TargetBranch) --no-push --registry http://localhost:4873 --yes --access public
|
|
||||||
displayName: Publish react-native-macos-init to verdaccio
|
displayName: Publish react-native-macos-init to verdaccio
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
|
@ -91,12 +90,6 @@ steps:
|
||||||
script: npx react-native-macos-init --version latest --overwrite --prerelease
|
script: npx react-native-macos-init --version latest --overwrite --prerelease
|
||||||
workingDirectory: $(Agent.BuildDirectory)/testcli
|
workingDirectory: $(Agent.BuildDirectory)/testcli
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: Install pods
|
|
||||||
inputs:
|
|
||||||
script: pod install
|
|
||||||
workingDirectory: $(Agent.BuildDirectory)/testcli/macos
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: Run macos
|
displayName: Run macos
|
||||||
inputs:
|
inputs:
|
||||||
|
|
2
Brewfile
2
Brewfile
|
@ -1,2 +1,2 @@
|
||||||
brew "node@10"
|
brew "node@12"
|
||||||
brew "watchman"
|
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';
|
'use strict';
|
||||||
|
|
||||||
|
const Promise = require('../../Promise');
|
||||||
|
const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter');
|
||||||
|
|
||||||
|
import NativeAccessibilityManager from './NativeAccessibilityManager';
|
||||||
|
|
||||||
const warning = require('fbjs/lib/warning');
|
const warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
type ChangeEventName = $Keys<{}>;
|
const CHANGE_EVENT_NAME = {
|
||||||
|
invertColorsChanged: 'invertColorsChanged',
|
||||||
|
reduceMotionChanged: 'reduceMotionChanged',
|
||||||
|
reduceTransparencyChanged: 'reduceTransparencyChanged',
|
||||||
|
screenReaderChanged: 'screenReaderChanged',
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChangeEventName = $Keys<{
|
||||||
|
change: string,
|
||||||
|
invertColorsChanged: string,
|
||||||
|
reduceMotionChanged: string,
|
||||||
|
reduceTransparencyChanged: string,
|
||||||
|
screenReaderChanged: string,
|
||||||
|
}>;
|
||||||
|
|
||||||
|
const _subscriptions = new Map();
|
||||||
const AccessibilityInfo = {
|
const AccessibilityInfo = {
|
||||||
/**
|
/**
|
||||||
* iOS only
|
* iOS only
|
||||||
|
@ -32,31 +51,78 @@ const AccessibilityInfo = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iOS only
|
* Query whether inverted colors are currently enabled.
|
||||||
|
*
|
||||||
|
* Returns a promise which resolves to a boolean.
|
||||||
|
* The result is `true` when invert color is enabled and `false` otherwise.
|
||||||
|
*
|
||||||
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isInvertColorsEnabled
|
||||||
*/
|
*/
|
||||||
isInvertColorsEnabled: function(): Promise<boolean> {
|
isInvertColorsEnabled: function(): Promise<boolean> {
|
||||||
return Promise.resolve(false);
|
return new Promise((resolve, reject) => {
|
||||||
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.getCurrentInvertColorsState(resolve, reject);
|
||||||
|
} else {
|
||||||
|
reject(reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android and iOS only
|
* Query whether reduced motion is currently enabled.
|
||||||
|
*
|
||||||
|
* Returns a promise which resolves to a boolean.
|
||||||
|
* The result is `true` when a reduce motion is enabled and `false` otherwise.
|
||||||
|
*
|
||||||
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceMotionEnabled
|
||||||
*/
|
*/
|
||||||
isReduceMotionEnabled: function(): Promise<boolean> {
|
isReduceMotionEnabled: function(): Promise<boolean> {
|
||||||
return Promise.resolve(false);
|
return new Promise((resolve, reject) => {
|
||||||
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.getCurrentReduceMotionState(resolve, reject);
|
||||||
|
} else {
|
||||||
|
reject(reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iOS only
|
* Query whether reduced transparency is currently enabled.
|
||||||
|
*
|
||||||
|
* Returns a promise which resolves to a boolean.
|
||||||
|
* The result is `true` when a reduce transparency is enabled and `false` otherwise.
|
||||||
|
*
|
||||||
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceTransparencyEnabled
|
||||||
*/
|
*/
|
||||||
isReduceTransparencyEnabled: function(): Promise<boolean> {
|
isReduceTransparencyEnabled: function(): Promise<boolean> {
|
||||||
return Promise.resolve(false);
|
return new Promise((resolve, reject) => {
|
||||||
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.getCurrentReduceTransparencyState(
|
||||||
|
resolve,
|
||||||
|
reject,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
reject(reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android and iOS only
|
* Query whether a screen reader is currently enabled.
|
||||||
|
*
|
||||||
|
* Returns a promise which resolves to a boolean.
|
||||||
|
* The result is `true` when a screen reader is enabled and `false` otherwise.
|
||||||
|
*
|
||||||
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isScreenReaderEnabled
|
||||||
*/
|
*/
|
||||||
isScreenReaderEnabled: function(): Promise<boolean> {
|
isScreenReaderEnabled: function(): Promise<boolean> {
|
||||||
return Promise.resolve(false);
|
return new Promise((resolve, reject) => {
|
||||||
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject);
|
||||||
|
} else {
|
||||||
|
reject(reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,15 +137,38 @@ const AccessibilityInfo = {
|
||||||
addEventListener: function(
|
addEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function,
|
handler: Function,
|
||||||
): void {
|
): Object {
|
||||||
warning(false, 'AccessibilityInfo is not supported on this platform.');
|
let listener;
|
||||||
|
|
||||||
|
if (eventName === 'change') {
|
||||||
|
listener = RCTDeviceEventEmitter.addListener(
|
||||||
|
CHANGE_EVENT_NAME.screenReaderChanged,
|
||||||
|
handler,
|
||||||
|
);
|
||||||
|
} else if (CHANGE_EVENT_NAME[eventName]) {
|
||||||
|
listener = RCTDeviceEventEmitter.addListener(eventName, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
_subscriptions.set(handler, listener);
|
||||||
|
return {
|
||||||
|
remove: AccessibilityInfo.removeEventListener.bind(
|
||||||
|
null,
|
||||||
|
eventName,
|
||||||
|
handler,
|
||||||
|
),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
removeEventListener: function(
|
removeEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function,
|
handler: Function,
|
||||||
): void {
|
): void {
|
||||||
warning(false, 'AccessibilityInfo is not supported on this platform.');
|
const listener = _subscriptions.get(handler);
|
||||||
|
if (!listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listener.remove();
|
||||||
|
_subscriptions.delete(handler);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +177,9 @@ const AccessibilityInfo = {
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus
|
||||||
*/
|
*/
|
||||||
setAccessibilityFocus: function(reactTag: number): void {
|
setAccessibilityFocus: function(reactTag: number): void {
|
||||||
warning(false, 'AccessibilityInfo is not supported on this platform.');
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.setAccessibilityFocus(reactTag);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +188,9 @@ const AccessibilityInfo = {
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility
|
||||||
*/
|
*/
|
||||||
announceForAccessibility: function(announcement: string): void {
|
announceForAccessibility: function(announcement: string): void {
|
||||||
warning(false, 'AccessibilityInfo is not supported on this platform.');
|
if (NativeAccessibilityManager) {
|
||||||
|
NativeAccessibilityManager.announceForAccessibility(announcement);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ const View = require('./View/View');
|
||||||
const invariant = require('invariant');
|
const invariant = require('invariant');
|
||||||
|
|
||||||
import type {PressEvent} from '../Types/CoreEventTypes';
|
import type {PressEvent} from '../Types/CoreEventTypes';
|
||||||
|
import type {FocusEvent, BlurEvent} from './TextInput/TextInput'; // TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
type ButtonProps = $ReadOnly<{|
|
type ButtonProps = $ReadOnly<{|
|
||||||
/**
|
/**
|
||||||
|
@ -100,6 +101,18 @@ type ButtonProps = $ReadOnly<{|
|
||||||
* Used to locate this view in end-to-end tests.
|
* Used to locate this view in end-to-end tests.
|
||||||
*/
|
*/
|
||||||
testID?: ?string,
|
testID?: ?string,
|
||||||
|
|
||||||
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
/**
|
||||||
|
* Handler to be called when the button receives key focus
|
||||||
|
*/
|
||||||
|
onBlur?: ?(e: BlurEvent) => void,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to be called when the button loses key focus
|
||||||
|
*/
|
||||||
|
onFocus?: ?(e: FocusEvent) => void,
|
||||||
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
|}>;
|
|}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +160,8 @@ class Button extends React.Component<ButtonProps> {
|
||||||
nextFocusUp,
|
nextFocusUp,
|
||||||
disabled,
|
disabled,
|
||||||
testID,
|
testID,
|
||||||
|
onFocus, // TODO(OSS Candidate ISS#2710739)
|
||||||
|
onBlur, // TODO(OSS Candidate ISS#2710739)
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const buttonStyles = [styles.button];
|
const buttonStyles = [styles.button];
|
||||||
const textStyles = [styles.text];
|
const textStyles = [styles.text];
|
||||||
|
@ -189,6 +204,8 @@ class Button extends React.Component<ButtonProps> {
|
||||||
testID={testID}
|
testID={testID}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
onFocus={onFocus} // TODO(OSS Candidate ISS#2710739)
|
||||||
|
onBlur={onBlur} // TODO(OSS Candidate ISS#2710739)
|
||||||
touchSoundDisabled={touchSoundDisabled}>
|
touchSoundDisabled={touchSoundDisabled}>
|
||||||
<View style={buttonStyles}>
|
<View style={buttonStyles}>
|
||||||
<Text style={textStyles} disabled={disabled}>
|
<Text style={textStyles} disabled={disabled}>
|
||||||
|
|
|
@ -1129,6 +1129,8 @@ function InternalTextInput(props: Props): React.Node {
|
||||||
<TouchableWithoutFeedback
|
<TouchableWithoutFeedback
|
||||||
onLayout={props.onLayout}
|
onLayout={props.onLayout}
|
||||||
onPress={_onPress}
|
onPress={_onPress}
|
||||||
|
onFocus={_onFocus} // TODO(macOS ISS#2323203)
|
||||||
|
onBlur={_onBlur} // TODO(macOS ISS#2323203)
|
||||||
accessible={props.accessible}
|
accessible={props.accessible}
|
||||||
accessibilityLabel={props.accessibilityLabel}
|
accessibilityLabel={props.accessibilityLabel}
|
||||||
accessibilityRole={props.accessibilityRole}
|
accessibilityRole={props.accessibilityRole}
|
||||||
|
|
|
@ -185,6 +185,8 @@ class TouchableBounce extends React.Component<Props, State> {
|
||||||
onDragEnter={this.props.onDragEnter}
|
onDragEnter={this.props.onDragEnter}
|
||||||
onDragLeave={this.props.onDragLeave}
|
onDragLeave={this.props.onDragLeave}
|
||||||
onDrop={this.props.onDrop}
|
onDrop={this.props.onDrop}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
||||||
ref={this.props.hostRef}
|
ref={this.props.hostRef}
|
||||||
{...eventHandlersWithoutBlurAndFocus}>
|
{...eventHandlersWithoutBlurAndFocus}>
|
||||||
|
|
|
@ -339,6 +339,8 @@ class TouchableHighlight extends React.Component<Props, State> {
|
||||||
onDragEnter={this.props.onDragEnter}
|
onDragEnter={this.props.onDragEnter}
|
||||||
onDragLeave={this.props.onDragLeave}
|
onDragLeave={this.props.onDragLeave}
|
||||||
onDrop={this.props.onDrop}
|
onDrop={this.props.onDrop}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS/win ISS#2323203)
|
draggedTypes={this.props.draggedTypes} // ]TODO(macOS/win ISS#2323203)
|
||||||
nativeID={this.props.nativeID}
|
nativeID={this.props.nativeID}
|
||||||
testID={this.props.testID}
|
testID={this.props.testID}
|
||||||
|
|
|
@ -275,6 +275,8 @@ class TouchableOpacity extends React.Component<Props, State> {
|
||||||
onDragEnter={this.props.onDragEnter}
|
onDragEnter={this.props.onDragEnter}
|
||||||
onDragLeave={this.props.onDragLeave}
|
onDragLeave={this.props.onDragLeave}
|
||||||
onDrop={this.props.onDrop}
|
onDrop={this.props.onDrop}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
onBlur={this.props.onBlur}
|
||||||
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
draggedTypes={this.props.draggedTypes} // ]TODO(macOS ISS#2323203)
|
||||||
ref={this.props.hostRef}
|
ref={this.props.hostRef}
|
||||||
{...eventHandlersWithoutBlurAndFocus}>
|
{...eventHandlersWithoutBlurAndFocus}>
|
||||||
|
|
|
@ -16,22 +16,22 @@ const ReactNativeViewViewConfigMacOS = {
|
||||||
uiViewClassName: 'RCTView',
|
uiViewClassName: 'RCTView',
|
||||||
directEventTypes: {
|
directEventTypes: {
|
||||||
topDoubleClick: {
|
topDoubleClick: {
|
||||||
registrationName: 'topDoubleClick',
|
registrationName: 'onDoubleClick',
|
||||||
},
|
},
|
||||||
topDragEnter: {
|
topDragEnter: {
|
||||||
registrationName: 'topDragEnter',
|
registrationName: 'onDragEnter',
|
||||||
},
|
},
|
||||||
topDragLeave: {
|
topDragLeave: {
|
||||||
registrationName: 'topDragLeave',
|
registrationName: 'onDragLeave',
|
||||||
},
|
},
|
||||||
topDrop: {
|
topDrop: {
|
||||||
registrationName: 'topDrop',
|
registrationName: 'onDrop',
|
||||||
},
|
},
|
||||||
topMouseEnter: {
|
topMouseEnter: {
|
||||||
registrationName: 'topMouseEnter',
|
registrationName: 'onMouseEnter',
|
||||||
},
|
},
|
||||||
topMouseLeave: {
|
topMouseLeave: {
|
||||||
registrationName: 'topMouseLeave',
|
registrationName: 'onMouseLeave',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validAttributes: {
|
validAttributes: {
|
||||||
|
|
|
@ -8,25 +8,19 @@
|
||||||
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
||||||
#if !TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#endif // [TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
|
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
|
||||||
|
UIImageRenderingModeAlwaysOriginal,
|
||||||
|
UIImageRenderingModeAlwaysTemplate,
|
||||||
|
};
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
#import <React/RCTView.h>
|
#import <React/RCTView.h>
|
||||||
#import <React/RCTResizeMode.h>
|
#import <React/RCTResizeMode.h>
|
||||||
|
|
||||||
@class RCTBridge;
|
@class RCTBridge;
|
||||||
@class RCTImageSource;
|
@class RCTImageSource;
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
@interface RCTImageView : RCTView
|
||||||
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
|
|
||||||
UIImageRenderingModeAlwaysOriginal,
|
|
||||||
UIImageRenderingModeAlwaysTemplate,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !TARGET_OS_OSX // ]TODO(macOS ISS#2323203)
|
|
||||||
@interface RCTImageView : UIImageView
|
|
||||||
#else // [TODO(macOS ISS#2323203)
|
|
||||||
@interface RCTImageView : NSImageView
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
|
||||||
|
|
||||||
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
@ -38,15 +32,6 @@ typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
|
||||||
@property (nonatomic, assign) RCTResizeMode resizeMode;
|
@property (nonatomic, assign) RCTResizeMode resizeMode;
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
/**
|
@property (nonatomic, copy) NSColor *tintColor;
|
||||||
* macOS Properties
|
|
||||||
*/
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onDoubleClick;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onClick;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onMouseEnter;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onMouseLeave;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onDragEnter;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onDragLeave;
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onDrop;
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -283,17 +283,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
_imageView.contentMode = UIViewContentModeScaleToFill;
|
_imageView.contentMode = UIViewContentModeScaleToFill;
|
||||||
#else // [TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
self.imageScaling = NSImageScaleAxesIndependently;
|
_imageView.imageScaling = NSImageScaleAxesIndependently;
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
} else {
|
} else {
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
_imageView.contentMode = (UIViewContentMode)resizeMode;
|
_imageView.contentMode = (UIViewContentMode)resizeMode;
|
||||||
#else // [TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
// This relies on having previously resampled the image to a size that exceeds the iamge view.
|
// This relies on having previously resampled the image to a size that exceeds the image view.
|
||||||
if (resizeMode == RCTResizeModeCover) {
|
if (resizeMode == RCTResizeModeCover) {
|
||||||
resizeMode = RCTResizeModeCenter;
|
resizeMode = RCTResizeModeCenter;
|
||||||
}
|
}
|
||||||
self.imageScaling = (NSImageScaling)resizeMode;
|
_imageView.imageScaling = (NSImageScaling)resizeMode;
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,5 +617,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
{
|
{
|
||||||
[self reloadImage];
|
[self reloadImage];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (RCTPlatformView *)reactAccessibilityElement
|
||||||
|
{
|
||||||
|
return (RCTPlatformView *)_imageView.cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSColor *)tintColor
|
||||||
|
{
|
||||||
|
NSColor *tintColor = nil;
|
||||||
|
if (@available(macOS 10.14, *)) {
|
||||||
|
tintColor = _imageView.contentTintColor;
|
||||||
|
}
|
||||||
|
return tintColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setTintColor:(NSColor *)tintColor
|
||||||
|
{
|
||||||
|
if (@available(macOS 10.14, *)) {
|
||||||
|
_imageView.contentTintColor = tintColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -41,7 +41,6 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
|
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
|
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
|
||||||
RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>);
|
RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>);
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
|
||||||
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
|
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
|
||||||
{
|
{
|
||||||
// Default tintColor isn't nil - it's inherited from the superView - but we
|
// Default tintColor isn't nil - it's inherited from the superView - but we
|
||||||
|
@ -50,7 +49,6 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
|
||||||
view.tintColor = [RCTConvert UIColor:json] ?: defaultView.tintColor;
|
view.tintColor = [RCTConvert UIColor:json] ?: defaultView.tintColor;
|
||||||
view.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode;
|
view.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode;
|
||||||
}
|
}
|
||||||
#endif // TODO(macOS ISS#2323203)
|
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request
|
RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request
|
||||||
successBlock:(RCTResponseSenderBlock)successBlock
|
successBlock:(RCTResponseSenderBlock)successBlock
|
||||||
|
|
|
@ -47,6 +47,7 @@ function nativeImageSource(spec: NativeImageSourceSpec): ImageURISource {
|
||||||
android: spec.android,
|
android: spec.android,
|
||||||
default: spec.default,
|
default: spec.default,
|
||||||
ios: spec.ios,
|
ios: spec.ios,
|
||||||
|
macos: spec.macos, // TODO(macOS ISS#2323203)
|
||||||
});
|
});
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|
|
@ -2163,6 +2163,7 @@ class CellRenderer extends React.Component<
|
||||||
return renderItem({
|
return renderItem({
|
||||||
item,
|
item,
|
||||||
index,
|
index,
|
||||||
|
isSelected, // TODO(macOS ISS#2323203)
|
||||||
separators: this._separators,
|
separators: this._separators,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <React/RCTComponent.h>
|
#import <React/RCTComponent.h>
|
||||||
|
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
|
@ -13,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface RCTTextView : RCTUIView // TODO(macOS ISS#3536887)
|
@interface RCTTextView : RCTUIView // TODO(macOS ISS#3536887)
|
||||||
|
|
||||||
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher; // TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
@property (nonatomic, assign) BOOL selectable;
|
@property (nonatomic, assign) BOOL selectable;
|
||||||
|
|
||||||
- (void)setTextStorage:(NSTextStorage *)textStorage
|
- (void)setTextStorage:(NSTextStorage *)textStorage
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#import <React/RCTAssert.h> // TODO(macOS ISS#2323203)
|
#import <React/RCTAssert.h> // TODO(macOS ISS#2323203)
|
||||||
#import <React/RCTUtils.h>
|
#import <React/RCTUtils.h>
|
||||||
#import <React/UIView+React.h>
|
#import <React/UIView+React.h>
|
||||||
|
#import <React/RCTFocusChangeEvent.h> // TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
#import <React/RCTTextShadowView.h>
|
#import <React/RCTTextShadowView.h>
|
||||||
|
|
||||||
|
@ -26,13 +27,26 @@
|
||||||
CAShapeLayer *_highlightLayer;
|
CAShapeLayer *_highlightLayer;
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
UILongPressGestureRecognizer *_longPressGestureRecognizer;
|
UILongPressGestureRecognizer *_longPressGestureRecognizer;
|
||||||
#endif // TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
|
NSString * _accessibilityLabel;
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
|
RCTEventDispatcher *_eventDispatcher; // TODO(OSS Candidate ISS#2710739)
|
||||||
NSArray<RCTUIView *> *_Nullable _descendantViews; // TODO(macOS ISS#3536887)
|
NSArray<RCTUIView *> *_Nullable _descendantViews; // TODO(macOS ISS#3536887)
|
||||||
NSTextStorage *_Nullable _textStorage;
|
NSTextStorage *_Nullable _textStorage;
|
||||||
CGRect _contentFrame;
|
CGRect _contentFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||||
|
{
|
||||||
|
if ((self = [self initWithFrame:CGRectZero])) {
|
||||||
|
_eventDispatcher = eventDispatcher;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if (self = [super initWithFrame:frame]) {
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
@ -49,6 +63,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[self removeAllTextStorageLayoutManagers];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeAllTextStorageLayoutManagers
|
||||||
|
{
|
||||||
|
// On macOS AppKit can throw an uncaught exception
|
||||||
|
// (-[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index ...)
|
||||||
|
// during the dealloc of NSLayoutManager. The _textStorage and its
|
||||||
|
// associated NSLayoutManager dealloc later in an autorelease pool.
|
||||||
|
// Manually removing the layout managers from _textStorage prior to release
|
||||||
|
// works around this issue in AppKit.
|
||||||
|
NSArray<NSLayoutManager *> *managers = [[_textStorage layoutManagers] copy];
|
||||||
|
for (NSLayoutManager *manager in managers) {
|
||||||
|
[_textStorage removeLayoutManager:manager];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)canBecomeKeyView
|
- (BOOL)canBecomeKeyView
|
||||||
{
|
{
|
||||||
// RCTText should not get any keyboard focus unless its `selectable` prop is true
|
// RCTText should not get any keyboard focus unless its `selectable` prop is true
|
||||||
|
@ -118,17 +151,7 @@
|
||||||
descendantViews:(NSArray<RCTUIView *> *)descendantViews // TODO(macOS ISS#3536887)
|
descendantViews:(NSArray<RCTUIView *> *)descendantViews // TODO(macOS ISS#3536887)
|
||||||
{
|
{
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
// On macOS when a large number of flex layouts are being performed, such
|
[self removeAllTextStorageLayoutManagers];
|
||||||
// as when a window is being resized, AppKit can throw an uncaught exception
|
|
||||||
// (-[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index ...)
|
|
||||||
// during the dealloc of NSLayoutManager. The _textStorage and its
|
|
||||||
// associated NSLayoutManager dealloc later in an autorelease pool.
|
|
||||||
// Manually removing the layout manager from _textStorage prior to release
|
|
||||||
// works around this issue in AppKit.
|
|
||||||
NSArray<NSLayoutManager *> *managers = [_textStorage layoutManagers];
|
|
||||||
for (NSLayoutManager *manager in managers) {
|
|
||||||
[_textStorage removeLayoutManager:manager];
|
|
||||||
}
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
_textStorage = textStorage;
|
_textStorage = textStorage;
|
||||||
|
@ -273,6 +296,28 @@
|
||||||
|
|
||||||
#pragma mark - Accessibility
|
#pragma mark - Accessibility
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
|
// This code is here to cover for a mismatch in the what accessibilityLabels and accessibilityValues mean in iOS versus macOS.
|
||||||
|
// In macOS a text element will always read its accessibilityValue, but will only read it's accessibilityLabel if it's value is set.
|
||||||
|
// In iOS a text element will only read it's accessibilityValue if it has no accessibilityLabel, and will always read its accessibilityLabel.
|
||||||
|
// This code replicates the expected behavior in macOS by:
|
||||||
|
// 1) Setting the accessibilityValue = the react-native accessibilityLabel prop if one exists and setting it equal to the text's contents otherwise.
|
||||||
|
// 2) Making sure that its accessibilityLabel is always nil, so that it doesn't read out the label twice.
|
||||||
|
|
||||||
|
- (void)setAccessibilityLabel:(NSString *)label
|
||||||
|
{
|
||||||
|
_accessibilityLabel = [label copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)accessibilityValue
|
||||||
|
{
|
||||||
|
if (_accessibilityLabel) {
|
||||||
|
return _accessibilityLabel;
|
||||||
|
}
|
||||||
|
return _textStorage.string;
|
||||||
|
}
|
||||||
|
#else // ]TODO(macOS ISS#2323203)
|
||||||
- (NSString *)accessibilityLabel
|
- (NSString *)accessibilityLabel
|
||||||
{
|
{
|
||||||
NSString *superAccessibilityLabel = [super accessibilityLabel];
|
NSString *superAccessibilityLabel = [super accessibilityLabel];
|
||||||
|
@ -281,6 +326,7 @@
|
||||||
}
|
}
|
||||||
return _textStorage.string;
|
return _textStorage.string;
|
||||||
}
|
}
|
||||||
|
#endif // TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
#pragma mark - Context Menu
|
#pragma mark - Context Menu
|
||||||
|
|
||||||
|
@ -349,6 +395,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)becomeFirstResponder
|
||||||
|
{
|
||||||
|
if (![super becomeFirstResponder]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've gained focus, notify listeners
|
||||||
|
[_eventDispatcher sendEvent:[RCTFocusChangeEvent focusEventWithReactTag:self.reactTag]];
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)resignFirstResponder
|
||||||
|
{
|
||||||
|
if (![super resignFirstResponder]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've lost focus, notify listeners
|
||||||
|
[_eventDispatcher sendEvent:[RCTFocusChangeEvent blurEventWithReactTag:self.reactTag]];
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
- (BOOL)canBecomeFirstResponder
|
- (BOOL)canBecomeFirstResponder
|
||||||
|
|
|
@ -54,7 +54,7 @@ RCT_EXPORT_VIEW_PROPERTY(selectable, BOOL)
|
||||||
|
|
||||||
- (RCTUIView *)view // TODO(macOS ISS#3536887)
|
- (RCTUIView *)view // TODO(macOS ISS#3536887)
|
||||||
{
|
{
|
||||||
return [RCTTextView new];
|
return [[RCTTextView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RCTShadowView *)shadowView
|
- (RCTShadowView *)shadowView
|
||||||
|
|
|
@ -191,6 +191,9 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
||||||
// enter/return
|
// enter/return
|
||||||
if (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:)) {
|
if (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:)) {
|
||||||
[self textFieldDidEndEditingOnExit];
|
[self textFieldDidEndEditingOnExit];
|
||||||
|
if ([[_backedTextInputView textInputDelegate] textInputShouldReturn]) {
|
||||||
|
[[_backedTextInputView window] makeFirstResponder:nil];
|
||||||
|
}
|
||||||
commandHandled = YES;
|
commandHandled = YES;
|
||||||
//backspace
|
//backspace
|
||||||
} else if (commandSelector == @selector(deleteBackward:)) {
|
} else if (commandSelector == @selector(deleteBackward:)) {
|
||||||
|
@ -298,18 +301,16 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
||||||
|
|
||||||
- (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
- (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
||||||
{
|
{
|
||||||
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
// Custom implementation of `textInputShouldReturn` and `textInputDidReturn` pair for `UITextView`.
|
// Custom implementation of `textInputShouldReturn` and `textInputDidReturn` pair for `UITextView`.
|
||||||
if (!_backedTextInputView.textWasPasted && [text isEqualToString:@"\n"]) {
|
if (!_backedTextInputView.textWasPasted && [text isEqualToString:@"\n"]) {
|
||||||
if ([_backedTextInputView.textInputDelegate textInputShouldReturn]) {
|
if ([_backedTextInputView.textInputDelegate textInputShouldReturn]) {
|
||||||
[_backedTextInputView.textInputDelegate textInputDidReturn];
|
[_backedTextInputView.textInputDelegate textInputDidReturn];
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
|
||||||
[_backedTextInputView endEditing:NO];
|
[_backedTextInputView endEditing:NO];
|
||||||
#else // [TODO(macOS ISS#2323203)
|
|
||||||
[[_backedTextInputView window] endEditingFor:nil];
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
NSString *newText =
|
NSString *newText =
|
||||||
[_backedTextInputView.textInputDelegate textInputShouldChangeText:text inRange:range];
|
[_backedTextInputView.textInputDelegate textInputShouldChangeText:text inRange:range];
|
||||||
|
@ -399,9 +400,11 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
||||||
BOOL commandHandled = NO;
|
BOOL commandHandled = NO;
|
||||||
id<RCTBackedTextInputDelegate> textInputDelegate = [_backedTextInputView textInputDelegate];
|
id<RCTBackedTextInputDelegate> textInputDelegate = [_backedTextInputView textInputDelegate];
|
||||||
// enter/return
|
// enter/return
|
||||||
if (textInputDelegate.textInputShouldReturn && (commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) {
|
if ((commandSelector == @selector(insertNewline:) || commandSelector == @selector(insertNewlineIgnoringFieldEditor:))) {
|
||||||
[_backedTextInputView.window makeFirstResponder:nil];
|
if (textInputDelegate.textInputShouldReturn) {
|
||||||
commandHandled = YES;
|
[_backedTextInputView.window makeFirstResponder:nil];
|
||||||
|
commandHandled = YES;
|
||||||
|
}
|
||||||
//backspace
|
//backspace
|
||||||
} else if (commandSelector == @selector(deleteBackward:)) {
|
} else if (commandSelector == @selector(deleteBackward:)) {
|
||||||
commandHandled = textInputDelegate != nil && ![textInputDelegate textInputShouldHandleDeleteBackward:_backedTextInputView];
|
commandHandled = textInputDelegate != nil && ![textInputDelegate textInputShouldHandleDeleteBackward:_backedTextInputView];
|
||||||
|
|
|
@ -348,7 +348,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
|
|
||||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
||||||
reactTag:self.reactTag
|
reactTag:self.reactTag
|
||||||
text:self.backedTextInputView.attributedText.string
|
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||||
key:nil
|
key:nil
|
||||||
eventCount:_nativeEventCount];
|
eventCount:_nativeEventCount];
|
||||||
}
|
}
|
||||||
|
@ -362,13 +362,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
{
|
{
|
||||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
|
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
|
||||||
reactTag:self.reactTag
|
reactTag:self.reactTag
|
||||||
text:self.backedTextInputView.attributedText.string
|
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||||
key:nil
|
key:nil
|
||||||
eventCount:_nativeEventCount];
|
eventCount:_nativeEventCount];
|
||||||
|
|
||||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
||||||
reactTag:self.reactTag
|
reactTag:self.reactTag
|
||||||
text:self.backedTextInputView.attributedText.string
|
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||||
key:nil
|
key:nil
|
||||||
eventCount:_nativeEventCount];
|
eventCount:_nativeEventCount];
|
||||||
}
|
}
|
||||||
|
@ -380,11 +380,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
// `onSubmitEditing` is called when "Submit" button
|
// `onSubmitEditing` is called when "Submit" button
|
||||||
// (the blue key on onscreen keyboard) did pressed
|
// (the blue key on onscreen keyboard) did pressed
|
||||||
// (no connection to any specific "submitting" process).
|
// (no connection to any specific "submitting" process).
|
||||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
|
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
|
||||||
reactTag:self.reactTag
|
if (_blurOnSubmit) {
|
||||||
text:self.backedTextInputView.attributedText.string
|
#endif // ]TODO(macOS Candidate ISS#2710739)
|
||||||
key:nil
|
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
|
||||||
eventCount:_nativeEventCount];
|
reactTag:self.reactTag
|
||||||
|
text:[self.backedTextInputView.attributedText.string copy] // [TODO(macOS Candidate ISS#2710739)
|
||||||
|
key:nil
|
||||||
|
eventCount:_nativeEventCount];
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS Candidate ISS#2710739)
|
||||||
|
|
||||||
return _blurOnSubmit;
|
return _blurOnSubmit;
|
||||||
}
|
}
|
||||||
|
@ -442,7 +448,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *previousText = backedTextInputView.attributedText.string ?: @"";
|
NSString *previousText = [backedTextInputView.attributedText.string copy] ?: @""; // TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
if (range.location + range.length > backedTextInputView.attributedText.string.length) {
|
if (range.location + range.length > backedTextInputView.attributedText.string.length) {
|
||||||
_predictedText = backedTextInputView.attributedText.string;
|
_predictedText = backedTextInputView.attributedText.string;
|
||||||
|
@ -489,7 +495,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||||
|
|
||||||
if (_onChange) {
|
if (_onChange) {
|
||||||
_onChange(@{
|
_onChange(@{
|
||||||
@"text": self.attributedText.string,
|
@"text": [self.attributedText.string copy], // [TODO(macOS Candidate ISS#2710739)
|
||||||
@"target": self.reactTag,
|
@"target": self.reactTag,
|
||||||
@"eventCount": @(_nativeEventCount),
|
@"eventCount": @(_nativeEventCount),
|
||||||
});
|
});
|
||||||
|
|
|
@ -37,9 +37,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
@property (assign, getter=isEditable) BOOL editable;
|
@property (assign, getter=isEditable) BOOL editable;
|
||||||
#endif
|
#endif
|
||||||
#if TARGET_OS_OSX
|
#if TARGET_OS_OSX
|
||||||
@property (nonatomic, assign) NSTextAlignment textAlignment;
|
|
||||||
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
|
|
||||||
@property (nonatomic, copy, nullable) NSString *text;
|
@property (nonatomic, copy, nullable) NSString *text;
|
||||||
|
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
|
||||||
|
@property (nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
|
||||||
|
@property (nonatomic, assign) NSTextAlignment textAlignment;
|
||||||
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
|
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
|
||||||
@property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled;
|
@property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled;
|
||||||
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor;
|
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor;
|
||||||
|
|
|
@ -83,15 +83,9 @@
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
@dynamic delegate;
|
@dynamic delegate;
|
||||||
|
|
||||||
static UIFont *defaultPlaceholderFont()
|
|
||||||
{
|
|
||||||
return [UIFont systemFontOfSize:17];
|
|
||||||
}
|
|
||||||
|
|
||||||
static RCTUIColor *defaultPlaceholderTextColor()
|
static RCTUIColor *defaultPlaceholderTextColor()
|
||||||
{
|
{
|
||||||
// Default placeholder color from UITextField.
|
return [NSColor placeholderTextColor];
|
||||||
return [RCTUIColor colorWithRed:0 green:0 blue:0.0980392 alpha:0.22];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
@ -106,8 +100,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
||||||
object:self];
|
object:self];
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
self.bordered = NO;
|
[self setBordered:NO];
|
||||||
self.accessibilityRole = NSAccessibilityTextFieldRole;
|
[self setAllowsEditingTextAttributes:YES];
|
||||||
|
[self setAccessibilityRole:NSAccessibilityTextFieldRole];
|
||||||
|
[self setBackgroundColor:[NSColor clearColor]];
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
_textInputDelegateAdapter = [[RCTBackedTextFieldDelegateAdapter alloc] initWithTextField:self];
|
_textInputDelegateAdapter = [[RCTBackedTextFieldDelegateAdapter alloc] initWithTextField:self];
|
||||||
|
@ -119,6 +115,10 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
||||||
- (void)_textDidChange
|
- (void)_textDidChange
|
||||||
{
|
{
|
||||||
_textWasPasted = NO;
|
_textWasPasted = NO;
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
[self setAttributedText:[[NSAttributedString alloc] initWithString:[self text]
|
||||||
|
attributes:[self defaultTextAttributes]]];
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Accessibility
|
#pragma mark - Accessibility
|
||||||
|
@ -243,6 +243,11 @@ static RCTUIColor *defaultPlaceholderTextColor()
|
||||||
[super setDefaultTextAttributes:defaultTextAttributes];
|
[super setDefaultTextAttributes:defaultTextAttributes];
|
||||||
#endif // TODO(macOS ISS#2323203)
|
#endif // TODO(macOS ISS#2323203)
|
||||||
[self _updatePlaceholder];
|
[self _updatePlaceholder];
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
[self setAttributedText:[[NSAttributedString alloc] initWithString:[self text]
|
||||||
|
attributes:[self defaultTextAttributes]]];
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
|
- (NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
|
||||||
|
|
|
@ -173,6 +173,13 @@ post_install do |installer|
|
||||||
puts ' adding arm64e to ' + config.name
|
puts ' adding arm64e to ' + config.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# TODO(macOS ISS#2323203): the internal Microsoft build pipeline needs macOS arm64 slices
|
||||||
|
if target.platform_name == :osx
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
(config.build_settings['ARCHS'] ||= ['$(ARCHS_STANDARD)']) << 'arm64'
|
||||||
|
puts ' adding arm64 to ' + config.name
|
||||||
|
end
|
||||||
|
end
|
||||||
# ]TODO(macOS ISS#2323203)
|
# ]TODO(macOS ISS#2323203)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -395,7 +395,7 @@ DEPENDENCIES:
|
||||||
- Yoga (from `../ReactCommon/yoga`)
|
- Yoga (from `../ReactCommon/yoga`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
https://cdn.cocoapods.org/:
|
trunk:
|
||||||
- CocoaAsyncSocket
|
- CocoaAsyncSocket
|
||||||
- CocoaLibEvent
|
- CocoaLibEvent
|
||||||
- Flipper
|
- Flipper
|
||||||
|
@ -501,7 +501,7 @@ SPEC CHECKSUMS:
|
||||||
RCTTypeSafety: 4e66a550e8f4d69f045dc4180cb8cfea0b982ed6
|
RCTTypeSafety: 4e66a550e8f4d69f045dc4180cb8cfea0b982ed6
|
||||||
React: bacecd5320c8bb453aa396179b93061ebd9d34bf
|
React: bacecd5320c8bb453aa396179b93061ebd9d34bf
|
||||||
React-ART: 2f0eb928d7bc51e6262da595955b0e8fcf6c0a9e
|
React-ART: 2f0eb928d7bc51e6262da595955b0e8fcf6c0a9e
|
||||||
React-Core: c80d3cb695659d2b582b7068a2f451c90ac0e744
|
React-Core: 5d95f89aa9cc03ef38e0bac9225ab0084a89f5f8
|
||||||
React-CoreModules: 0d5bcd5a3cfd73e5ed5f9d5e7f8f2a733bf62be3
|
React-CoreModules: 0d5bcd5a3cfd73e5ed5f9d5e7f8f2a733bf62be3
|
||||||
React-cxxreact: b7826b0513bdb89e2ddb6b185a9f822069e7c540
|
React-cxxreact: b7826b0513bdb89e2ddb6b185a9f822069e7c540
|
||||||
React-jsi: e6b9022a422abf5add4598413f9d8bddc5c98fec
|
React-jsi: e6b9022a422abf5add4598413f9d8bddc5c98fec
|
||||||
|
@ -522,6 +522,6 @@ SPEC CHECKSUMS:
|
||||||
Yoga: 3ed3c35bb7c41fa8f5056b767bc048539f6526ad
|
Yoga: 3ed3c35bb7c41fa8f5056b767bc048539f6526ad
|
||||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3cfdde26e08d043498daa8442c611eb479f77fb0
|
PODFILE CHECKSUM: dba3e89372dafdb3103dc904bc23601aaf239f68
|
||||||
|
|
||||||
COCOAPODS: 1.9.3
|
COCOAPODS: 1.9.3
|
||||||
|
|
|
@ -40,9 +40,7 @@
|
||||||
RCT_TEST(ViewExample)
|
RCT_TEST(ViewExample)
|
||||||
RCT_TEST(LayoutExample)
|
RCT_TEST(LayoutExample)
|
||||||
RCT_TEST(ScrollViewExample)
|
RCT_TEST(ScrollViewExample)
|
||||||
#if !TARGET_OS_OSX // Reason: Intermittent failure: crash deallocating NSTextStorage of a TextView: tracked by https://github.com/microsoft/react-native-macos/issues/357
|
|
||||||
RCT_TEST(TextExample)
|
RCT_TEST(TextExample)
|
||||||
#endif
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
// No switch available on tvOS
|
// No switch available on tvOS
|
||||||
RCT_TEST(SwitchExample)
|
RCT_TEST(SwitchExample)
|
||||||
|
|
|
@ -134,6 +134,15 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
descriptionText: {
|
descriptionText: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
...Platform.select({
|
||||||
|
macos: {
|
||||||
|
color: {semantic: 'secondaryLabelColor'},
|
||||||
|
},
|
||||||
|
ios: {
|
||||||
|
color: {semantic: 'secondaryLabelColor'},
|
||||||
|
},
|
||||||
|
default: undefined,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
margin: 10,
|
margin: 10,
|
||||||
|
|
|
@ -23,10 +23,19 @@ class RNTesterExampleContainer extends React.Component {
|
||||||
const {description, platform} = example;
|
const {description, platform} = example;
|
||||||
let {title} = example;
|
let {title} = example;
|
||||||
if (platform) {
|
if (platform) {
|
||||||
if (Platform.OS !== platform) {
|
// [TODO(macOS ISS#2323203)
|
||||||
return null;
|
if (platform instanceof Array) {
|
||||||
}
|
if (!platform.includes(Platform.OS)) {
|
||||||
title += ' (' + platform + ' only)';
|
return null;
|
||||||
|
}
|
||||||
|
title += ' (' + platform.join() + ' only)';
|
||||||
|
} else {
|
||||||
|
// ]TODO(macOS ISS#2323203)
|
||||||
|
if (Platform.OS !== platform) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
title += ' (' + platform + ' only)';
|
||||||
|
} // TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<RNTesterBlock key={i} title={title} description={description}>
|
<RNTesterBlock key={i} title={title} description={description}>
|
||||||
|
|
|
@ -733,7 +733,101 @@ class ScreenReaderStatusExample extends React.Component<{}> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
class DisplayOptionsStatusExample extends React.Component<{}> {
|
||||||
|
state = {};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
AccessibilityInfo.addEventListener(
|
||||||
|
'invertColorsChanged',
|
||||||
|
this._handleInvertColorsToggled,
|
||||||
|
);
|
||||||
|
AccessibilityInfo.isInvertColorsEnabled().done(isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
invertColorsEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AccessibilityInfo.addEventListener(
|
||||||
|
'reduceMotionChanged',
|
||||||
|
this._handleReduceMotionToggled,
|
||||||
|
);
|
||||||
|
AccessibilityInfo.isReduceMotionEnabled().done(isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
reduceMotionEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AccessibilityInfo.addEventListener(
|
||||||
|
'reduceTransparencyChanged',
|
||||||
|
this._handleReduceTransparencyToggled,
|
||||||
|
);
|
||||||
|
AccessibilityInfo.isReduceTransparencyEnabled().done(isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
reduceTransparencyEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
AccessibilityInfo.removeEventListener(
|
||||||
|
'invertColorsChanged',
|
||||||
|
this._handleInvertColorsToggled,
|
||||||
|
);
|
||||||
|
AccessibilityInfo.removeEventListener(
|
||||||
|
'reduceMotionChanged',
|
||||||
|
this._handleReduceMotionToggled,
|
||||||
|
);
|
||||||
|
AccessibilityInfo.removeEventListener(
|
||||||
|
'reduceTransparencyChanged',
|
||||||
|
this._handleReduceTransparencyToggled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleInvertColorsToggled = isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
invertColorsEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleReduceMotionToggled = isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
reduceMotionEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleReduceTransparencyToggled = isEnabled => {
|
||||||
|
this.setState({
|
||||||
|
reduceTransparencyEnabled: isEnabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<View>
|
||||||
|
<Text>
|
||||||
|
Invert colors is{' '}
|
||||||
|
{this.state.invertColorsEnabled ? 'enabled' : 'disabled'}.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Text>
|
||||||
|
Reduce motion is{' '}
|
||||||
|
{this.state.reduceMotionEnabled ? 'enabled' : 'disabled'}.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Text>
|
||||||
|
Reduce transparency is{' '}
|
||||||
|
{this.state.reduceTransparencyEnabled ? 'enabled' : 'disabled'}.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
class AnnounceForAccessibility extends React.Component<{}> {
|
class AnnounceForAccessibility extends React.Component<{}> {
|
||||||
_handleOnPress = () =>
|
_handleOnPress = () =>
|
||||||
AccessibilityInfo.announceForAccessibility('Announcement Test');
|
AccessibilityInfo.announceForAccessibility('Announcement Test');
|
||||||
|
@ -750,6 +844,26 @@ class AnnounceForAccessibility extends React.Component<{}> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SetAccessibilityFocus extends React.Component<{}> {
|
||||||
|
_handleOnPress = () => {
|
||||||
|
if (findNodeHandle(this.focusRef.current)) {
|
||||||
|
const reactTag = findNodeHandle(this.focusRef.current);
|
||||||
|
AccessibilityInfo.setAccessibilityFocus(reactTag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
render() {
|
||||||
|
this.focusRef = React.createRef();
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Button onPress={this._handleOnPress} title="Set Accessibility Focus" />
|
||||||
|
<Text ref={this.focusRef} accessible={true}>
|
||||||
|
Move focus here on button press.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.title = 'Accessibility';
|
exports.title = 'Accessibility';
|
||||||
exports.description = 'Examples of using Accessibility APIs.';
|
exports.description = 'Examples of using Accessibility APIs.';
|
||||||
exports.examples = [
|
exports.examples = [
|
||||||
|
@ -783,10 +897,24 @@ exports.examples = [
|
||||||
return <ScreenReaderStatusExample />;
|
return <ScreenReaderStatusExample />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
{
|
||||||
|
title: 'Check if the display options are enabled',
|
||||||
|
render(): React.Element<typeof DisplayOptionsStatusExample> {
|
||||||
|
return <DisplayOptionsStatusExample />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
{
|
{
|
||||||
title: 'Check if the screen reader announces',
|
title: 'Check if the screen reader announces',
|
||||||
render(): React.Element<typeof AnnounceForAccessibility> {
|
render(): React.Element<typeof AnnounceForAccessibility> {
|
||||||
return <AnnounceForAccessibility />;
|
return <AnnounceForAccessibility />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Check if the screen reader focus sets ',
|
||||||
|
render(): React.Element<typeof SetAccessibilityFocus> {
|
||||||
|
return <SetAccessibilityFocus />;
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var ReactNative = require('react-native');
|
var ReactNative = require('react-native');
|
||||||
import {Platform} from 'react-native';
|
import {Platform} from 'react-native';
|
||||||
var {StyleSheet, Text, View, TextInput} = ReactNative;
|
var {Button, StyleSheet, Text, View, TextInput} = ReactNative;
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
eventStream: string,
|
eventStream: string,
|
||||||
|
@ -110,33 +110,103 @@ class FocusEventExample extends React.Component<{}, State> {
|
||||||
|
|
||||||
{// Only test View on MacOS, since canBecomeFirstResponder is false on all iOS, therefore we can't focus
|
{// Only test View on MacOS, since canBecomeFirstResponder is false on all iOS, therefore we can't focus
|
||||||
Platform.OS === 'macos' ? (
|
Platform.OS === 'macos' ? (
|
||||||
<View
|
<View>
|
||||||
onFocus={() => {
|
|
||||||
this.setState(prevState => ({
|
|
||||||
eventStream:
|
|
||||||
prevState.eventStream + '\nNested View Parent Focus',
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
onBlur={() => {
|
|
||||||
this.setState(prevState => ({
|
|
||||||
eventStream:
|
|
||||||
prevState.eventStream + '\nNested View Parent Blur',
|
|
||||||
}));
|
|
||||||
}}>
|
|
||||||
<View
|
<View
|
||||||
acceptsKeyboardFocus={true}
|
|
||||||
enableFocusRing={true}
|
|
||||||
onFocus={() => {
|
onFocus={() => {
|
||||||
this.setState(prevState => ({
|
this.setState(prevState => ({
|
||||||
eventStream: prevState.eventStream + '\nNested View Focus',
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Button Focus',
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
this.setState(prevState => ({
|
this.setState(prevState => ({
|
||||||
eventStream: prevState.eventStream + '\nNested View Blur',
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Button Blur',
|
||||||
}));
|
}));
|
||||||
}}>
|
}}>
|
||||||
<Text>Nested Focusable View</Text>
|
<View>
|
||||||
|
<Button
|
||||||
|
title="Button whose ancestor has onFocus/onBlur"
|
||||||
|
onPress={() => {}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
onFocus={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Button Focus',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Button Blur',
|
||||||
|
}));
|
||||||
|
}}>
|
||||||
|
<View>
|
||||||
|
<Button
|
||||||
|
title="Button with onFocus/onBlur and ancestor has onFocus/onBlur"
|
||||||
|
onPress={() => {}}
|
||||||
|
onFocus={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream: prevState.eventStream + '\nButton Focus',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream: prevState.eventStream + '\nButton Blur',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
onFocus={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Text Focus',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nDescendent Text Blur',
|
||||||
|
}));
|
||||||
|
}}>
|
||||||
|
<View>
|
||||||
|
<Text selectable={true}>Selectable text</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
onFocus={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nNested View Parent Focus',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nNested View Parent Blur',
|
||||||
|
}));
|
||||||
|
}}>
|
||||||
|
<View
|
||||||
|
acceptsKeyboardFocus={true}
|
||||||
|
enableFocusRing={true}
|
||||||
|
onFocus={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream:
|
||||||
|
prevState.eventStream + '\nNested View Focus',
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
eventStream: prevState.eventStream + '\nNested View Blur',
|
||||||
|
}));
|
||||||
|
}}>
|
||||||
|
<Text>Nested Focusable View</Text>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -15,6 +15,7 @@ const React = require('react');
|
||||||
const {
|
const {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Image,
|
Image,
|
||||||
|
Platform, // TODO(OSS Candidate ISS#2710739)
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
View,
|
View,
|
||||||
|
@ -26,7 +27,7 @@ const base64Icon =
|
||||||
|
|
||||||
const ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
const ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
||||||
const IMAGE_PREFETCH_URL =
|
const IMAGE_PREFETCH_URL =
|
||||||
'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now();
|
'https://www.facebook.com/favicon.ico?r=1&t=' + Date.now();
|
||||||
const prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
const prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
||||||
|
|
||||||
type ImageSource = $ReadOnly<{|
|
type ImageSource = $ReadOnly<{|
|
||||||
|
@ -312,18 +313,17 @@ class MultipleSourcesExample extends React.Component<
|
||||||
style={{flex: 1}}
|
style={{flex: 1}}
|
||||||
source={[
|
source={[
|
||||||
{
|
{
|
||||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
uri: 'https://www.facebook.com/favicon.ico',
|
||||||
width: 38,
|
width: 38,
|
||||||
height: 38,
|
height: 38,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
uri: 'https://www.facebook.com/favicon.ico',
|
||||||
width: 76,
|
width: 76,
|
||||||
height: 76,
|
height: 76,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
uri:
|
uri: 'https://www.facebook.com/ads/pics/successstories.png',
|
||||||
'https://facebook.github.io/react-native/img/opengraph.png',
|
|
||||||
width: 400,
|
width: 400,
|
||||||
height: 400,
|
height: 400,
|
||||||
},
|
},
|
||||||
|
@ -336,10 +336,10 @@ class MultipleSourcesExample extends React.Component<
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullImage = {
|
const fullImage = {
|
||||||
uri: 'https://facebook.github.io/react-native/img/opengraph.png',
|
uri: 'https://www.facebook.com/ads/pics/successstories.png',
|
||||||
};
|
};
|
||||||
const smallImage = {
|
const smallImage = {
|
||||||
uri: 'https://facebook.github.io/react-native/img/favicon.png',
|
uri: 'https://www.facebook.com/favicon.ico',
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -448,9 +448,7 @@ exports.examples = [
|
||||||
return (
|
return (
|
||||||
<NetworkImageCallbackExample
|
<NetworkImageCallbackExample
|
||||||
source={{
|
source={{
|
||||||
uri:
|
uri: 'https://www.facebook.com/favicon.ico?r=1&t=' + Date.now(),
|
||||||
'http://origami.design/public/images/bird-logo.png?r=1&t=' +
|
|
||||||
Date.now(),
|
|
||||||
}}
|
}}
|
||||||
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
|
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
|
||||||
/>
|
/>
|
||||||
|
@ -463,7 +461,7 @@ exports.examples = [
|
||||||
return (
|
return (
|
||||||
<NetworkImageExample
|
<NetworkImageExample
|
||||||
source={{
|
source={{
|
||||||
uri: 'https://TYPO_ERROR_facebook.github.io/react/logo-og.png',
|
uri: 'https://www.facebook.com/favicon_TYPO.ico',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -476,7 +474,7 @@ exports.examples = [
|
||||||
return (
|
return (
|
||||||
<NetworkImageExample
|
<NetworkImageExample
|
||||||
source={{
|
source={{
|
||||||
uri: 'http://origami.design/public/images/bird-logo.png?r=1',
|
uri: 'https://www.facebook.com/favicon.ico?r=1',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -491,7 +489,7 @@ exports.examples = [
|
||||||
<Image
|
<Image
|
||||||
defaultSource={require('../../assets/bunny.png')}
|
defaultSource={require('../../assets/bunny.png')}
|
||||||
source={{
|
source={{
|
||||||
uri: 'https://facebook.github.io/origami/public/images/birds.jpg',
|
uri: 'https://origami.design/public/images/bird-logo.png',
|
||||||
}}
|
}}
|
||||||
style={styles.base}
|
style={styles.base}
|
||||||
/>
|
/>
|
||||||
|
@ -888,7 +886,8 @@ exports.examples = [
|
||||||
<Image
|
<Image
|
||||||
source={{
|
source={{
|
||||||
uri: 'ImageInBundle',
|
uri: 'ImageInBundle',
|
||||||
bundle: 'RNTesterBundle',
|
bundle:
|
||||||
|
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
}}
|
}}
|
||||||
|
@ -897,7 +896,8 @@ exports.examples = [
|
||||||
<Image
|
<Image
|
||||||
source={{
|
source={{
|
||||||
uri: 'ImageInAssetCatalog',
|
uri: 'ImageInAssetCatalog',
|
||||||
bundle: 'RNTesterBundle',
|
bundle:
|
||||||
|
'RNTesterBundle' + (Platform.OS === 'macos' ? '-macOS' : ''),
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
}}
|
}}
|
||||||
|
@ -906,7 +906,7 @@ exports.examples = [
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
platform: 'ios',
|
platform: ['ios', 'macos'], // TODO(OSS Candidate ISS#2710739)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blur Radius',
|
title: 'Blur Radius',
|
||||||
|
|
|
@ -430,6 +430,113 @@ class TouchableDisabled extends React.Component<{...}> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TODO(macOS ISS#2323203)
|
||||||
|
class TouchableHover extends React.Component<{}, $FlowFixMeState> {
|
||||||
|
state = {
|
||||||
|
hoverOver: false,
|
||||||
|
};
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<TouchableOpacity
|
||||||
|
onMouseEnter={this._handlePress}
|
||||||
|
onMouseLeave={this._handlePress}
|
||||||
|
style={[styles.row, styles.block]}>
|
||||||
|
<Text style={this.state.hoverOver ? {color: 'red'} : {color: 'blue'}}>
|
||||||
|
Touchable Opacity with mouse enter/exit events
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableHighlight
|
||||||
|
onMouseEnter={() => console.log('Mouse Enter')}
|
||||||
|
onMouseLeave={() => console.log('Mouse Exit')}
|
||||||
|
activeOpacity={1}
|
||||||
|
disabled={true}
|
||||||
|
underlayColor="rgb(210, 230, 255)"
|
||||||
|
style={[styles.row, styles.block]}
|
||||||
|
onPress={() => console.log('custom THW text - highlight')}>
|
||||||
|
<Text style={styles.disabledButton}>
|
||||||
|
Touchable Highlight with mouse event logging
|
||||||
|
</Text>
|
||||||
|
</TouchableHighlight>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_handlePress = () => {
|
||||||
|
this.setState({hoverOver: !this.state.hoverOver});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class TouchableMouseEvents extends React.Component<{}, $FlowFixMeState> {
|
||||||
|
state = {
|
||||||
|
eventLog: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View testID="touchable_feedback_mouse_events">
|
||||||
|
<View style={[styles.row, {justifyContent: 'center'}]}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.wrapper}
|
||||||
|
testID="touchable_feedback_mouse_events_button"
|
||||||
|
accessibilityLabel="touchable feedback mouse events"
|
||||||
|
onPressIn={e => this._appendEvent('MouseIn', e.nativeEvent)}
|
||||||
|
onPressOut={e => this._appendEvent('MouseOut', e.nativeEvent)}
|
||||||
|
draggedTypes={'fileUrl'}
|
||||||
|
onDragEnter={e =>
|
||||||
|
this._appendEvent('MouseDragEnter', e.nativeEvent)
|
||||||
|
}
|
||||||
|
onDragLeave={e =>
|
||||||
|
this._appendEvent('MouseDragLeave', e.nativeEvent)
|
||||||
|
}
|
||||||
|
onDrop={e => this._appendEvent('MouseDrop', e.nativeEvent)}>
|
||||||
|
<Text style={styles.button}>Click Me</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
testID="touchable_feedback_mouse_events_console"
|
||||||
|
style={styles.eventLogBox}>
|
||||||
|
{this.state.eventLog.map((e, ii) => (
|
||||||
|
<Text key={ii}>{e}</Text>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_appendEvent = (eventName, nativeEvent) => {
|
||||||
|
var limit = 6;
|
||||||
|
var eventLog = this.state.eventLog.slice(0, limit - 1);
|
||||||
|
|
||||||
|
var eventType = '';
|
||||||
|
if (nativeEvent.button === 0) {
|
||||||
|
eventType = 'left';
|
||||||
|
} else if (nativeEvent.button === 2) {
|
||||||
|
eventType = 'right';
|
||||||
|
}
|
||||||
|
var modifier = '';
|
||||||
|
if (nativeEvent.shiftKey) {
|
||||||
|
modifier += 'shift, ';
|
||||||
|
}
|
||||||
|
if (nativeEvent.ctrlKey) {
|
||||||
|
modifier += 'ctrl, ';
|
||||||
|
}
|
||||||
|
if (nativeEvent.altKey) {
|
||||||
|
modifier += 'alt, ';
|
||||||
|
}
|
||||||
|
if (nativeEvent.metaKey) {
|
||||||
|
modifier += 'meta, ';
|
||||||
|
}
|
||||||
|
if (modifier.length > 0) {
|
||||||
|
modifier = ' - ' + modifier.slice(0, -2) + ' pressed';
|
||||||
|
}
|
||||||
|
|
||||||
|
eventLog.unshift(eventType + eventName + modifier);
|
||||||
|
this.setState({eventLog});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
const heartImage = {
|
const heartImage = {
|
||||||
uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small',
|
uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small',
|
||||||
};
|
};
|
||||||
|
@ -611,4 +718,24 @@ exports.examples = [
|
||||||
return <TouchableDisabled />;
|
return <TouchableDisabled />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// [TODO(macOS ISS#2323203)
|
||||||
|
title: 'Touchable Hover',
|
||||||
|
description:
|
||||||
|
('<Touchable*> components reacts to mouse events ' +
|
||||||
|
'onMouseEnter and onMouseLeave': string),
|
||||||
|
render: function(): React.Element<any> {
|
||||||
|
return <TouchableHover />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Touchable feedback mouse events',
|
||||||
|
description:
|
||||||
|
('<Touchable*> components reacts to mouse events ' +
|
||||||
|
'onPressIn, onPressOut, onDragEnter, onDragLeave, and onDrop': string),
|
||||||
|
render: function(): React.Element<any> {
|
||||||
|
return <TouchableMouseEvents />;
|
||||||
|
},
|
||||||
|
platform: 'macos',
|
||||||
|
}, // ]TODO(macOS ISS#2323203)
|
||||||
];
|
];
|
||||||
|
|
|
@ -64,7 +64,9 @@ Pod::Spec.new do |s|
|
||||||
# [TODO(macOS ISS#2323203)
|
# [TODO(macOS ISS#2323203)
|
||||||
"**/macOS/*"
|
"**/macOS/*"
|
||||||
ss.osx.exclude_files = "React/Modules/RCTRedBoxExtraDataViewController.{h,m}",
|
ss.osx.exclude_files = "React/Modules/RCTRedBoxExtraDataViewController.{h,m}",
|
||||||
"React/Profiler/RCTProfileTrampoline-{arm,arm64,i386}.S",
|
"React/Modules/RCTAccessibilityManager.m",
|
||||||
|
"React/Profiler/{RCTFPSGraph,RCTPerfMonitor}.*",
|
||||||
|
"React/Profiler/RCTProfileTrampoline-{arm,i386}.S",
|
||||||
"React/Base/RCTKeyCommands.*",
|
"React/Base/RCTKeyCommands.*",
|
||||||
"React/Base/RCTTV*.*",
|
"React/Base/RCTTV*.*",
|
||||||
"React/Views/{RCTModal*,RCTMasked*,RCTTV*,RCTWrapperViewController}.*",
|
"React/Views/{RCTModal*,RCTMasked*,RCTTV*,RCTWrapperViewController}.*",
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import <React/RCTComponentEvent.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a focus change event meaning that a view that can become first responder has become or resigned being first responder.
|
||||||
|
*/
|
||||||
|
@interface RCTFocusChangeEvent : RCTComponentEvent
|
||||||
|
|
||||||
|
+ (instancetype)focusEventWithReactTag:(NSNumber *)reactTag;
|
||||||
|
+ (instancetype)blurEventWithReactTag:(NSNumber *)reactTag;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTFocusChangeEvent.h"
|
||||||
|
|
||||||
|
#import "RCTAssert.h"
|
||||||
|
|
||||||
|
@implementation RCTFocusChangeEvent
|
||||||
|
|
||||||
|
+ (instancetype)focusEventWithReactTag:(NSNumber *)reactTag
|
||||||
|
{
|
||||||
|
RCTFocusChangeEvent *event = [[self alloc] initWithName:@"focus"
|
||||||
|
viewTag:reactTag
|
||||||
|
body:@{}];
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)blurEventWithReactTag:(NSNumber *)reactTag
|
||||||
|
{
|
||||||
|
RCTFocusChangeEvent *event = [[self alloc] initWithName:@"blur"
|
||||||
|
viewTag:reactTag
|
||||||
|
body:@{}];
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -38,6 +38,10 @@
|
||||||
#import "RCTDevMenu.h"
|
#import "RCTDevMenu.h"
|
||||||
#endif // ]TODO(OSS Candidate ISS#2710739)
|
#endif // ]TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
#define RCT_LAYOUT_THROTTLE 0.25
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification";
|
NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification";
|
||||||
|
|
||||||
@interface RCTUIManager (RCTRootView)
|
@interface RCTUIManager (RCTRootView)
|
||||||
|
@ -53,6 +57,11 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
||||||
RCTRootContentView *_contentView;
|
RCTRootContentView *_contentView;
|
||||||
BOOL _passThroughTouches;
|
BOOL _passThroughTouches;
|
||||||
CGSize _intrinsicContentSize;
|
CGSize _intrinsicContentSize;
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
NSDate *_lastLayout;
|
||||||
|
BOOL _throttleLayout;
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||||
|
@ -80,6 +89,10 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
||||||
_loadingViewFadeDuration = 0.25;
|
_loadingViewFadeDuration = 0.25;
|
||||||
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
|
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
_lastLayout = [NSDate new];
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(bridgeDidReload)
|
selector:@selector(bridgeDidReload)
|
||||||
name:RCTJavaScriptWillStartLoadingNotification
|
name:RCTJavaScriptWillStartLoadingNotification
|
||||||
|
@ -174,6 +187,35 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||||
return fitSize;
|
return fitSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
// TODO: https://github.com/microsoft/react-native-macos/issues/459
|
||||||
|
// This is a workaround for window resizing events overloading the shadow queue:
|
||||||
|
// - https://github.com/microsoft/react-native-macos/issues/322
|
||||||
|
// - https://github.com/microsoft/react-native-macos/issues/422
|
||||||
|
// We should revisit this issue when we switch over to Fabric.
|
||||||
|
- (void)layout
|
||||||
|
{
|
||||||
|
if (self.window != nil && !_throttleLayout) {
|
||||||
|
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:_lastLayout];
|
||||||
|
if (interval >= RCT_LAYOUT_THROTTLE) {
|
||||||
|
_lastLayout = [NSDate new];
|
||||||
|
[self layoutSubviews];
|
||||||
|
} else {
|
||||||
|
_throttleLayout = YES;
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
int64_t delta = (RCT_LAYOUT_THROTTLE - interval) * NSEC_PER_SEC;
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta), dispatch_get_main_queue(), ^{
|
||||||
|
typeof(self) strongSelf = weakSelf;
|
||||||
|
if (strongSelf != nil) {
|
||||||
|
strongSelf->_throttleLayout = NO;
|
||||||
|
[strongSelf setNeedsLayout];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
|
|
@ -61,9 +61,9 @@ static NSString *const RCTDarkAquaColor = @"darkAquaColor";
|
||||||
NSColor *effectiveColor = _aquaColor;
|
NSColor *effectiveColor = _aquaColor;
|
||||||
if (@available(macOS 10.14, *)) {
|
if (@available(macOS 10.14, *)) {
|
||||||
NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance];
|
NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance];
|
||||||
|
|
||||||
NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
||||||
|
|
||||||
if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) {
|
if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) {
|
||||||
effectiveColor = _darkAquaColor;
|
effectiveColor = _darkAquaColor;
|
||||||
}
|
}
|
||||||
|
@ -181,4 +181,37 @@ RCT_FORWARD_PROPERTY(localizedColorNameComponent, NSString *)
|
||||||
return [[self effectiveColor] colorWithSystemEffect:systemEffect];
|
return [[self effectiveColor] colorWithSystemEffect:systemEffect];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash
|
||||||
|
{
|
||||||
|
const NSUInteger prime = 31;
|
||||||
|
NSUInteger result = 1;
|
||||||
|
result = prime * result + [_aquaColor hash];
|
||||||
|
result = prime * result + [_darkAquaColor hash];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)other {
|
||||||
|
if (other == self) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return other != nil && [other isKindOfClass:[self class]] && [self isEqualToDynamicColor:other];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToDynamicColor:(RCTDynamicColor *)other {
|
||||||
|
if (self == other) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([_aquaColor isNotEqualTo:other->_aquaColor]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([_darkAquaColor isNotEqualTo:other->_darkAquaColor]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTAccessibilityManager.h"
|
||||||
|
|
||||||
|
#import "RCTBridge.h"
|
||||||
|
#import "RCTConvert.h"
|
||||||
|
#import "RCTEventDispatcher.h"
|
||||||
|
#import "RCTLog.h"
|
||||||
|
#import "RCTUIManager.h"
|
||||||
|
|
||||||
|
NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification =
|
||||||
|
@"RCTAccessibilityManagerDidUpdateMultiplierNotification";
|
||||||
|
|
||||||
|
@implementation RCTAccessibilityManager
|
||||||
|
@synthesize bridge = _bridge;
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
|
static void *AccessibilityVoiceOverChangeContext = &AccessibilityVoiceOverChangeContext;
|
||||||
|
|
||||||
|
+ (BOOL)requiresMainQueueSetup
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
[[NSWorkspace sharedWorkspace] addObserver:self
|
||||||
|
forKeyPath:@"voiceOverEnabled"
|
||||||
|
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
|
||||||
|
context:AccessibilityVoiceOverChangeContext];
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
|
||||||
|
selector:@selector(accessibilityDisplayOptionsChange:)
|
||||||
|
name:NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
|
||||||
|
object:nil];
|
||||||
|
_isInvertColorsEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldInvertColors];
|
||||||
|
_isReduceMotionEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
|
||||||
|
_isReduceTransparencyEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
|
||||||
|
_isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
|
||||||
|
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[[NSWorkspace sharedWorkspace] removeObserver:self
|
||||||
|
forKeyPath:@"voiceOverEnabled"
|
||||||
|
context:AccessibilityVoiceOverChangeContext];
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(announceForAccessibility:(NSString *)announcement)
|
||||||
|
{
|
||||||
|
NSAccessibilityPostNotificationWithUserInfo(
|
||||||
|
NSApp,
|
||||||
|
NSAccessibilityAnnouncementRequestedNotification,
|
||||||
|
@{NSAccessibilityAnnouncementKey : announcement,
|
||||||
|
NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getCurrentInvertColorsState:(RCTResponseSenderBlock)callback
|
||||||
|
error:(__unused RCTResponseSenderBlock)error)
|
||||||
|
{
|
||||||
|
callback(@[@(_isInvertColorsEnabled)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getCurrentReduceMotionState:(RCTResponseSenderBlock)callback
|
||||||
|
error:(__unused RCTResponseSenderBlock)error)
|
||||||
|
{
|
||||||
|
callback(@[@(_isReduceMotionEnabled)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getCurrentReduceTransparencyState:(RCTResponseSenderBlock)callback
|
||||||
|
error:(__unused RCTResponseSenderBlock)error)
|
||||||
|
{
|
||||||
|
callback(@[@(_isReduceTransparencyEnabled)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getCurrentVoiceOverState:(RCTResponseSenderBlock)callback
|
||||||
|
error:(__unused RCTResponseSenderBlock)error)
|
||||||
|
{
|
||||||
|
BOOL isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
|
||||||
|
callback(@[ @(isVoiceOverEnabled) ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(setAccessibilityFocus:(nonnull NSNumber *)reactTag)
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
NSView *view = [self.bridge.uiManager viewForReactTag:reactTag];
|
||||||
|
[[view window] makeFirstResponder:view];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||||
|
ofObject:(id)object
|
||||||
|
change:(NSDictionary *)change
|
||||||
|
context:(void *)context {
|
||||||
|
if (context == AccessibilityVoiceOverChangeContext) {
|
||||||
|
BOOL newIsVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
|
||||||
|
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
|
||||||
|
_isVoiceOverEnabled = newIsVoiceOverEnabled;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"screenReaderChanged"
|
||||||
|
body:@(_isVoiceOverEnabled)];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[super observeValueForKeyPath:keyPath
|
||||||
|
ofObject:object
|
||||||
|
change:change
|
||||||
|
context:context];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)accessibilityDisplayOptionsChange:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
BOOL newInvertColorsEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldInvertColors];
|
||||||
|
BOOL newReduceMotionEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
|
||||||
|
BOOL newReduceTransparencyEnabled = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
|
||||||
|
if (_isInvertColorsEnabled != newInvertColorsEnabled) {
|
||||||
|
_isInvertColorsEnabled = newInvertColorsEnabled;
|
||||||
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"invertColorsChanged"
|
||||||
|
body:@(_isInvertColorsEnabled)];
|
||||||
|
}
|
||||||
|
if (_isReduceMotionEnabled != newReduceMotionEnabled) {
|
||||||
|
_isReduceMotionEnabled = newReduceMotionEnabled;
|
||||||
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceMotionChanged"
|
||||||
|
body:@(_isReduceMotionEnabled)];
|
||||||
|
}
|
||||||
|
if (_isReduceTransparencyEnabled != newReduceTransparencyEnabled) {
|
||||||
|
_isReduceTransparencyEnabled = newReduceTransparencyEnabled;
|
||||||
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceTransparencyChanged"
|
||||||
|
body:@(_isReduceTransparencyEnabled)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
- (void)startAnimating
|
- (void)startAnimating
|
||||||
{
|
{
|
||||||
|
// `wantsLayer` gets reset after the animation is stopped. We have to
|
||||||
|
// reset it in order for CALayer filters to take effect.
|
||||||
|
[self setWantsLayer:YES];
|
||||||
[self startAnimation:self];
|
[self startAnimation:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +69,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setColor: (RCTUIColor*)color
|
- (void)setColor:(RCTUIColor*)color
|
||||||
{
|
{
|
||||||
if (_color != color) {
|
if (_color != color) {
|
||||||
_color = color;
|
_color = color;
|
||||||
|
@ -77,19 +80,23 @@
|
||||||
- (void)updateLayer
|
- (void)updateLayer
|
||||||
{
|
{
|
||||||
[super updateLayer];
|
[super updateLayer];
|
||||||
if (_color) {
|
if (_color != nil) {
|
||||||
CGFloat r, g, b, a;
|
CGFloat r, g, b, a;
|
||||||
[[_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a];
|
[[_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a];
|
||||||
|
|
||||||
CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"];
|
CIFilter *colorPoly = [CIFilter filterWithName:@"CIColorPolynomial"];
|
||||||
[colorPoly setDefaults];
|
[colorPoly setDefaults];
|
||||||
|
|
||||||
CIVector *redVector = [CIVector vectorWithX:r Y:0 Z:0 W:0];
|
CIVector *redVector = [CIVector vectorWithX:r Y:0 Z:0 W:0];
|
||||||
CIVector *greenVector = [CIVector vectorWithX:g Y:0 Z:0 W:0];
|
CIVector *greenVector = [CIVector vectorWithX:g Y:0 Z:0 W:0];
|
||||||
CIVector *blueVector = [CIVector vectorWithX:b Y:0 Z:0 W:0];
|
CIVector *blueVector = [CIVector vectorWithX:b Y:0 Z:0 W:0];
|
||||||
[colorPoly setValue:redVector forKey:@"inputRedCoefficients"];
|
[colorPoly setValue:redVector forKey:@"inputRedCoefficients"];
|
||||||
[colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"];
|
[colorPoly setValue:greenVector forKey:@"inputGreenCoefficients"];
|
||||||
[colorPoly setValue:blueVector forKey:@"inputBlueCoefficients"];
|
[colorPoly setValue:blueVector forKey:@"inputBlueCoefficients"];
|
||||||
self.contentFilters = @[colorPoly];
|
|
||||||
|
[[self layer] setFilters:@[colorPoly]];
|
||||||
|
} else {
|
||||||
|
[[self layer] setFilters:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
@property (nonatomic, assign) NSInteger selectedIndex;
|
@property (nonatomic, assign) NSInteger selectedIndex;
|
||||||
|
|
||||||
@property (nonatomic, strong) RCTUIColor *color; // TODO(OSS Candidate ISS#2710739)
|
@property (nonatomic, strong) RCTUIColor *color; // TODO(OSS Candidate ISS#2710739)
|
||||||
|
#if !TARGET_OS_OSX // [TODO(OSS Candidate ISS#2710739) // NSControl defines font prop for macOS, but iOS superviews don't
|
||||||
@property (nonatomic, strong) UIFont *font;
|
@property (nonatomic, strong) UIFont *font;
|
||||||
|
#endif // ]TODO(OSS Candidate ISS#2710739)
|
||||||
@property (nonatomic, assign) NSTextAlignment textAlign;
|
@property (nonatomic, assign) NSTextAlignment textAlign;
|
||||||
|
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
|
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
|
||||||
|
|
|
@ -23,16 +23,17 @@
|
||||||
- (instancetype)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if ((self = [super initWithFrame:frame])) {
|
if ((self = [super initWithFrame:frame])) {
|
||||||
_color = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739)
|
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
|
_color = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739)
|
||||||
_font = [UIFont systemFontOfSize:21]; // TODO: selected title default should be 23.5
|
_font = [UIFont systemFontOfSize:21]; // TODO: selected title default should be 23.5
|
||||||
#else // [TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
_font = [UIFont systemFontOfSize:11];
|
_color = [NSColor labelColor];
|
||||||
|
[self setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
_selectedIndex = NSNotFound;
|
_selectedIndex = NSNotFound;
|
||||||
_textAlign = NSTextAlignmentCenter;
|
_textAlign = NSTextAlignmentCenter;
|
||||||
self.delegate = self;
|
self.delegate = self;
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
self.controlSize = NSControlSizeRegular;
|
self.controlSize = NSControlSizeRegular;
|
||||||
self.editable = NO;
|
self.editable = NO;
|
||||||
|
@ -63,7 +64,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||||
NSMutableDictionary *mutableItem = item.mutableCopy;
|
NSMutableDictionary *mutableItem = item.mutableCopy;
|
||||||
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[RCTConvert NSString:item[@"label"]]
|
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[RCTConvert NSString:item[@"label"]]
|
||||||
attributes:@{NSForegroundColorAttributeName : [RCTConvert UIColor:item[@"textColor"]] ?: _color,
|
attributes:@{NSForegroundColorAttributeName : [RCTConvert UIColor:item[@"textColor"]] ?: _color,
|
||||||
NSFontAttributeName: _font,
|
NSFontAttributeName: [self font] /* Use the font prop instead of the ivar so it's compatible on iOS and macOS TODO(OSS Candidate ISS#2710739) */,
|
||||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||||
NSSize size = attrString.size;
|
NSSize size = attrString.size;
|
||||||
if (size.height > maxHeight) {
|
if (size.height > maxHeight) {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#import <React/RCTBorderStyle.h>
|
#import <React/RCTBorderStyle.h>
|
||||||
#import <React/RCTComponent.h>
|
#import <React/RCTComponent.h>
|
||||||
|
#import <React/RCTEventDispatcher.h> // TODO(OSS Candidate ISS#2710739)
|
||||||
#import <React/RCTPointerEvents.h>
|
#import <React/RCTPointerEvents.h>
|
||||||
|
|
||||||
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
|
@ -22,6 +23,8 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
|
||||||
@interface RCTView : RCTUIView // TODO(macOS ISS#3536887)
|
@interface RCTView : RCTUIView // TODO(macOS ISS#3536887)
|
||||||
|
|
||||||
// [TODO(OSS Candidate ISS#2710739)
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||||
|
|
||||||
- (BOOL)becomeFirstResponder;
|
- (BOOL)becomeFirstResponder;
|
||||||
- (BOOL)resignFirstResponder;
|
- (BOOL)resignFirstResponder;
|
||||||
// ]TODO(OSS Candidate ISS#2710739)
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#import "RCTAutoInsetsProtocol.h"
|
#import "RCTAutoInsetsProtocol.h"
|
||||||
#import "RCTBorderDrawing.h"
|
#import "RCTBorderDrawing.h"
|
||||||
|
#import "RCTFocusChangeEvent.h" // TODO(OSS Candidate ISS#2710739)
|
||||||
#import "RCTConvert.h"
|
#import "RCTConvert.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
#import "RCTRootContentView.h" // TODO(macOS ISS#2323203)
|
#import "RCTRootContentView.h" // TODO(macOS ISS#2323203)
|
||||||
|
@ -108,6 +109,7 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
|
||||||
@implementation RCTView
|
@implementation RCTView
|
||||||
{
|
{
|
||||||
RCTUIColor *_backgroundColor; // TODO(OSS Candidate ISS#2710739)
|
RCTUIColor *_backgroundColor; // TODO(OSS Candidate ISS#2710739)
|
||||||
|
RCTEventDispatcher *_eventDispatcher; // TODO(OSS Candidate ISS#2710739)
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
NSTrackingArea *_trackingArea;
|
NSTrackingArea *_trackingArea;
|
||||||
BOOL _hasMouseOver;
|
BOOL _hasMouseOver;
|
||||||
|
@ -116,6 +118,16 @@ static NSString *RCTRecursiveAccessibilityLabel(RCTUIView *view) // TODO(macOS I
|
||||||
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap;
|
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TODO(OSS Candidate ISS#2710739)
|
||||||
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||||
|
{
|
||||||
|
if ((self = [self initWithFrame:CGRectZero])) {
|
||||||
|
_eventDispatcher = eventDispatcher;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
// ]TODO(OSS Candidate ISS#2710739)
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if ((self = [super initWithFrame:frame])) {
|
if ((self = [super initWithFrame:frame])) {
|
||||||
|
@ -724,21 +736,20 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've gained focus, notify listeners
|
// If we've gained focus, notify listeners
|
||||||
if (self.onFocus != nil ) {
|
[_eventDispatcher sendEvent:[RCTFocusChangeEvent focusEventWithReactTag:self.reactTag]];
|
||||||
self.onFocus(nil);
|
|
||||||
}
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)resignFirstResponder
|
- (BOOL)resignFirstResponder
|
||||||
{
|
{
|
||||||
if (![super resignFirstResponder]) {
|
if (![super resignFirstResponder]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've gained focus, notify listeners
|
// If we've lost focus, notify listeners
|
||||||
if (self.onBlur != nil ) {
|
[_eventDispatcher sendEvent:[RCTFocusChangeEvent blurEventWithReactTag:self.reactTag]];
|
||||||
self.onBlur(nil);
|
|
||||||
}
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,6 +922,11 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RCTUpdateShadowPathForView(self);
|
RCTUpdateShadowPathForView(self);
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
// clipsToBounds is stubbed out on macOS because it's not part of NSView
|
||||||
|
layer.masksToBounds = self.clipsToBounds;
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
const RCTCornerRadii cornerRadii = [self cornerRadii];
|
const RCTCornerRadii cornerRadii = [self cornerRadii];
|
||||||
const UIEdgeInsets borderInsets = [self bordersAsInsets];
|
const UIEdgeInsets borderInsets = [self bordersAsInsets];
|
||||||
|
|
|
@ -89,7 +89,7 @@ RCT_EXPORT_MODULE()
|
||||||
#if TARGET_OS_TV
|
#if TARGET_OS_TV
|
||||||
return [RCTTVView new];
|
return [RCTTVView new];
|
||||||
#else
|
#else
|
||||||
return [RCTView new];
|
return [[RCTView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; // TODO(OSS Candidate ISS#2710739)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface RCTScrollContentLocalData : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CGFloat horizontalScrollerHeight;
|
||||||
|
@property (nonatomic, assign) CGFloat verticalScrollerWidth;
|
||||||
|
|
||||||
|
- (instancetype)initWithVerticalScroller:(nullable NSScroller *)verticalScroller
|
||||||
|
horizontalScroller:(nullable NSScroller *)horizontalScroller;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTScrollContentLocalData.h"
|
||||||
|
|
||||||
|
@implementation RCTScrollContentLocalData
|
||||||
|
|
||||||
|
- (instancetype)initWithVerticalScroller:(NSScroller *)verticalScroller
|
||||||
|
horizontalScroller:(NSScroller *)horizontalScroller
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_verticalScrollerWidth = NSWidth([verticalScroller frame]);
|
||||||
|
_horizontalScrollerHeight = NSHeight([horizontalScroller frame]);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -9,10 +9,28 @@
|
||||||
|
|
||||||
#import <yoga/Yoga.h>
|
#import <yoga/Yoga.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
#import "RCTScrollContentLocalData.h"
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
@implementation RCTScrollContentShadowView
|
@implementation RCTScrollContentShadowView
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
- (void)setLocalData:(RCTScrollContentLocalData *)localData
|
||||||
|
{
|
||||||
|
RCTAssert(
|
||||||
|
[localData isKindOfClass:[RCTScrollContentLocalData class]],
|
||||||
|
@"Local data object for `RCTScrollContentView` must be `RCTScrollContentLocalData` instance.");
|
||||||
|
|
||||||
|
super.marginEnd = (YGValue){localData.verticalScrollerWidth, YGUnitPoint};
|
||||||
|
super.marginBottom = (YGValue){localData.horizontalScrollerHeight, YGUnitPoint};
|
||||||
|
|
||||||
|
[self didSetProps:@[@"marginEnd", @"marginBottom"]];
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
|
- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
|
||||||
layoutContext:(RCTLayoutContext)layoutContext
|
layoutContext:(RCTLayoutContext)layoutContext
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,9 +10,20 @@
|
||||||
#import <React/RCTAssert.h>
|
#import <React/RCTAssert.h>
|
||||||
#import <React/UIView+React.h>
|
#import <React/UIView+React.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
#import <React/RCTUIManager.h>
|
||||||
|
#import "RCTScrollContentLocalData.h"
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
#import "RCTScrollView.h"
|
#import "RCTScrollView.h"
|
||||||
|
|
||||||
@implementation RCTScrollContentView
|
@implementation RCTScrollContentView
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
{
|
||||||
|
BOOL _hasHorizontalScroller;
|
||||||
|
BOOL _hasVerticalScroller;
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
- (void)reactSetFrame:(CGRect)frame
|
- (void)reactSetFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
|
@ -21,25 +32,6 @@
|
||||||
#else // [TODO(macOS ISS#2323203)
|
#else // [TODO(macOS ISS#2323203)
|
||||||
// macOS also has a NSClipView in its hierarchy
|
// macOS also has a NSClipView in its hierarchy
|
||||||
RCTScrollView *scrollView = (RCTScrollView *)self.superview.superview.superview;
|
RCTScrollView *scrollView = (RCTScrollView *)self.superview.superview.superview;
|
||||||
|
|
||||||
if (scrollView != nil) {
|
|
||||||
// On macOS scroll indicators may float over the content view like they do in iOS
|
|
||||||
// or depending on system preferences they may be outside of the content view
|
|
||||||
// which means the clip view will be smaller than the scroll view itself.
|
|
||||||
// In such cases the content view layout must shrink accordingly otherwise
|
|
||||||
// the contents will overflow causing the scroll indicators to appear unnecessarily.
|
|
||||||
NSScrollView *platformScrollView = scrollView.scrollView;
|
|
||||||
if (platformScrollView.scrollerStyle == NSScrollerStyleLegacy) {
|
|
||||||
NSScroller *verticalScroller = platformScrollView.verticalScroller;
|
|
||||||
if (!verticalScroller.isHidden) {
|
|
||||||
frame.size.width -= verticalScroller.frame.size.width;
|
|
||||||
}
|
|
||||||
NSScroller *horizontalScroller = platformScrollView.horizontalScroller;
|
|
||||||
if (!horizontalScroller.isHidden) {
|
|
||||||
frame.size.height -= horizontalScroller.frame.size.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // ]TODO(macOS ISS#2323203)
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
|
|
||||||
[super reactSetFrame:frame];
|
[super reactSetFrame:frame];
|
||||||
|
@ -52,6 +44,32 @@
|
||||||
@"Unexpected view hierarchy of RCTScrollView component.");
|
@"Unexpected view hierarchy of RCTScrollView component.");
|
||||||
|
|
||||||
[scrollView updateContentOffsetIfNeeded];
|
[scrollView updateContentOffsetIfNeeded];
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
// On macOS scroll indicators may float over the content view like they do in iOS
|
||||||
|
// or depending on system preferences they may be outside of the content view
|
||||||
|
// which means the clip view will be smaller than the scroll view itself.
|
||||||
|
// In such cases the content view layout must shrink accordingly otherwise
|
||||||
|
// the contents will overflow causing the scroll indicators to appear unnecessarily.
|
||||||
|
NSScrollView *platformScrollView = [scrollView scrollView];
|
||||||
|
if ([platformScrollView scrollerStyle] == NSScrollerStyleLegacy) {
|
||||||
|
const BOOL nextHasHorizontalScroller = [platformScrollView hasHorizontalScroller];
|
||||||
|
const BOOL nextHasVerticalScroller = [platformScrollView hasVerticalScroller];
|
||||||
|
|
||||||
|
if (_hasHorizontalScroller != nextHasHorizontalScroller ||
|
||||||
|
_hasVerticalScroller != nextHasVerticalScroller) {
|
||||||
|
|
||||||
|
_hasHorizontalScroller = nextHasHorizontalScroller;
|
||||||
|
_hasVerticalScroller = nextHasVerticalScroller;
|
||||||
|
|
||||||
|
RCTScrollContentLocalData *localData =
|
||||||
|
[[RCTScrollContentLocalData alloc]
|
||||||
|
initWithVerticalScroller:[platformScrollView verticalScroller]
|
||||||
|
horizontalScroller:[platformScrollView horizontalScroller]];
|
||||||
|
[[[scrollView bridge] uiManager] setLocalData:localData forView:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) RCTBridge *bridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `RCTScrollView` may have at most one single subview. This will ensure
|
* The `RCTScrollView` may have at most one single subview. This will ensure
|
||||||
* that the scroll view's `contentSize` will be efficiently set to the size of
|
* that the scroll view's `contentSize` will be efficiently set to the size of
|
||||||
|
|
|
@ -57,7 +57,6 @@
|
||||||
self.scrollEnabled = YES;
|
self.scrollEnabled = YES;
|
||||||
self.hasHorizontalScroller = YES;
|
self.hasHorizontalScroller = YES;
|
||||||
self.hasVerticalScroller = YES;
|
self.hasVerticalScroller = YES;
|
||||||
self.autohidesScrollers = YES;
|
|
||||||
self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
|
self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
|
||||||
#else // ]TODO(macOS ISS#2323203)
|
#else // ]TODO(macOS ISS#2323203)
|
||||||
[self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)];
|
[self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)];
|
||||||
|
@ -436,6 +435,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (RCTBridge *)bridge
|
||||||
|
{
|
||||||
|
return [_eventDispatcher bridge];
|
||||||
|
}
|
||||||
|
|
||||||
- (RCTUIView *)contentView // TODO(macOS ISS#3536887)
|
- (RCTUIView *)contentView // TODO(macOS ISS#3536887)
|
||||||
{
|
{
|
||||||
return _scrollView.documentView;
|
return _scrollView.documentView;
|
||||||
|
@ -621,6 +625,11 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
||||||
[self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView];
|
[self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView];
|
||||||
_lastClippedToRect = bounds;
|
_lastClippedToRect = bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
[[self scrollView] setHasHorizontalScroller:[self isHorizontal:_scrollView]];
|
||||||
|
[[self scrollView] setHasVerticalScroller:[self isVertical:_scrollView]];
|
||||||
|
#endif // ]TODO(macOS ISS#2323203)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||||
|
@ -678,6 +687,13 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
||||||
return scrollView.contentSize.width > self.frame.size.width;
|
return scrollView.contentSize.width > self.frame.size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
|
||||||
|
- (BOOL)isVertical:(RCTCustomScrollView *)scrollView
|
||||||
|
{
|
||||||
|
return scrollView.contentSize.height > self.frame.size.height;
|
||||||
|
}
|
||||||
|
#endif // ]TODO(macOS Candidate ISS#2710739)
|
||||||
|
|
||||||
- (void)scrollToOffset:(CGPoint)offset
|
- (void)scrollToOffset:(CGPoint)offset
|
||||||
{
|
{
|
||||||
[self scrollToOffset:offset animated:YES];
|
[self scrollToOffset:offset animated:YES];
|
||||||
|
|
|
@ -294,7 +294,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reactBlur {
|
- (void)reactBlur {
|
||||||
|
#if TARGET_OS_OSX // TODO(macOS ISS#2323203)
|
||||||
|
if (self == [[self window] firstResponder]) {
|
||||||
|
[[self window] makeFirstResponder:[[self window] nextResponder]];
|
||||||
|
}
|
||||||
|
#else
|
||||||
[self resignFirstResponder];
|
[self resignFirstResponder];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Layout
|
#pragma mark - Layout
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- "D:\\code\\work\\react-native-v0.61.5\\ReactAndroid\\ReactAndroid.nuspec" 1969-12-31 16:00:00.000000000 -0800
|
--- "D:\\code\\work\\react-native-v0.61.5\\ReactAndroid\\ReactAndroid.nuspec" 1969-12-31 16:00:00.000000000 -0800
|
||||||
+++ "D:\\code\\work\\react-native-fb61merge\\ReactAndroid\\ReactAndroid.nuspec" 2020-03-30 21:05:08.615724600 -0700
|
+++ "D:\\code\\work\\react-native-fb61merge\\ReactAndroid\\ReactAndroid.nuspec" 2020-03-30 21:05:08.615724600 -0700
|
||||||
@@ -0,0 +1,120 @@
|
@@ -0,0 +1,110 @@
|
||||||
+<?xml version="1.0" encoding="utf-8"?>
|
+<?xml version="1.0" encoding="utf-8"?>
|
||||||
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
+ <metadata>
|
+ <metadata>
|
||||||
|
@ -45,11 +45,6 @@
|
||||||
+ <file src="build\react-ndk\all\x86\libreactnativejni.so" target="lib\droidx86"/>
|
+ <file src="build\react-ndk\all\x86\libreactnativejni.so" target="lib\droidx86"/>
|
||||||
+ <file src="build\react-ndk\all\arm64-v8a\libreactnativejni.so" target="lib\droidarm64"/>
|
+ <file src="build\react-ndk\all\arm64-v8a\libreactnativejni.so" target="lib\droidarm64"/>
|
||||||
+
|
+
|
||||||
+ <file src="build\react-ndk\all\x86_64\libv8executor.so" target="lib\droidx64"/>
|
|
||||||
+ <file src="build\react-ndk\all\armeabi-v7a\libv8executor.so" target="lib\droidarm"/>
|
|
||||||
+ <file src="build\react-ndk\all\x86\libv8executor.so" target="lib\droidx86"/>
|
|
||||||
+ <file src="build\react-ndk\all\arm64-v8a\libv8executor.so" target="lib\droidarm64"/>
|
|
||||||
+
|
|
||||||
+ <file src="build\react-ndk\all\x86_64\libyoga.so" target="lib\droidx64"/>
|
+ <file src="build\react-ndk\all\x86_64\libyoga.so" target="lib\droidx64"/>
|
||||||
+ <file src="build\react-ndk\all\armeabi-v7a\libyoga.so" target="lib\droidarm"/>
|
+ <file src="build\react-ndk\all\armeabi-v7a\libyoga.so" target="lib\droidarm"/>
|
||||||
+ <file src="build\react-ndk\all\x86\libyoga.so" target="lib\droidx86"/>
|
+ <file src="build\react-ndk\all\x86\libyoga.so" target="lib\droidx86"/>
|
||||||
|
@ -91,11 +86,6 @@
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\x86\libreactnativejni.so" target="lib\droidx86\unstripped"/>
|
+ <file src="build\tmp\buildReactNdkLib\local\x86\libreactnativejni.so" target="lib\droidx86\unstripped"/>
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libreactnativejni.so" target="lib\droidarm64\unstripped"/>
|
+ <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libreactnativejni.so" target="lib\droidarm64\unstripped"/>
|
||||||
+
|
+
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\x86_64\libv8executor.so" target="lib\droidx64\unstripped"/>
|
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libv8executor.so" target="lib\droidarm\unstripped"/>
|
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\x86\libv8executor.so" target="lib\droidx86\unstripped"/>
|
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\arm64-v8a\libv8executor.so" target="lib\droidarm64\unstripped"/>
|
|
||||||
+
|
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\x86_64\libyoga.so" target="lib\droidx64\unstripped"/>
|
+ <file src="build\tmp\buildReactNdkLib\local\x86_64\libyoga.so" target="lib\droidx64\unstripped"/>
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libyoga.so" target="lib\droidarm\unstripped"/>
|
+ <file src="build\tmp\buildReactNdkLib\local\armeabi-v7a\libyoga.so" target="lib\droidarm\unstripped"/>
|
||||||
+ <file src="build\tmp\buildReactNdkLib\local\x86\libyoga.so" target="lib\droidx86\unstripped"/>
|
+ <file src="build\tmp\buildReactNdkLib\local\x86\libyoga.so" target="lib\droidx86\unstripped"/>
|
||||||
|
@ -115,7 +105,7 @@
|
||||||
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
|
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
|
||||||
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
|
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
|
||||||
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
|
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
|
||||||
+ <file src="..\folly\**\*.*" target="inc" />
|
+ <file src="..\Folly\**\*.*" target="inc" />
|
||||||
+ <file src="..\glog\src\glog\*.h" target="inc\glog" />
|
+ <file src="..\glog\src\glog\*.h" target="inc\glog" />
|
||||||
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
||||||
+ </files>
|
+ </files>
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
|
+ <file src="..\ReactCommon\cxxreact\**\*.h" target="inc\cxxreact"/>
|
||||||
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
|
+ <file src="..\ReactCommon\jsi\**\*.h" target="inc\jsi"/>
|
||||||
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
|
+ <file src="..\ReactCommon\yoga\yoga\**\*.h" target="inc\Yoga"/>
|
||||||
+ <file src="..\folly\**\*.*" target="inc" />
|
+ <file src="..\Folly\**\*.*" target="inc" />
|
||||||
+ <file src="..\glog\src\glog\*.h" target="inc\glog" />
|
+ <file src="..\glog\src\glog\*.h" target="inc\glog" />
|
||||||
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
+ <file src="..\jsc\jsc-headers\*.h" target="inc\jsc"/>
|
||||||
+ </files>
|
+ </files>
|
||||||
|
|
|
@ -52,6 +52,7 @@ function copyProjectTemplateAndReplace(
|
||||||
|
|
||||||
[
|
[
|
||||||
{ from: path.join(srcRootPath, macOSDir, 'Podfile'), to: path.join(macOSDir, 'Podfile') },
|
{ from: path.join(srcRootPath, macOSDir, 'Podfile'), to: path.join(macOSDir, 'Podfile') },
|
||||||
|
{ from: path.join(srcRootPath, macOSDir, '_gitignore'), to: path.join(macOSDir, '.gitignore') },
|
||||||
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'iOS')), to: srcDirPath(newProjectName, 'iOS') },
|
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'iOS')), to: srcDirPath(newProjectName, 'iOS') },
|
||||||
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'macOS')), to: srcDirPath(newProjectName, 'macOS') },
|
{ from: path.join(srcRootPath, srcDirPath(oldProjectName, 'macOS')), to: srcDirPath(newProjectName, 'macOS') },
|
||||||
{ from: path.join(srcRootPath, pbxprojPath(oldProjectName)), to: pbxprojPath(newProjectName) },
|
{ from: path.join(srcRootPath, pbxprojPath(oldProjectName)), to: pbxprojPath(newProjectName) },
|
||||||
|
@ -143,12 +144,18 @@ function installDependencies(options) {
|
||||||
childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions);
|
childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {{ verbose?: boolean }=} options
|
||||||
|
*/
|
||||||
function installPods(options) {
|
function installPods(options) {
|
||||||
const cwd = path.join(process.cwd(), macOSDir);
|
const cwd = path.join(process.cwd(), macOSDir);
|
||||||
const quietFlag = options && options.verbose ? '' : '--quiet';
|
const quietFlag = options && options.verbose ? '' : '--quiet';
|
||||||
childProcess.execSync(`npx pod-install --non-interactive ${quietFlag}`, { stdio: 'inherit', cwd });
|
childProcess.execSync(`npx ${quietFlag} pod-install --non-interactive ${quietFlag}`, { stdio: 'inherit', cwd });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} newProjectName
|
||||||
|
*/
|
||||||
function printFinishMessage(newProjectName) {
|
function printFinishMessage(newProjectName) {
|
||||||
console.log(`
|
console.log(`
|
||||||
${chalk.blue(`Run instructions for ${chalk.bold('macOS')}`)}:
|
${chalk.blue(`Run instructions for ${chalk.bold('macOS')}`)}:
|
||||||
|
|
|
@ -683,7 +683,7 @@
|
||||||
<scene sceneID="R2V-B0-nI4">
|
<scene sceneID="R2V-B0-nI4">
|
||||||
<objects>
|
<objects>
|
||||||
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
|
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
|
||||||
<window key="window" title="HelloWorld" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
|
<window key="window" title="HelloWorld" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# CocoaPods
|
||||||
|
Pods/
|
|
@ -1,6 +1,21 @@
|
||||||
{
|
{
|
||||||
"name": "react-native-macos-init",
|
"name": "react-native-macos-init",
|
||||||
"entries": [
|
"entries": [
|
||||||
|
{
|
||||||
|
"date": "Mon, 18 May 2020 23:31:12 GMT",
|
||||||
|
"tag": "react-native-macos-init_v2.1.0",
|
||||||
|
"version": "2.1.0",
|
||||||
|
"comments": {
|
||||||
|
"minor": [
|
||||||
|
{
|
||||||
|
"comment": "check the currently installed version of RNmacOS + CLI display tweaks",
|
||||||
|
"author": "gosimek@gmail.com",
|
||||||
|
"commit": "1f640ad99a98c7731a5c210b0dd92673d6a7a230",
|
||||||
|
"package": "react-native-macos-init"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"date": "Sun, 05 Apr 2020 00:06:57 GMT",
|
"date": "Sun, 05 Apr 2020 00:06:57 GMT",
|
||||||
"tag": "react-native-macos-init_v2.0.0",
|
"tag": "react-native-macos-init_v2.0.0",
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
# Change Log - react-native-macos-init
|
# Change Log - react-native-macos-init
|
||||||
|
|
||||||
This log was last generated on Sun, 05 Apr 2020 00:06:57 GMT and should not be manually modified.
|
This log was last generated on Mon, 18 May 2020 23:31:12 GMT and should not be manually modified.
|
||||||
|
|
||||||
<!-- Start content -->
|
<!-- Start content -->
|
||||||
|
|
||||||
|
## 2.1.0
|
||||||
|
|
||||||
|
Mon, 18 May 2020 23:31:12 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- check the currently installed version of RNmacOS + CLI display tweaks (gosimek@gmail.com)
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
Sun, 05 Apr 2020 00:06:57 GMT
|
Sun, 05 Apr 2020 00:06:57 GMT
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-native-macos-init",
|
"name": "react-native-macos-init",
|
||||||
"version": "2.0.0",
|
"version": "2.1.0",
|
||||||
"description": "CLI to add react-native-macos to an existing react-native project",
|
"description": "CLI to add react-native-macos to an existing react-native project",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": "https://github.com/microsoft/react-native-macos",
|
"repository": "https://github.com/microsoft/react-native-macos",
|
||||||
|
|
|
@ -47,19 +47,22 @@ const EXITCODE_NO_REACTNATIVE_FOUND = 5;
|
||||||
const EXITCODE_UNKNOWN_ERROR = 6;
|
const EXITCODE_UNKNOWN_ERROR = 6;
|
||||||
const EXITCODE_NO_PACKAGE_JSON = 7;
|
const EXITCODE_NO_PACKAGE_JSON = 7;
|
||||||
|
|
||||||
|
const RNPKG = 'react-native';
|
||||||
|
const MACOSPKG = 'react-native-macos';
|
||||||
|
|
||||||
function reactNativeMacOSGeneratePath() {
|
function reactNativeMacOSGeneratePath() {
|
||||||
return require.resolve('react-native-macos/local-cli/generate-macos.js', {
|
return require.resolve(`${MACOSPKG}/local-cli/generate-macos.js`, {
|
||||||
paths: [process.cwd()],
|
paths: [process.cwd()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReactNativeAppName() {
|
function getReactNativeAppName() {
|
||||||
console.log('Reading application name from package.json...');
|
console.log(`Reading ${chalk.cyan('application name')} from package.json…`);
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
const pkgJsonPath = findUp.sync('package.json', {cwd});
|
const pkgJsonPath = findUp.sync('package.json', {cwd});
|
||||||
if (!pkgJsonPath) {
|
if (!pkgJsonPath) {
|
||||||
console.error(
|
printError(
|
||||||
'Unable to find package.json. This should be run from within an existing react-native app.',
|
`Unable to find package.json. This should be run from within an existing ${RNPKG} app.`,
|
||||||
);
|
);
|
||||||
process.exit(EXITCODE_NO_PACKAGE_JSON);
|
process.exit(EXITCODE_NO_PACKAGE_JSON);
|
||||||
}
|
}
|
||||||
|
@ -67,36 +70,52 @@ function getReactNativeAppName() {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
const appJsonPath = findUp.sync('app.json', {cwd});
|
const appJsonPath = findUp.sync('app.json', {cwd});
|
||||||
if (appJsonPath) {
|
if (appJsonPath) {
|
||||||
console.log('Reading application name from app.json...');
|
console.log(`Reading ${chalk.cyan('application name')} from app.json…`);
|
||||||
name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name;
|
name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!name) {
|
if (!name) {
|
||||||
console.error('Please specify name in package.json or app.json');
|
printError('Please specify name in package.json or app.json.');
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReactNativeVersion() {
|
function getPackageVersion(
|
||||||
console.log('Reading react-native version from node_modules...');
|
packageName: string,
|
||||||
const rnPkgJsonPath = require.resolve('react-native/package.json', {
|
exitOnError: boolean = true
|
||||||
paths: [process.cwd()],
|
) {
|
||||||
});
|
console.log(`Reading ${chalk.cyan(packageName)} version from node_modules…`);
|
||||||
if (fs.existsSync(rnPkgJsonPath)) {
|
|
||||||
return require(rnPkgJsonPath).version;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error(
|
try {
|
||||||
'Error: Must be run from a project that already depends on react-native, and has react-native installed.',
|
const pkgJsonPath = require.resolve(`${packageName}/package.json`, {
|
||||||
);
|
paths: [process.cwd()],
|
||||||
process.exit(EXITCODE_NO_REACTNATIVE_FOUND);
|
});
|
||||||
|
if (fs.existsSync(pkgJsonPath)) {
|
||||||
|
return require(pkgJsonPath).version;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (exitOnError) {
|
||||||
|
printError(
|
||||||
|
`Must be run from a project that already depends on ${packageName}, and has ${packageName} installed.`,
|
||||||
|
);
|
||||||
|
process.exit(EXITCODE_NO_REACTNATIVE_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReactNativeVersion() {
|
||||||
|
return getPackageVersion(RNPKG);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReactNativeMacOSVersion() {
|
||||||
|
return getPackageVersion(MACOSPKG, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorOutOnUnsupportedVersionOfReactNative(rnVersion: string) {
|
function errorOutOnUnsupportedVersionOfReactNative(rnVersion: string) {
|
||||||
console.error(`Error: Unsupported version of react-native: ${chalk.cyan(
|
printError(`Unsupported version of ${RNPKG}: ${chalk.cyan(
|
||||||
rnVersion,
|
rnVersion,
|
||||||
)}
|
)}
|
||||||
react-native-macos supports react-native versions ${chalk.cyan('>=0.60')}`);
|
${MACOSPKG} supports ${RNPKG} versions ${chalk.cyan('>=0.60')}`);
|
||||||
process.exit(EXITCODE_UNSUPPORTED_VERION_RN);
|
process.exit(EXITCODE_UNSUPPORTED_VERION_RN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +179,7 @@ function getLatestMatchingVersion(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reject(
|
reject(
|
||||||
new Error(`No matching version of ${pkg}@${versionSemVer} found`),
|
new Error(`No matching version of ${pkg}@${versionSemVer} found!`),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -177,7 +196,7 @@ function getLatestMatchingVersion(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reject(
|
reject(
|
||||||
new Error(`No matching version of ${pkg}@${versionSemVer} found`),
|
new Error(`No matching version of ${pkg}@${versionSemVer} found!`),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -190,13 +209,13 @@ async function getLatestMatchingReactNativeMacOSVersion(
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const version = await getLatestMatchingVersion(
|
const version = await getLatestMatchingVersion(
|
||||||
'react-native-macos',
|
MACOSPKG,
|
||||||
versionSemVer,
|
versionSemVer,
|
||||||
);
|
);
|
||||||
return version;
|
return version;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
printError(
|
||||||
`Error: No version of react-native-macos@${versionSemVer} found`,
|
`No version of ${printPkg(MACOSPKG, versionSemVer)} found!`,
|
||||||
);
|
);
|
||||||
process.exit(EXITCODE_NO_MATCHING_RNMACOS);
|
process.exit(EXITCODE_NO_MATCHING_RNMACOS);
|
||||||
return "";
|
return "";
|
||||||
|
@ -210,17 +229,33 @@ function isProjectUsingYarn(cwd: string) {
|
||||||
return findUp.sync('yarn.lock', {cwd});
|
return findUp.sync('yarn.lock', {cwd});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs decorated version of the package for the CLI
|
||||||
|
*/
|
||||||
|
function printPkg(name: string, version?: string) {
|
||||||
|
return `${chalk.yellow(name)}${version ? `${chalk.grey('@')}${chalk.cyan(version)}` : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints decorated version of console.error to the CLI
|
||||||
|
*/
|
||||||
|
function printError(message: string, ...optionalParams: any[]) {
|
||||||
|
console.error(chalk.red(chalk.bold(message)), ...optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const name = getReactNativeAppName();
|
const { overwrite, verbose } = argv;
|
||||||
let version = argv.version;
|
let version = argv.version;
|
||||||
|
|
||||||
|
const name = getReactNativeAppName();
|
||||||
|
const reactNativeVersion = getReactNativeVersion();
|
||||||
|
const reactNativeMacOSVersion = getReactNativeMacOSVersion();
|
||||||
const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest');
|
const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest');
|
||||||
|
|
||||||
if (!version) {
|
if (!version) {
|
||||||
const rnVersion = getReactNativeVersion();
|
|
||||||
version = getDefaultReactNativeMacOSSemVerForReactNativeVersion(
|
version = getDefaultReactNativeMacOSSemVerForReactNativeVersion(
|
||||||
rnVersion,
|
reactNativeVersion,
|
||||||
reactNativeMacOSLatestVersion
|
reactNativeMacOSLatestVersion
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -229,33 +264,25 @@ function isProjectUsingYarn(cwd: string) {
|
||||||
|
|
||||||
if (!argv.version) {
|
if (!argv.version) {
|
||||||
console.log(
|
console.log(
|
||||||
`Latest matching version of ${chalk.bold(
|
`Latest matching version of ${chalk.green(MACOSPKG)} for ${printPkg(
|
||||||
'react-native-macos',
|
RNPKG,
|
||||||
)} for ${chalk.green('react-native')}@${chalk.cyan(
|
reactNativeVersion
|
||||||
getReactNativeVersion(),
|
)} is ${printPkg(
|
||||||
)} is ${chalk.green('react-native-macos')}@${chalk.cyan(
|
MACOSPKG,
|
||||||
reactNativeMacOSResolvedVersion,
|
reactNativeMacOSResolvedVersion
|
||||||
)}`,
|
)}.`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (semver.prerelease(reactNativeMacOSResolvedVersion)) {
|
if (semver.prerelease(reactNativeMacOSResolvedVersion)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`
|
`
|
||||||
${chalk.green('react-native-macos')}@${chalk.cyan(
|
${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)} is a ${chalk.bgYellow('pre-release')} version.
|
||||||
reactNativeMacOSResolvedVersion,
|
The latest supported version is ${printPkg(MACOSPKG, reactNativeMacOSLatestVersion)}.
|
||||||
)} is a ${chalk.yellow('pre-release')} version.
|
You can either downgrade your version of ${chalk.yellow(RNPKG)} to ${chalk.cyan(
|
||||||
The latest supported version is ${chalk.green(
|
|
||||||
'react-native-macos',
|
|
||||||
)}@${chalk.cyan(reactNativeMacOSLatestVersion)}.
|
|
||||||
You can either downgrade your version of ${chalk.green(
|
|
||||||
'react-native',
|
|
||||||
)} to ${chalk.cyan(
|
|
||||||
getMatchingReactNativeSemVerForReactNativeMacOSVersion(
|
getMatchingReactNativeSemVerForReactNativeMacOSVersion(
|
||||||
reactNativeMacOSLatestVersion,
|
reactNativeMacOSLatestVersion,
|
||||||
),
|
),
|
||||||
)}, or continue with a ${chalk.yellow(
|
)}, or continue with a ${chalk.bgYellow('pre-release')} version of ${chalk.yellow(MACOSPKG)}.
|
||||||
'pre-release',
|
|
||||||
)} version of ${chalk.bold('react-native-macos')}.
|
|
||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -263,9 +290,7 @@ You can either downgrade your version of ${chalk.green(
|
||||||
const confirm = (await prompts({
|
const confirm = (await prompts({
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'confirm',
|
name: 'confirm',
|
||||||
message: `Do you wish to continue with ${chalk.green(
|
message: `Do you wish to continue with ${printPkg(MACOSPKG, reactNativeMacOSResolvedVersion)}?`,
|
||||||
'react-native-macos',
|
|
||||||
)}@${chalk.cyan(reactNativeMacOSResolvedVersion)}?`,
|
|
||||||
})).confirm;
|
})).confirm;
|
||||||
|
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
|
@ -275,29 +300,29 @@ You can either downgrade your version of ${chalk.green(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pkgmgr = isProjectUsingYarn(process.cwd())
|
const pkgLatest = printPkg(MACOSPKG, version);
|
||||||
? 'yarn add'
|
|
||||||
: 'npm install --save';
|
|
||||||
|
|
||||||
const execOptions = argv.verbose ? {stdio: 'inherit' as 'inherit'} : {};
|
if (reactNativeMacOSResolvedVersion !== reactNativeMacOSVersion) {
|
||||||
console.log(
|
console.log(`${reactNativeMacOSVersion ? 'Upgrading to' : 'Installing'} ${pkgLatest}…`);
|
||||||
`Installing ${chalk.green('react-native-macos')}@${chalk.cyan(
|
|
||||||
version,
|
const pkgmgr = isProjectUsingYarn(process.cwd())
|
||||||
)}...`,
|
? `yarn add${verbose ? '' : ' -s'}`
|
||||||
);
|
: `npm install --save${verbose ? '' : ' --silent'}`;
|
||||||
execSync(`${pkgmgr} "react-native-macos@${version}"`, execOptions);
|
const execOptions = verbose ? { stdio: 'inherit' as 'inherit' } : {};
|
||||||
console.log(
|
execSync(`${pkgmgr} "${MACOSPKG}@${version}"`, execOptions);
|
||||||
chalk.green(`react-native-macos@${version} successfully installed.`),
|
|
||||||
);
|
console.log(`${pkgLatest} ${chalk.green('successfully installed!')}`);
|
||||||
|
} else {
|
||||||
|
console.log(`${chalk.green('Latest version')} of ${pkgLatest} already installed.`);
|
||||||
|
}
|
||||||
|
|
||||||
const generateMacOS = require(reactNativeMacOSGeneratePath());
|
const generateMacOS = require(reactNativeMacOSGeneratePath());
|
||||||
generateMacOS(process.cwd(), name, {
|
generateMacOS(process.cwd(), name, {
|
||||||
overwrite: argv.overwrite,
|
overwrite,
|
||||||
verbose: argv.verbose,
|
verbose,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(chalk.red(error.message));
|
printError(error.message, error);
|
||||||
console.error(error);
|
|
||||||
process.exit(EXITCODE_UNKNOWN_ERROR);
|
process.exit(EXITCODE_UNKNOWN_ERROR);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче