react-native-navigation的迁移库

ComponentEventsObserver.ts 4.3KB

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