From 46e8a13474659e06b9986df9392ee8edb4324582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Sun, 28 Feb 2021 20:29:23 +0100 Subject: [PATCH] [Android] Add isInvertColorsEnabled accessibility info --- .../AccessibilityInfo.android.js | 18 +++++-- .../NativeAccessibilityInfo.js | 3 ++ .../AccessibilityInfoModule.java | 53 +++++++++++++++++++ .../Accessibility/AccessibilityExample.js | 13 ++--- 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js index d619b897254e93..9c62b97ad16570 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js @@ -18,10 +18,12 @@ import {type ElementRef} from 'react'; const REDUCE_MOTION_EVENT = 'reduceMotionDidChange'; const TOUCH_EXPLORATION_EVENT = 'touchExplorationDidChange'; +const INVERT_COLORS_EVENT = 'invertColorsDidChange;'; type AccessibilityEventDefinitions = { reduceMotionChanged: [boolean], screenReaderChanged: [boolean], + invertColorsChanged: [boolean], // alias for screenReaderChanged change: [boolean], }; @@ -55,11 +57,14 @@ const AccessibilityInfo = { return Promise.resolve(false); }, - /** - * iOS only - */ isInvertColorsEnabled: function(): Promise { - return Promise.resolve(false); + return new Promise((resolve, reject) => { + if (NativeAccessibilityInfo) { + NativeAccessibilityInfo.isInvertColorsEnabled(resolve); + } else { + reject(false); + } + }); }, isReduceMotionEnabled: function(): Promise { @@ -118,6 +123,11 @@ const AccessibilityInfo = { REDUCE_MOTION_EVENT, handler, ); + } else if (eventName === 'invertColorsChanged') { + listener = RCTDeviceEventEmitter.addListener( + INVERT_COLORS_EVENT, + handler, + ); } // $FlowFixMe[escaped-generic] diff --git a/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js b/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js index 4810127fd7d48b..73907852463b17 100644 --- a/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js +++ b/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js @@ -15,6 +15,9 @@ export interface Spec extends TurboModule { +isReduceMotionEnabled: ( onSuccess: (isReduceMotionEnabled: boolean) => void, ) => void; + +isInvertColorsEnabled: ( + onSuccess: (isInvertColorsEnabled: boolean) => void, + ) => void; +isTouchExplorationEnabled: ( onSuccess: (isScreenReaderEnabled: boolean) => void, ) => void; diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java index 85a2ac54f2eecb..f59c0a685c3350 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java @@ -62,14 +62,32 @@ public void onChange(boolean selfChange, Uri uri) { } }; + // Listener that is notified when the secure ACCESSIBILITY_DISPLAY_INVERSION_ENABLED. + private final ContentObserver accessibilityDisplayInversionObserver = + new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange) { + this.onChange(selfChange, null); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (getReactApplicationContext().hasActiveCatalystInstance()) { + AccessibilityInfoModule.this.updateAndSendInvertColorsChangeEvent(); + } + } + }; + private @Nullable AccessibilityManager mAccessibilityManager; private @Nullable ReactTouchExplorationStateChangeListener mTouchExplorationStateChangeListener; private final ContentResolver mContentResolver; private boolean mReduceMotionEnabled = false; private boolean mTouchExplorationEnabled = false; + private boolean mInvertColorsEnabled = false; private static final String REDUCE_MOTION_EVENT_NAME = "reduceMotionDidChange"; private static final String TOUCH_EXPLORATION_EVENT_NAME = "touchExplorationDidChange"; + private static final String INVERT_COLORS_EVENT_NAME = "invertColorsDidChange"; public AccessibilityInfoModule(ReactApplicationContext context) { super(context); @@ -79,6 +97,7 @@ public AccessibilityInfoModule(ReactApplicationContext context) { mContentResolver = getReactApplicationContext().getContentResolver(); mTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled(); mReduceMotionEnabled = this.getIsReduceMotionEnabledValue(); + mInvertColorsEnabled = this.getIsInvertColorsEnabled(); mTouchExplorationStateChangeListener = new ReactTouchExplorationStateChangeListener(); } @@ -95,6 +114,15 @@ private boolean getIsReduceMotionEnabledValue() { return value != null && value.equals("0.0"); } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private boolean getIsInvertColorsEnabled() { + String value = + Settings.Secure.getString( + mContentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); + + return value != null && value.equals("1"); + } + @Override public void isReduceMotionEnabled(Callback successCallback) { successCallback.invoke(mReduceMotionEnabled); @@ -105,6 +133,11 @@ public void isTouchExplorationEnabled(Callback successCallback) { successCallback.invoke(mTouchExplorationEnabled); } + @Override + public void isInvertColorsEnabled(Callback successCallback) { + successCallback.invoke(mInvertColorsEnabled); + } + private void updateAndSendReduceMotionChangeEvent() { boolean isReduceMotionEnabled = this.getIsReduceMotionEnabledValue(); @@ -133,6 +166,21 @@ private void updateAndSendTouchExplorationChangeEvent(boolean enabled) { } } + private void updateAndSendInvertColorsChangeEvent() { + boolean isInvertColorsEnabled = this.getIsInvertColorsEnabled(); + + if (mInvertColorsEnabled != isInvertColorsEnabled) { + mInvertColorsEnabled = isInvertColorsEnabled; + + ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); + if (reactApplicationContext != null) { + reactApplicationContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(INVERT_COLORS_EVENT_NAME, mInvertColorsEnabled); + } + } + } + @Override @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void onHostResume() { @@ -140,10 +188,13 @@ public void onHostResume() { mTouchExplorationStateChangeListener); Uri transitionUri = Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); + Uri invertColorsUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); mContentResolver.registerContentObserver(transitionUri, false, animationScaleObserver); + mContentResolver.registerContentObserver(invertColorsUri, false, accessibilityDisplayInversionObserver); updateAndSendTouchExplorationChangeEvent(mAccessibilityManager.isTouchExplorationEnabled()); updateAndSendReduceMotionChangeEvent(); + updateAndSendInvertColorsChangeEvent(); } @Override @@ -153,6 +204,7 @@ public void onHostPause() { mTouchExplorationStateChangeListener); mContentResolver.unregisterContentObserver(animationScaleObserver); + mContentResolver.unregisterContentObserver(accessibilityDisplayInversionObserver); } @Override @@ -160,6 +212,7 @@ public void initialize() { getReactApplicationContext().addLifecycleEventListener(this); updateAndSendTouchExplorationChangeEvent(mAccessibilityManager.isTouchExplorationEnabled()); updateAndSendReduceMotionChangeEvent(); + updateAndSendInvertColorsChangeEvent(); } @Override diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index 22b2c0710eb594..16da98c1ad2d5d 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -761,12 +761,6 @@ class EnabledExamples extends React.Component<{}> { eventListener="grayscaleChanged" /> - - - { eventListener="screenReaderChanged" /> + + + + ); }