react-native-navigation的迁移库

ComponentEventsObserver.ts 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import isString from 'lodash/isString'
  2. import isNil from 'lodash/isNil'
  3. import uniqueId from 'lodash/uniqueId'
  4. import unset from 'lodash/unset'
  5. import forEach from 'lodash/forEach'
  6. import { EventSubscription } from '../interfaces/EventSubscription';
  7. import {
  8. ComponentDidAppearEvent,
  9. ComponentDidDisappearEvent,
  10. NavigationButtonPressedEvent,
  11. SearchBarUpdatedEvent,
  12. SearchBarCancelPressedEvent,
  13. ComponentEvent,
  14. PreviewCompletedEvent,
  15. ModalDismissedEvent,
  16. ScreenPoppedEvent,
  17. ModalAttemptedToDismissEvent
  18. } from '../interfaces/ComponentEvents';
  19. import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver';
  20. import { Store } from '../components/Store';
  21. import { NavigationComponentListener } from 'react-native-navigation/interfaces/NavigationComponentListener'
  22. type ReactComponentWithIndexing = NavigationComponentListener & Record<string, any>;
  23. export class ComponentEventsObserver {
  24. private listeners: Record<string, Record<string, ReactComponentWithIndexing>> = {};
  25. private alreadyRegistered = false;
  26. constructor(
  27. private readonly nativeEventsReceiver: NativeEventsReceiver,
  28. private readonly store: Store
  29. ) {
  30. this.notifyComponentDidAppear = this.notifyComponentDidAppear.bind(this);
  31. this.notifyComponentDidDisappear = this.notifyComponentDidDisappear.bind(this);
  32. this.notifyNavigationButtonPressed = this.notifyNavigationButtonPressed.bind(this);
  33. this.notifyModalDismissed = this.notifyModalDismissed.bind(this);
  34. this.notifyModalAttemptedToDismiss = this.notifyModalAttemptedToDismiss.bind(this);
  35. this.notifySearchBarUpdated = this.notifySearchBarUpdated.bind(this);
  36. this.notifySearchBarCancelPressed = this.notifySearchBarCancelPressed.bind(this);
  37. this.notifyPreviewCompleted = this.notifyPreviewCompleted.bind(this);
  38. this.notifyScreenPopped = this.notifyScreenPopped.bind(this);
  39. }
  40. public registerOnceForAllComponentEvents() {
  41. if (this.alreadyRegistered) { return; }
  42. this.alreadyRegistered = true;
  43. this.nativeEventsReceiver.registerComponentDidAppearListener(this.notifyComponentDidAppear);
  44. this.nativeEventsReceiver.registerComponentDidDisappearListener(this.notifyComponentDidDisappear);
  45. this.nativeEventsReceiver.registerNavigationButtonPressedListener(this.notifyNavigationButtonPressed);
  46. this.nativeEventsReceiver.registerModalDismissedListener(this.notifyModalDismissed);
  47. this.nativeEventsReceiver.registerModalAttemptedToDismissListener(this.notifyModalAttemptedToDismiss);
  48. this.nativeEventsReceiver.registerSearchBarUpdatedListener(this.notifySearchBarUpdated);
  49. this.nativeEventsReceiver.registerSearchBarCancelPressedListener(this.notifySearchBarCancelPressed);
  50. this.nativeEventsReceiver.registerPreviewCompletedListener(this.notifyPreviewCompleted);
  51. this.nativeEventsReceiver.registerScreenPoppedListener(this.notifyPreviewCompleted);
  52. }
  53. public bindComponent(component: React.Component<any>, componentId?: string): EventSubscription {
  54. const computedComponentId = componentId || component.props.componentId;
  55. if (!isString(computedComponentId)) {
  56. throw new Error(`bindComponent expects a component with a componentId in props or a componentId as the second argument`);
  57. }
  58. return this.registerComponentListener(component as NavigationComponentListener, computedComponentId);
  59. }
  60. public registerComponentListener(listener: NavigationComponentListener, componentId: string): EventSubscription {
  61. if (!isString(componentId)) {
  62. throw new Error(`registerComponentListener expects a componentId as the second argument`);
  63. }
  64. if (isNil(this.listeners[componentId])) {
  65. this.listeners[componentId] = {};
  66. }
  67. const key = uniqueId();
  68. this.listeners[componentId][key] = listener;
  69. return { remove: () => unset(this.listeners[componentId], key) };
  70. }
  71. public unmounted(componentId: string) {
  72. unset(this.listeners, componentId);
  73. }
  74. notifyComponentDidAppear(event: ComponentDidAppearEvent) {
  75. event.passProps = this.store.getPropsForId(event.componentId);
  76. this.triggerOnAllListenersByComponentId(event, 'componentDidAppear');
  77. }
  78. notifyComponentDidDisappear(event: ComponentDidDisappearEvent) {
  79. this.triggerOnAllListenersByComponentId(event, 'componentDidDisappear');
  80. }
  81. notifyNavigationButtonPressed(event: NavigationButtonPressedEvent) {
  82. this.triggerOnAllListenersByComponentId(event, 'navigationButtonPressed');
  83. }
  84. notifyModalDismissed(event: ModalDismissedEvent) {
  85. this.triggerOnAllListenersByComponentId(event, 'modalDismissed');
  86. }
  87. notifyModalAttemptedToDismiss(event: ModalAttemptedToDismissEvent) {
  88. this.triggerOnAllListenersByComponentId(event, 'modalAttemptedToDismiss');
  89. }
  90. notifySearchBarUpdated(event: SearchBarUpdatedEvent) {
  91. this.triggerOnAllListenersByComponentId(event, 'searchBarUpdated');
  92. }
  93. notifySearchBarCancelPressed(event: SearchBarCancelPressedEvent) {
  94. this.triggerOnAllListenersByComponentId(event, 'searchBarCancelPressed');
  95. }
  96. notifyPreviewCompleted(event: PreviewCompletedEvent) {
  97. this.triggerOnAllListenersByComponentId(event, 'previewCompleted');
  98. }
  99. notifyScreenPopped(event: ScreenPoppedEvent) {
  100. this.triggerOnAllListenersByComponentId(event, 'screenPopped');
  101. }
  102. private triggerOnAllListenersByComponentId(event: ComponentEvent, method: string) {
  103. forEach(this.listeners[event.componentId], (component) => {
  104. if (component && component[method]) {
  105. component[method](event);
  106. }
  107. });
  108. }
  109. }