react-native-navigation的迁移库

ComponentEventsObserver.ts 5.0KB

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