BackHandler.ios.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. * @flow
  8. * @format
  9. */
  10. // On Apple TV, this implements back navigation using the TV remote's menu button.
  11. // On iOS, this just implements a stub.
  12. 'use strict';
  13. const Platform = require('./Platform');
  14. const TVEventHandler = require('../Components/AppleTV/TVEventHandler');
  15. type BackPressEventName = 'backPress' | 'hardwareBackPress';
  16. function emptyFunction(): void {}
  17. /**
  18. * Detect hardware button presses for back navigation.
  19. *
  20. * Android: Detect hardware back button presses, and programmatically invoke the default back button
  21. * functionality to exit the app if there are no listeners or if none of the listeners return true.
  22. *
  23. * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented:
  24. * programmatically disable menu button handling
  25. * functionality to exit the app if there are no listeners or if none of the listeners return true.)
  26. *
  27. * iOS: Not applicable.
  28. *
  29. * The event subscriptions are called in reverse order (i.e. last registered subscription first),
  30. * and if one subscription returns true then subscriptions registered earlier will not be called.
  31. *
  32. * Example:
  33. *
  34. * ```javascript
  35. * BackHandler.addEventListener('hardwareBackPress', function() {
  36. * // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here
  37. * // Typically you would use the navigator here to go to the last state.
  38. *
  39. * if (!this.onMainScreen()) {
  40. * this.goBack();
  41. * return true;
  42. * }
  43. * return false;
  44. * });
  45. * ```
  46. */
  47. type TBackHandler = {|
  48. +exitApp: () => void,
  49. +addEventListener: (
  50. eventName: BackPressEventName,
  51. handler: Function,
  52. ) => {remove: () => void, ...},
  53. +removeEventListener: (
  54. eventName: BackPressEventName,
  55. handler: Function,
  56. ) => void,
  57. |};
  58. let BackHandler: TBackHandler;
  59. if (Platform.isTV) {
  60. const _tvEventHandler = new TVEventHandler();
  61. const _backPressSubscriptions = new Set();
  62. _tvEventHandler.enable(this, function(cmp, evt) {
  63. if (evt && evt.eventType === 'menu') {
  64. let invokeDefault = true;
  65. const subscriptions = Array.from(
  66. _backPressSubscriptions.values(),
  67. ).reverse();
  68. for (let i = 0; i < subscriptions.length; ++i) {
  69. if (subscriptions[i]()) {
  70. invokeDefault = false;
  71. break;
  72. }
  73. }
  74. if (invokeDefault) {
  75. BackHandler.exitApp();
  76. }
  77. }
  78. });
  79. BackHandler = {
  80. exitApp: emptyFunction,
  81. addEventListener: function(
  82. eventName: BackPressEventName,
  83. handler: Function,
  84. ): {remove: () => void, ...} {
  85. _backPressSubscriptions.add(handler);
  86. return {
  87. remove: () => BackHandler.removeEventListener(eventName, handler),
  88. };
  89. },
  90. removeEventListener: function(
  91. eventName: BackPressEventName,
  92. handler: Function,
  93. ): void {
  94. _backPressSubscriptions.delete(handler);
  95. },
  96. };
  97. } else {
  98. BackHandler = {
  99. exitApp: emptyFunction,
  100. addEventListener(_eventName: BackPressEventName, _handler: Function) {
  101. return {
  102. remove: emptyFunction,
  103. };
  104. },
  105. removeEventListener(_eventName: BackPressEventName, _handler: Function) {},
  106. };
  107. }
  108. module.exports = BackHandler;