diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index 73940778356..1e7c70d265a 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -55,6 +55,7 @@ const EventNames: Map< ['highTextContrastChanged', 'highTextContrastDidChange'], ['screenReaderChanged', 'touchExplorationDidChange'], ['accessibilityServiceChanged', 'accessibilityServiceDidChange'], + ['invertColorsChanged', 'invertColorDidChange'], ]) : new Map([ ['announcementFinished', 'announcementFinished'], @@ -138,7 +139,13 @@ const AccessibilityInfo = { */ isInvertColorsEnabled(): Promise { if (Platform.OS === 'android') { - return Promise.resolve(false); + return new Promise((resolve, reject) => { + if (NativeAccessibilityInfoAndroid?.isInvertColorsEnabled != null) { + NativeAccessibilityInfoAndroid.isInvertColorsEnabled(resolve); + } else { + reject(null); + } + }); } else { return new Promise((resolve, reject) => { if (NativeAccessibilityManagerIOS != null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.kt index 6a44b60ed51..4f8ed62c7cd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.kt @@ -86,6 +86,7 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : private var touchExplorationEnabled = false private var accessibilityServiceEnabled = false private var recommendedTimeout = 0 + private var invertColorsEnabled = false init { val appContext = context.applicationContext @@ -111,6 +112,17 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : return parsedValue == 0f } + @get:TargetApi(Build.VERSION_CODES.LOLLIPOP) + private val isInvertColorsEnabledValue: Boolean + get() { + try { + return Settings.Secure.getInt( + contentResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) == 1 + } catch (e: Settings.SettingNotFoundException) { + return false + } + } + @get:TargetApi(Build.VERSION_CODES.LOLLIPOP) private val isHighTextContrastEnabledValue: Boolean get() { @@ -125,6 +137,10 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : successCallback.invoke(reduceMotionEnabled) } + override fun isInvertColorsEnabled(successCallback: Callback) { + successCallback.invoke(invertColorsEnabled) + } + override fun isHighTextContrastEnabled(successCallback: Callback) { successCallback.invoke(highTextContrastEnabled) } @@ -148,6 +164,17 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : } } + private fun updateAndSendInvertColorsChangeEvent() { + val isInvertColorsEnabled = isInvertColorsEnabledValue + if (invertColorsEnabled != isInvertColorsEnabled) { + invertColorsEnabled = isInvertColorsEnabled + val reactApplicationContext = getReactApplicationContextIfActiveOrWarn() + if (reactApplicationContext != null) { + reactApplicationContext.emitDeviceEvent(INVERT_COLOR_EVENT_NAME, invertColorsEnabled) + } + } + } + private fun updateAndSendHighTextContrastChangeEvent() { val isHighTextContrastEnabled = isHighTextContrastEnabledValue if (highTextContrastEnabled != isHighTextContrastEnabled) { @@ -199,6 +226,7 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : updateAndSendAccessibilityServiceChangeEvent(accessibilityManager?.isEnabled == true) updateAndSendReduceMotionChangeEvent() updateAndSendHighTextContrastChangeEvent() + updateAndSendInvertColorsChangeEvent() } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @@ -263,5 +291,6 @@ internal class AccessibilityInfoModule(context: ReactApplicationContext) : private const val ACCESSIBILITY_SERVICE_EVENT_NAME = "accessibilityServiceDidChange" private const val ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_CONSTANT = "high_text_contrast_enabled" // constant is marked with @hide + private const val INVERT_COLOR_EVENT_NAME = "invertColorDidChange" } } diff --git a/packages/react-native/src/private/specs/modules/NativeAccessibilityInfo.js b/packages/react-native/src/private/specs/modules/NativeAccessibilityInfo.js index dfb0a27952a..07b4b17622a 100644 --- a/packages/react-native/src/private/specs/modules/NativeAccessibilityInfo.js +++ b/packages/react-native/src/private/specs/modules/NativeAccessibilityInfo.js @@ -16,6 +16,9 @@ export interface Spec extends TurboModule { +isReduceMotionEnabled: ( onSuccess: (isReduceMotionEnabled: boolean) => void, ) => void; + +isInvertColorsEnabled?: ( + onSuccess: (isInvertColorsEnabled: boolean) => void, + ) => void; +isHighTextContrastEnabled?: ( onSuccess: (isHighTextContrastEnabled: boolean) => void, ) => void; diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index 308ec71e43b..7bbe1c5d8c9 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -1341,12 +1341,6 @@ class EnabledExamples extends React.Component<{}> { eventListener="grayscaleChanged" /> - - - { /> + + + +