AccessibilityInfo.ios.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. * @flow
  9. */
  10. 'use strict';
  11. const Promise = require('../../Promise');
  12. const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter');
  13. import NativeAccessibilityManager from './NativeAccessibilityManager';
  14. const CHANGE_EVENT_NAME = {
  15. announcementFinished: 'announcementFinished',
  16. boldTextChanged: 'boldTextChanged',
  17. grayscaleChanged: 'grayscaleChanged',
  18. invertColorsChanged: 'invertColorsChanged',
  19. reduceMotionChanged: 'reduceMotionChanged',
  20. reduceTransparencyChanged: 'reduceTransparencyChanged',
  21. screenReaderChanged: 'screenReaderChanged',
  22. };
  23. type ChangeEventName = $Keys<{
  24. announcementFinished: string,
  25. boldTextChanged: string,
  26. change: string,
  27. grayscaleChanged: string,
  28. invertColorsChanged: string,
  29. reduceMotionChanged: string,
  30. reduceTransparencyChanged: string,
  31. screenReaderChanged: string,
  32. ...
  33. }>;
  34. const _subscriptions = new Map();
  35. /**
  36. * Sometimes it's useful to know whether or not the device has a screen reader
  37. * that is currently active. The `AccessibilityInfo` API is designed for this
  38. * purpose. You can use it to query the current state of the screen reader as
  39. * well as to register to be notified when the state of the screen reader
  40. * changes.
  41. *
  42. * See https://reactnative.dev/docs/accessibilityinfo.html
  43. */
  44. const AccessibilityInfo = {
  45. /**
  46. * Query whether bold text is currently enabled.
  47. *
  48. * Returns a promise which resolves to a boolean.
  49. * The result is `true` when bold text is enabled and `false` otherwise.
  50. *
  51. * See https://reactnative.dev/docs/accessibilityinfo.html#isBoldTextEnabled
  52. */
  53. isBoldTextEnabled: function(): Promise<boolean> {
  54. return new Promise((resolve, reject) => {
  55. if (NativeAccessibilityManager) {
  56. NativeAccessibilityManager.getCurrentBoldTextState(resolve, reject);
  57. } else {
  58. reject(reject);
  59. }
  60. });
  61. },
  62. /**
  63. * Query whether grayscale is currently enabled.
  64. *
  65. * Returns a promise which resolves to a boolean.
  66. * The result is `true` when grayscale is enabled and `false` otherwise.
  67. *
  68. * See https://reactnative.dev/docs/accessibilityinfo.html#isGrayscaleEnabled
  69. */
  70. isGrayscaleEnabled: function(): Promise<boolean> {
  71. return new Promise((resolve, reject) => {
  72. if (NativeAccessibilityManager) {
  73. NativeAccessibilityManager.getCurrentGrayscaleState(resolve, reject);
  74. } else {
  75. reject(reject);
  76. }
  77. });
  78. },
  79. /**
  80. * Query whether inverted colors are currently enabled.
  81. *
  82. * Returns a promise which resolves to a boolean.
  83. * The result is `true` when invert color is enabled and `false` otherwise.
  84. *
  85. * See https://reactnative.dev/docs/accessibilityinfo.html#isInvertColorsEnabled
  86. */
  87. isInvertColorsEnabled: function(): Promise<boolean> {
  88. return new Promise((resolve, reject) => {
  89. if (NativeAccessibilityManager) {
  90. NativeAccessibilityManager.getCurrentInvertColorsState(resolve, reject);
  91. } else {
  92. reject(reject);
  93. }
  94. });
  95. },
  96. /**
  97. * Query whether reduced motion is currently enabled.
  98. *
  99. * Returns a promise which resolves to a boolean.
  100. * The result is `true` when a reduce motion is enabled and `false` otherwise.
  101. *
  102. * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceMotionEnabled
  103. */
  104. isReduceMotionEnabled: function(): Promise<boolean> {
  105. return new Promise((resolve, reject) => {
  106. if (NativeAccessibilityManager) {
  107. NativeAccessibilityManager.getCurrentReduceMotionState(resolve, reject);
  108. } else {
  109. reject(reject);
  110. }
  111. });
  112. },
  113. /**
  114. * Query whether reduced transparency is currently enabled.
  115. *
  116. * Returns a promise which resolves to a boolean.
  117. * The result is `true` when a reduce transparency is enabled and `false` otherwise.
  118. *
  119. * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceTransparencyEnabled
  120. */
  121. isReduceTransparencyEnabled: function(): Promise<boolean> {
  122. return new Promise((resolve, reject) => {
  123. if (NativeAccessibilityManager) {
  124. NativeAccessibilityManager.getCurrentReduceTransparencyState(
  125. resolve,
  126. reject,
  127. );
  128. } else {
  129. reject(reject);
  130. }
  131. });
  132. },
  133. /**
  134. * Query whether a screen reader is currently enabled.
  135. *
  136. * Returns a promise which resolves to a boolean.
  137. * The result is `true` when a screen reader is enabled and `false` otherwise.
  138. *
  139. * See https://reactnative.dev/docs/accessibilityinfo.html#isScreenReaderEnabled
  140. */
  141. isScreenReaderEnabled: function(): Promise<boolean> {
  142. return new Promise((resolve, reject) => {
  143. if (NativeAccessibilityManager) {
  144. NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject);
  145. } else {
  146. reject(reject);
  147. }
  148. });
  149. },
  150. /**
  151. * Deprecated
  152. *
  153. * Same as `isScreenReaderEnabled`
  154. */
  155. get fetch(): $FlowFixMe {
  156. console.warn(
  157. 'AccessibilityInfo.fetch is deprecated, call AccessibilityInfo.isScreenReaderEnabled instead',
  158. );
  159. return this.isScreenReaderEnabled;
  160. },
  161. /**
  162. * Add an event handler. Supported events:
  163. *
  164. * - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes.
  165. * The argument to the event handler is a boolean. The boolean is `true` when a bold text
  166. * is enabled and `false` otherwise.
  167. * - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes.
  168. * The argument to the event handler is a boolean. The boolean is `true` when a gray scale
  169. * is enabled and `false` otherwise.
  170. * - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle
  171. * changes. The argument to the event handler is a boolean. The boolean is `true` when a invert
  172. * colors is enabled and `false` otherwise.
  173. * - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes.
  174. * The argument to the event handler is a boolean. The boolean is `true` when a reduce
  175. * motion is enabled (or when "Transition Animation Scale" in "Developer options" is
  176. * "Animation off") and `false` otherwise.
  177. * - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency
  178. * toggle changes. The argument to the event handler is a boolean. The boolean is `true`
  179. * when a reduce transparency is enabled and `false` otherwise.
  180. * - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument
  181. * to the event handler is a boolean. The boolean is `true` when a screen
  182. * reader is enabled and `false` otherwise.
  183. * - `announcementFinished`: iOS-only event. Fires when the screen reader has
  184. * finished making an announcement. The argument to the event handler is a
  185. * dictionary with these keys:
  186. * - `announcement`: The string announced by the screen reader.
  187. * - `success`: A boolean indicating whether the announcement was
  188. * successfully made.
  189. *
  190. * See https://reactnative.dev/docs/accessibilityinfo.html#addeventlistener
  191. */
  192. addEventListener: function(
  193. eventName: ChangeEventName,
  194. handler: Function,
  195. ): Object {
  196. let listener;
  197. if (eventName === 'change') {
  198. listener = RCTDeviceEventEmitter.addListener(
  199. CHANGE_EVENT_NAME.screenReaderChanged,
  200. handler,
  201. );
  202. } else if (CHANGE_EVENT_NAME[eventName]) {
  203. listener = RCTDeviceEventEmitter.addListener(eventName, handler);
  204. }
  205. _subscriptions.set(handler, listener);
  206. return {
  207. remove: AccessibilityInfo.removeEventListener.bind(
  208. null,
  209. eventName,
  210. handler,
  211. ),
  212. };
  213. },
  214. /**
  215. * Set accessibility focus to a react component.
  216. *
  217. * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus
  218. */
  219. setAccessibilityFocus: function(reactTag: number): void {
  220. if (NativeAccessibilityManager) {
  221. NativeAccessibilityManager.setAccessibilityFocus(reactTag);
  222. }
  223. },
  224. /**
  225. * Post a string to be announced by the screen reader.
  226. *
  227. * See https://reactnative.dev/docs/accessibilityinfo.html#announceforaccessibility
  228. */
  229. announceForAccessibility: function(announcement: string): void {
  230. if (NativeAccessibilityManager) {
  231. NativeAccessibilityManager.announceForAccessibility(announcement);
  232. }
  233. },
  234. /**
  235. * Remove an event handler.
  236. *
  237. * See https://reactnative.dev/docs/accessibilityinfo.html#removeeventlistener
  238. */
  239. removeEventListener: function(
  240. eventName: ChangeEventName,
  241. handler: Function,
  242. ): void {
  243. const listener = _subscriptions.get(handler);
  244. if (!listener) {
  245. return;
  246. }
  247. listener.remove();
  248. _subscriptions.delete(handler);
  249. },
  250. };
  251. module.exports = AccessibilityInfo;