Browse Source

Add missing typescript interfaces (#6203)

* Add missing typescript interfaces

* Fix tsconfig

* Fix ts imports

* Remove NavigationListener

* Add Navigation.events().registerComponentListener()

* Avoid breaking changes in typescript

* Export NavigationComponentProps
Yogev Ben David 4 years ago
parent
commit
ec7f32404d
No account linked to committer's email address

+ 14
- 0
lib/src/events/ComponentEventsObserver.test.tsx View File

221
     expect(willUnmountFn).toHaveBeenCalledTimes(1);
221
     expect(willUnmountFn).toHaveBeenCalledTimes(1);
222
   });
222
   });
223
 
223
 
224
+  it(`registerComponentListener accepts listener object`, () => {
225
+    const tree = renderer.create(<UnboundScreen />);
226
+    const didAppearListenerFn = jest.fn();
227
+    uut.registerComponentListener({
228
+      componentDidAppear: didAppearListenerFn
229
+    }, 'myCompId')
230
+
231
+    expect(tree.toJSON()).toBeDefined();
232
+    expect(didAppearListenerFn).not.toHaveBeenCalled();
233
+
234
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
235
+    expect(didAppearListenerFn).toHaveBeenCalledTimes(1);
236
+  });
237
+
224
   it(`componentDidAppear should receive component props from store`, () => {
238
   it(`componentDidAppear should receive component props from store`, () => {
225
     const event = {
239
     const event = {
226
       componentId: 'myCompId',
240
       componentId: 'myCompId',

+ 14
- 5
lib/src/events/ComponentEventsObserver.ts View File

18
 } from '../interfaces/ComponentEvents';
18
 } from '../interfaces/ComponentEvents';
19
 import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver';
19
 import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver';
20
 import { Store } from '../components/Store';
20
 import { Store } from '../components/Store';
21
+import { NavigationComponentListener } from 'react-native-navigation/interfaces/NavigationComponentListener'
21
 
22
 
22
-type ReactComponentWithIndexing = React.Component<any> & Record<string, any>;
23
+type ReactComponentWithIndexing = NavigationComponentListener & Record<string, any>;
23
 
24
 
24
 export class ComponentEventsObserver {
25
 export class ComponentEventsObserver {
25
   private listeners: Record<string, Record<string, ReactComponentWithIndexing>> = {};
26
   private listeners: Record<string, Record<string, ReactComponentWithIndexing>> = {};
60
     if (!isString(computedComponentId)) {
61
     if (!isString(computedComponentId)) {
61
       throw new Error(`bindComponent expects a component with a componentId in props or a componentId as the second argument`);
62
       throw new Error(`bindComponent expects a component with a componentId in props or a componentId as the second argument`);
62
     }
63
     }
63
-    if (isNil(this.listeners[computedComponentId])) {
64
-      this.listeners[computedComponentId] = {};
64
+    
65
+    return this.registerComponentListener(component as NavigationComponentListener, computedComponentId);
66
+  }
67
+
68
+  public registerComponentListener(listener: NavigationComponentListener, componentId: string): EventSubscription {
69
+    if (!isString(componentId)) {
70
+      throw new Error(`registerComponentListener expects a componentId as the second argument`);
71
+    }
72
+    if (isNil(this.listeners[componentId])) {
73
+      this.listeners[componentId] = {};
65
     }
74
     }
66
     const key = uniqueId();
75
     const key = uniqueId();
67
-    this.listeners[computedComponentId][key] = component;
76
+    this.listeners[componentId][key] = listener;
68
 
77
 
69
-    return { remove: () => unset(this.listeners[computedComponentId], key) };
78
+    return { remove: () => unset(this.listeners[componentId], key) };
70
   }
79
   }
71
 
80
 
72
   public unmounted(componentId: string) {
81
   public unmounted(componentId: string) {

+ 10
- 1
lib/src/events/EventsRegistry.test.tsx View File

2
 import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
2
 import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
3
 import { CommandsObserver } from './CommandsObserver';
3
 import { CommandsObserver } from './CommandsObserver';
4
 import { UniqueIdProvider } from '../adapters/UniqueIdProvider';
4
 import { UniqueIdProvider } from '../adapters/UniqueIdProvider';
5
+import { NavigationComponent } from '../interfaces/NavigationComponent';
6
+import { NavigationComponentListener } from 'react-native-navigation/interfaces/NavigationComponentListener';
5
 
7
 
6
 describe('EventsRegistry', () => {
8
 describe('EventsRegistry', () => {
7
   let uut: EventsRegistry;
9
   let uut: EventsRegistry;
117
     const subscription = {};
119
     const subscription = {};
118
     mockScreenEventsRegistry.bindComponent = jest.fn();
120
     mockScreenEventsRegistry.bindComponent = jest.fn();
119
     mockScreenEventsRegistry.bindComponent.mockReturnValueOnce(subscription);
121
     mockScreenEventsRegistry.bindComponent.mockReturnValueOnce(subscription);
120
-    expect(uut.bindComponent({} as React.Component<any>)).toEqual(subscription);
122
+    expect(uut.bindComponent({} as NavigationComponent<any>)).toEqual(subscription);
123
+  });
124
+
125
+  it(`delegates registerComponentListener to ComponentObserver`, () => {
126
+    const subscription = {};
127
+    mockScreenEventsRegistry.registerComponentListener = jest.fn();
128
+    mockScreenEventsRegistry.registerComponentListener.mockReturnValueOnce(subscription);
129
+    expect(uut.registerComponentListener({} as NavigationComponentListener, 'componentId')).toEqual(subscription);
121
   });
130
   });
122
 
131
 
123
   it('delegates screenPopped to nativeEventsReceiver', () => {
132
   it('delegates screenPopped to nativeEventsReceiver', () => {

+ 8
- 0
lib/src/events/EventsRegistry.ts View File

21
   BottomTabLongPressedEvent,
21
   BottomTabLongPressedEvent,
22
   BottomTabPressedEvent
22
   BottomTabPressedEvent
23
 } from '../interfaces/Events';
23
 } from '../interfaces/Events';
24
+import { NavigationComponentListener } from 'react-native-navigation/interfaces/NavigationComponentListener';
24
 
25
 
25
 export class EventsRegistry {
26
 export class EventsRegistry {
26
   constructor(
27
   constructor(
134
     return this.componentEventsObserver.bindComponent(component, componentId);
135
     return this.componentEventsObserver.bindComponent(component, componentId);
135
   }
136
   }
136
 
137
 
138
+  public registerComponentListener(
139
+    listener: NavigationComponentListener,
140
+    componentId: string
141
+  ): EventSubscription {
142
+    return this.componentEventsObserver.registerComponentListener(listener, componentId);
143
+  }
144
+
137
   public registerScreenPoppedListener(
145
   public registerScreenPoppedListener(
138
     callback: (event: ScreenPoppedEvent) => void
146
     callback: (event: ScreenPoppedEvent) => void
139
   ): EmitterSubscription {
147
   ): EmitterSubscription {

+ 2
- 0
lib/src/index.ts View File

9
 export * from './interfaces/EventSubscription';
9
 export * from './interfaces/EventSubscription';
10
 export * from './interfaces/Layout';
10
 export * from './interfaces/Layout';
11
 export * from './interfaces/Options';
11
 export * from './interfaces/Options';
12
+export * from './interfaces/NavigationComponent';
13
+export * from './interfaces/NavigationComponentProps';

+ 26
- 0
lib/src/interfaces/NavigationComponent.ts View File

1
+import React from 'react';
2
+import {
3
+  NavigationButtonPressedEvent,
4
+  ModalDismissedEvent,
5
+  ModalAttemptedToDismissEvent,
6
+  SearchBarUpdatedEvent,
7
+  SearchBarCancelPressedEvent,
8
+  PreviewCompletedEvent,
9
+  ScreenPoppedEvent,
10
+  ComponentDidAppearEvent,
11
+  ComponentDidDisappearEvent,
12
+} from './ComponentEvents';
13
+import { NavigationComponentProps } from './NavigationComponentProps';
14
+
15
+export class NavigationComponent<Props = {}, State = {}, Snapshot = any>
16
+  extends React.Component<Props & NavigationComponentProps, State, Snapshot> {
17
+    componentDidAppear(_event: ComponentDidAppearEvent) {}
18
+    componentDidDisappear(_event: ComponentDidDisappearEvent) {}
19
+    navigationButtonPressed(_event: NavigationButtonPressedEvent) {}
20
+    modalDismissed(_event: ModalDismissedEvent) {}
21
+    modalAttemptedToDismiss(_event: ModalAttemptedToDismissEvent) {}
22
+    searchBarUpdated(_event: SearchBarUpdatedEvent) {}
23
+    searchBarCancelPressed(_event: SearchBarCancelPressedEvent) {}
24
+    previewCompleted(_event: PreviewCompletedEvent) {}
25
+    screenPopped(_event: ScreenPoppedEvent) {}
26
+  }

+ 23
- 0
lib/src/interfaces/NavigationComponentListener.ts View File

1
+import {
2
+  NavigationButtonPressedEvent,
3
+  ModalDismissedEvent,
4
+  ModalAttemptedToDismissEvent,
5
+  SearchBarUpdatedEvent,
6
+  SearchBarCancelPressedEvent,
7
+  PreviewCompletedEvent,
8
+  ScreenPoppedEvent,
9
+  ComponentDidAppearEvent,
10
+  ComponentDidDisappearEvent,
11
+} from './ComponentEvents';
12
+
13
+export interface NavigationComponentListener {
14
+    componentDidAppear? : (_event: ComponentDidAppearEvent) => void
15
+    componentDidDisappear? : (_event: ComponentDidDisappearEvent) => void
16
+    navigationButtonPressed? : (_event: NavigationButtonPressedEvent) => void
17
+    modalDismissed? : (_event: ModalDismissedEvent) => void
18
+    modalAttemptedToDismiss? : (_event: ModalAttemptedToDismissEvent) => void
19
+    searchBarUpdated? : (_event: SearchBarUpdatedEvent) => void
20
+    searchBarCancelPressed? : (_event: SearchBarCancelPressedEvent) => void
21
+    previewCompleted? : (_event: PreviewCompletedEvent) => void
22
+    screenPopped? : (_event: ScreenPoppedEvent) => void
23
+  }

+ 3
- 0
lib/src/interfaces/NavigationComponentProps.ts View File

1
+export interface NavigationComponentProps {
2
+  componentId: string;
3
+}

+ 2
- 2
playground/src/screens/index.js View File

11
 function registerScreens() {
11
 function registerScreens() {
12
   Navigation.registerComponent(Screens.Alert, () => require('./Alert'));
12
   Navigation.registerComponent(Screens.Alert, () => require('./Alert'));
13
   Navigation.registerComponent(Screens.CocktailDetailsScreen, () => require('./sharedElementTransition/CocktailDetailsScreen'));
13
   Navigation.registerComponent(Screens.CocktailDetailsScreen, () => require('./sharedElementTransition/CocktailDetailsScreen'));
14
-  Navigation.registerComponent(Screens.CocktailsListScreen, () => require('./sharedElementTransition/CocktailsListScreen'));
15
-  Navigation.registerComponent(Screens.CocktailsListMasterScreen, () => require('./splitView/CocktailsListMasterScreen'));
14
+  Navigation.registerComponent(Screens.CocktailsListScreen, () => require('./sharedElementTransition/CocktailsListScreen').default);
15
+  Navigation.registerComponent(Screens.CocktailsListMasterScreen, () => require('./splitView/CocktailsListMasterScreen').default);
16
   Navigation.registerComponent(Screens.EventsOverlay, () => require('./StaticLifecycleOverlay').StaticLifecycleOverlay);
16
   Navigation.registerComponent(Screens.EventsOverlay, () => require('./StaticLifecycleOverlay').StaticLifecycleOverlay);
17
   Navigation.registerComponent(Screens.EventsScreen, () => require('./StaticEventsScreen'));
17
   Navigation.registerComponent(Screens.EventsScreen, () => require('./StaticEventsScreen'));
18
   Navigation.registerComponent(Screens.ExternalComponent, () => require('./ExternalComponentScreen'));
18
   Navigation.registerComponent(Screens.ExternalComponent, () => require('./ExternalComponentScreen'));

playground/src/screens/sharedElementTransition/CocktailsListScreen.js → playground/src/screens/sharedElementTransition/CocktailsListScreen.tsx View File

1
 const React = require('react');
1
 const React = require('react');
2
-const { Component } = require('react');
2
+import { NavigationComponent } from 'react-native-navigation';
3
 const CocktailsView = require('./CocktailsView')
3
 const CocktailsView = require('./CocktailsView')
4
 const { Platform } = require('react-native');
4
 const { Platform } = require('react-native');
5
 const Navigation = require('../../services/Navigation');
5
 const Navigation = require('../../services/Navigation');
8
 const LONG_DURATION = 350 * MULTIPLIER
8
 const LONG_DURATION = 350 * MULTIPLIER
9
 const SHORT_DURATION = 190 * MULTIPLIER
9
 const SHORT_DURATION = 190 * MULTIPLIER
10
 
10
 
11
-class CocktailsListScreen extends Component {
11
+export default class CocktailsListScreen extends NavigationComponent {
12
   static options() {
12
   static options() {
13
     return {
13
     return {
14
       ...Platform.select({
14
       ...Platform.select({
35
     );
35
     );
36
   }
36
   }
37
 
37
 
38
-  update = (item) => {
38
+  update = (item: any) => {
39
     Navigation.updateProps('DETAILS_COMPONENT_ID', item);
39
     Navigation.updateProps('DETAILS_COMPONENT_ID', item);
40
   }
40
   }
41
 
41
 
42
-  pushCocktailDetails = (item) => {
42
+  pushCocktailDetails = (item: any) => {
43
     Navigation.push(
43
     Navigation.push(
44
       this,
44
       this,
45
       {
45
       {
94
     )
94
     )
95
   }
95
   }
96
 }
96
 }
97
-module.exports = CocktailsListScreen;
97
+

playground/src/screens/splitView/CocktailsListMasterScreen.js → playground/src/screens/splitView/CocktailsListMasterScreen.tsx View File

3
 const { Platform } = require('react-native');
3
 const { Platform } = require('react-native');
4
 const Navigation = require('../../services/Navigation');
4
 const Navigation = require('../../services/Navigation');
5
 const Screens = require('../Screens');
5
 const Screens = require('../Screens');
6
-const CocktailsListScreen = require('../sharedElementTransition/CocktailsListScreen');
6
+import CocktailsListScreen from '../sharedElementTransition/CocktailsListScreen';
7
+import { NavigationButtonPressedEvent } from 'react-native-navigation';
8
+
7
 const {
9
 const {
8
   PUSH_MASTER_BTN
10
   PUSH_MASTER_BTN
9
 } = require('../../testIDs');
11
 } = require('../../testIDs');
10
 
12
 
11
-class CocktailsListMasterScreen extends CocktailsListScreen {
13
+export default class CocktailsListMasterScreen extends CocktailsListScreen {
12
   static options() {
14
   static options() {
13
     return {
15
     return {
14
       ...Platform.select({
16
       ...Platform.select({
32
     }
34
     }
33
   }
35
   }
34
 
36
 
35
-  constructor(props) {
37
+  constructor(props: any) {
36
     super(props);
38
     super(props);
37
     Navigation.events().bindComponent(this);
39
     Navigation.events().bindComponent(this);
38
   }
40
   }
39
 
41
 
40
-  navigationButtonPressed({buttonId}) {
41
-    if (buttonId === 'pushMaster') {
42
+  navigationButtonPressed(event: NavigationButtonPressedEvent) {
43
+    if (event.buttonId === 'pushMaster') {
42
       Navigation.push(this, Screens.Pushed)
44
       Navigation.push(this, Screens.Pushed)
43
     }
45
     }
44
   }
46
   }
52
     );
54
     );
53
   }
55
   }
54
 
56
 
55
-  updateDetailsScreen = (item) => {
57
+  updateDetailsScreen = (item: any) => {
56
     Navigation.updateProps('DETAILS_COMPONENT_ID', item);
58
     Navigation.updateProps('DETAILS_COMPONENT_ID', item);
57
   }
59
   }
58
 }
60
 }
59
-
60
-module.exports = CocktailsListMasterScreen;

+ 2
- 2
scripts/build.js View File

7
 function run() {
7
 function run() {
8
     if (isWindows) {
8
     if (isWindows) {
9
         exec.execSync(`del /F /S /Q lib\\dist`);
9
         exec.execSync(`del /F /S /Q lib\\dist`);
10
-        exec.execSync(`tsc`);
10
+        exec.execSync(`tsc --project tsconfig.build.json`);
11
     } else {
11
     } else {
12
-        exec.execSync(`rm -rf ./lib/dist && tsc`);
12
+        exec.execSync(`rm -rf ./lib/dist && tsc --project tsconfig.build.json`);
13
     }
13
     }
14
 }
14
 }

+ 1
- 1
scripts/start-windows.js View File

5
 function run() {
5
 function run() {
6
   // exec.killPort(8081);
6
   // exec.killPort(8081);
7
   // exec.execSync(`rd "./lib/dist" /Q/S`);
7
   // exec.execSync(`rd "./lib/dist" /Q/S`);
8
-  exec.execSync(`"./node_modules/.bin/tsc"`);
8
+  exec.execSync(`"./node_modules/.bin/tsc --project tsconfig.build.json"`);
9
   exec.execSync(`adb reverse tcp:8081 tcp:8081`);
9
   exec.execSync(`adb reverse tcp:8081 tcp:8081`);
10
   exec.execSync(`node ./node_modules/react-native/local-cli/cli.js start`);
10
   exec.execSync(`node ./node_modules/react-native/local-cli/cli.js start`);
11
 }
11
 }

+ 2
- 2
scripts/watch.js View File

7
 function run() {
7
 function run() {
8
     if (isWindows) {
8
     if (isWindows) {
9
         exec.execSync(`del /F /S /Q lib\\dist`);
9
         exec.execSync(`del /F /S /Q lib\\dist`);
10
-        exec.execSync(`tsc --watch`);
10
+        exec.execSync(`tsc --project tsconfig.build.json --watch`);
11
     } else {
11
     } else {
12
-        exec.execSync(`rm -rf ./lib/dist && tsc --watch`);
12
+        exec.execSync(`rm -rf ./lib/dist && tsc --project tsconfig.build.json --watch`);
13
     }
13
     }
14
 }
14
 }

+ 6
- 0
tsconfig.build.json View File

1
+{
2
+  "extends": "./tsconfig.json",
3
+  "exclude": [
4
+    "./playground/**/*"
5
+  ]
6
+}

+ 8
- 2
tsconfig.json View File

15
       "react",
15
       "react",
16
       "react-native",
16
       "react-native",
17
       "react-test-renderer"
17
       "react-test-renderer"
18
-    ]
18
+    ],
19
+    "baseUrl": ".",
20
+    "paths": {
21
+      "react-native-navigation": ["lib/src/"],
22
+      "react-native-navigation/*": ["lib/src/*"]
23
+    }
19
   },
24
   },
20
   "include": [
25
   "include": [
21
-    "./lib/src/**/*"
26
+    "./lib/src/**/*",
27
+    "./playground/**/*"
22
   ]
28
   ]
23
 }
29
 }