From 22028b4190b2e2f3ac42ec860b5b6bd6576fc8d5 Mon Sep 17 00:00:00 2001 From: Anandraj Date: Thu, 11 Jun 2020 09:50:46 -0700 Subject: [PATCH 01/57] Working around ndk paths containing spaces in it (#445) * Working around ndk paths containing spaces in it * Fixing a syntax error in task definitino --- .ado/android-pr.yml | 8 +++++++- .ado/android_symlink_ndk.bat | 28 ++++++++++++++++++++++++++++ .ado/publish.yml | 8 +++++++- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 .ado/android_symlink_ndk.bat diff --git a/.ado/android-pr.yml b/.ado/android-pr.yml index ff205fdf4ba872..a3b04d66d3ae68 100644 --- a/.ado/android-pr.yml +++ b/.ado/android-pr.yml @@ -103,9 +103,15 @@ jobs: inputs: script: node cli.js bundle --entry-file .\RNTester\js\RNTesterApp.android.js --bundle-output RNTesterApp.android.bundle --platform android + - task: CmdLine@2 + displayName: Workaround for NDK path containing spaces in it + inputs: + script: .ado\android_symlink_ndk.bat + - task: Gradle@1 displayName: gradlew installArchives -# env: + env: + ANDROID_NDK: c:\android_ndk_symlink__ # REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps inputs: gradleWrapperFile: gradlew diff --git a/.ado/android_symlink_ndk.bat b/.ado/android_symlink_ndk.bat new file mode 100644 index 00000000000000..157a6ffa8fc294 --- /dev/null +++ b/.ado/android_symlink_ndk.bat @@ -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 \ No newline at end of file diff --git a/.ado/publish.yml b/.ado/publish.yml index 65be2bc2d9422d..f4b10e1807360d 100644 --- a/.ado/publish.yml +++ b/.ado/publish.yml @@ -181,9 +181,15 @@ jobs: # inputs: # script: .ado\setup_droid_deps.bat + - task: CmdLine@2 + displayName: Workaround for NDK path containing spaces in it + inputs: + script: .ado\android_symlink_ndk.bat + - task: Gradle@1 displayName: gradlew installArchives -# env: + env: + ANDROID_NDK: c:\android_ndk_symlink__ # REACT_NATIVE_DEPENDENCIES: $(System.DefaultWorkingDirectory)\build_deps inputs: gradleWrapperFile: gradlew From fdeb6d2f030d07772865227e2d20e849f7d2a944 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Thu, 11 Jun 2020 18:51:29 +0200 Subject: [PATCH 02/57] Fix -[RCTDynamicColor effectiveColor] being called off UI thread (#438) --- React/Base/macOS/RCTDynamicColor.m | 37 ++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/React/Base/macOS/RCTDynamicColor.m b/React/Base/macOS/RCTDynamicColor.m index 16157c46629fe3..31b8e13a160dfd 100644 --- a/React/Base/macOS/RCTDynamicColor.m +++ b/React/Base/macOS/RCTDynamicColor.m @@ -61,9 +61,9 @@ - (NSColor *)effectiveColor NSColor *effectiveColor = _aquaColor; if (@available(macOS 10.14, *)) { NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance]; - + NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]]; - + if (_darkAquaColor != nil && [appearanceName isEqualToString:NSAppearanceNameDarkAqua]) { effectiveColor = _darkAquaColor; } @@ -181,4 +181,37 @@ - (NSColor *)colorWithSystemEffect:(NSColorSystemEffect)systemEffect NS_AVAILABL 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 From 9a4e56c929eaad0b5eb02263fb36bf6a774da4e9 Mon Sep 17 00:00:00 2001 From: React-Native Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 11 Jun 2020 16:54:58 +0000 Subject: [PATCH 03/57] Applying package update to 0.61.40 ***NO_CI*** --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b40d39dc9b4bb3..4d2aa7d08b995a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-macos", - "version": "0.61.39", + "version": "0.61.40", "description": "[Microsoft Fork] A framework for building native apps using React", "license": "MIT", "repository": { From 1e5eabd8a2a478b0fd6baf1b0421f0ae00837154 Mon Sep 17 00:00:00 2001 From: graytmatterMS <65255457+graytmatterMS@users.noreply.github.com> Date: Thu, 11 Jun 2020 12:30:58 -0700 Subject: [PATCH 04/57] Adds AccessibilityInfo.isScreenReaderEnabled to RN MacOS (#444) * Attempting to add isVoiceOverEnabled to macOS * Added changes for failure for TurboModules and NativeModules * Mannaged to get static checking working * Enabled screenReaderChanged watcher with KVC * Forked file and cleaned up * Finished cleaning up * Did one last bit of clean up * Removed console.log and returned to using TurboModules. * added Dealloc to remove the KVO observer * ran npx clang-format then polished a few things * Fixed flow error * Added new line * Update React/Modules/MacOS/RCTAccessibilityManager.m Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com> * Taken Set up off main thread * Added correct comment * Removed ifdefs since the file is no longer being used for macOS Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com> --- .../AccessibilityInfo.macos.js | 59 ++++++++++++-- React-Core.podspec | 1 + React/Modules/MacOS/RCTAccessibilityManager.m | 79 +++++++++++++++++++ React/Modules/RCTAccessibilityManager.m | 3 - 4 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 React/Modules/MacOS/RCTAccessibilityManager.m diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js index 3d3ee07711ea31..0c23d168dd63f2 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js @@ -12,10 +12,23 @@ 'use strict'; +const Promise = require('../../Promise'); +const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter'); + +import NativeAccessibilityManager from './NativeAccessibilityManager'; + const warning = require('fbjs/lib/warning'); -type ChangeEventName = $Keys<{}>; +const CHANGE_EVENT_NAME = { + screenReaderChanged: 'screenReaderChanged', +}; + +type ChangeEventName = $Keys<{ + change: string, + screenReaderChanged: string, +}>; +const _subscriptions = new Map(); const AccessibilityInfo = { /** * iOS only @@ -53,10 +66,21 @@ const AccessibilityInfo = { }, /** - * 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 { - return Promise.resolve(false); + return new Promise((resolve, reject) => { + if (NativeAccessibilityManager) { + NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject); + } else { + reject(reject); + } + }); }, /** @@ -71,15 +95,38 @@ const AccessibilityInfo = { addEventListener: function( eventName: ChangeEventName, handler: Function, - ): void { - warning(false, 'AccessibilityInfo is not supported on this platform.'); + ): Object { + let listener; + + if (eventName === 'change') { + listener = RCTDeviceEventEmitter.addListener( + CHANGE_EVENT_NAME.screenReaderChanged, + handler, + ); + } else if (CHANGE_EVENT_NAME[eventName]) { + listener = RCTDeviceEventEmitter.addListener(eventName, handler); + } + + _subscriptions.set(handler, listener); + return { + remove: AccessibilityInfo.removeEventListener.bind( + null, + eventName, + handler, + ), + }; }, removeEventListener: function( eventName: ChangeEventName, handler: Function, ): void { - warning(false, 'AccessibilityInfo is not supported on this platform.'); + const listener = _subscriptions.get(handler); + if (!listener) { + return; + } + listener.remove(); + _subscriptions.delete(handler); }, /** diff --git a/React-Core.podspec b/React-Core.podspec index b69127dea48cc7..945c9fc746e6ad 100644 --- a/React-Core.podspec +++ b/React-Core.podspec @@ -64,6 +64,7 @@ Pod::Spec.new do |s| # [TODO(macOS ISS#2323203) "**/MacOS/*" ss.osx.exclude_files = "React/Modules/RCTRedBoxExtraDataViewController.{h,m}", + "React/Modules/RCTAccessibilityManager.m", "React/Profiler/{RCTFPSGraph,RCTPerfMonitor}.*", "React/Profiler/RCTProfileTrampoline-{arm,arm64,i386}.S", "React/Base/RCTKeyCommands.*", diff --git a/React/Modules/MacOS/RCTAccessibilityManager.m b/React/Modules/MacOS/RCTAccessibilityManager.m new file mode 100644 index 00000000000000..7258c59ec347cc --- /dev/null +++ b/React/Modules/MacOS/RCTAccessibilityManager.m @@ -0,0 +1,79 @@ +/** + * 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]; + _isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled]; + } + return self; +} + +- (void)dealloc +{ + [[NSWorkspace sharedWorkspace] removeObserver:self + forKeyPath:@"voiceOverEnabled" + context:AccessibilityVoiceOverChangeContext]; +} + +RCT_EXPORT_METHOD(getCurrentVoiceOverState:(RCTResponseSenderBlock)callback + error:(__unused RCTResponseSenderBlock)error) +{ + BOOL isVoiceOverEnabled = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled]; + callback(@[ @(isVoiceOverEnabled) ]); +} + +- (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]; + } +} + +@end diff --git a/React/Modules/RCTAccessibilityManager.m b/React/Modules/RCTAccessibilityManager.m index b91bf0040fc3b9..50678c38049472 100644 --- a/React/Modules/RCTAccessibilityManager.m +++ b/React/Modules/RCTAccessibilityManager.m @@ -15,8 +15,6 @@ NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification = @"RCTAccessibilityManagerDidUpdateMultiplierNotification"; -#if !TARGET_OS_OSX // TODO(macOS ISS#2323203) - static NSString *UIKitCategoryFromJSCategory(NSString *JSCategory) { static NSDictionary *map = nil; @@ -345,4 +343,3 @@ - (RCTAccessibilityManager *)accessibilityManager @end -#endif // TODO(macOS ISS#2323203) From 929b57cb0adabd1d95fa1b3c0b54647275634900 Mon Sep 17 00:00:00 2001 From: React-Native Bot <53619745+rnbot@users.noreply.github.com> Date: Thu, 11 Jun 2020 19:35:29 +0000 Subject: [PATCH 05/57] Applying package update to 0.61.41 ***NO_CI*** --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d2aa7d08b995a..e137b555d996a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-macos", - "version": "0.61.40", + "version": "0.61.41", "description": "[Microsoft Fork] A framework for building native apps using React", "license": "MIT", "repository": { From 33c5b4949c40e57335ebbad9b9578bd91deaba15 Mon Sep 17 00:00:00 2001 From: graytmatterMS <65255457+graytmatterMS@users.noreply.github.com> Date: Tue, 16 Jun 2020 16:25:21 -0700 Subject: [PATCH 06/57] Enabling AccessibilityInfo.setAccessibilityFocus for MacOS (#450) * Attempting to add isVoiceOverEnabled to macOS * Actually completed merge * Added Tester for SetFocus * Enabled setFocus * Clean up console.log * Cleaned up newline * merged and cleaned up comments * Added newlines back in * Added linting changes * Moved props into a single line for eslint. --- .../AccessibilityInfo.macos.js | 4 ++- .../Accessibility/AccessibilityExample.js | 26 +++++++++++++++++++ React/Modules/MacOS/RCTAccessibilityManager.m | 8 ++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js index 0c23d168dd63f2..c7d4251bbadb8c 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js @@ -135,7 +135,9 @@ const AccessibilityInfo = { * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus */ setAccessibilityFocus: function(reactTag: number): void { - warning(false, 'AccessibilityInfo is not supported on this platform.'); + if (NativeAccessibilityManager) { + NativeAccessibilityManager.setAccessibilityFocus(reactTag); + } }, /** diff --git a/RNTester/js/examples/Accessibility/AccessibilityExample.js b/RNTester/js/examples/Accessibility/AccessibilityExample.js index 39ba0ab1bc3ae4..a00d7a77c3949c 100644 --- a/RNTester/js/examples/Accessibility/AccessibilityExample.js +++ b/RNTester/js/examples/Accessibility/AccessibilityExample.js @@ -570,6 +570,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 ( + +