Skip to content

Commit

Permalink
Road to implicit any part5 (#4500)
Browse files Browse the repository at this point in the history
- `registerCommandListener` documentation was wrong so that is fixed
- use `uniqueIdProvider` much as possible so we are not duplicating logic
- add `appRegistryService` which makes `componentRegistry` cleaner and also makes testing easier
- type return type of `NativeEventsReceiver.ts` correctly
- add types to `LayoutTreeParser`
- `ComponentRegistry.test.tsx` refactor so it tests only things that is should and not implementation of React Native functions
- fix type `center` prop to be required on `LayoutSideMenu`
- add missing layout props `topTabs` and `externalComponent`
- lots of minor cleaning
  • Loading branch information
henrikra authored and guyca committed Dec 27, 2018
1 parent 565c23a commit ee6dc78
Show file tree
Hide file tree
Showing 21 changed files with 250 additions and 217 deletions.
16 changes: 8 additions & 8 deletions docs/docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
this.navigationEventListener.remove();
}
}

componentDidAppear() {

}
Expand Down Expand Up @@ -66,7 +66,7 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
Expand Down Expand Up @@ -101,7 +101,7 @@ The `commandListener` is called whenever a *Navigation command* (i.e push, pop,

```js
// Subscribe
const commandListener = Navigation.events().registerCommandListener(({ name, params }) => {
const commandListener = Navigation.events().registerCommandListener((name, params) => {

});
...
Expand Down Expand Up @@ -158,7 +158,7 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
Expand Down Expand Up @@ -197,7 +197,7 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
Expand All @@ -220,7 +220,7 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
Expand All @@ -243,7 +243,7 @@ class MyComponent extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}

componentWillUnmount() {
// Not mandatory
if (this.navigationEventListener) {
Expand Down
15 changes: 11 additions & 4 deletions lib/src/Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ComponentWrapper } from './components/ComponentWrapper';
import { OptionsProcessor } from './commands/OptionsProcessor';
import { ColorService } from './adapters/ColorService';
import { AssetService } from './adapters/AssetResolver';
import { AppRegistryService } from './adapters/AppRegistryService';

export class NavigationRoot {
public readonly Element: React.ComponentType<{ elementId: any; resizeMode?: any; }>;
Expand All @@ -45,12 +46,18 @@ export class NavigationRoot {
this.nativeEventsReceiver = new NativeEventsReceiver();
this.uniqueIdProvider = new UniqueIdProvider();
this.componentEventsObserver = new ComponentEventsObserver(this.nativeEventsReceiver);
this.componentRegistry = new ComponentRegistry(this.store, this.componentEventsObserver);
const appRegistryService = new AppRegistryService();
this.componentRegistry = new ComponentRegistry(
this.store,
this.componentEventsObserver,
this.componentWrapper,
appRegistryService
);
this.layoutTreeParser = new LayoutTreeParser();
const optionsProcessor = new OptionsProcessor(this.store, this.uniqueIdProvider, new ColorService(), new AssetService());
this.layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store, optionsProcessor);
this.nativeCommandsSender = new NativeCommandsSender();
this.commandsObserver = new CommandsObserver();
this.commandsObserver = new CommandsObserver(this.uniqueIdProvider);
this.commands = new Commands(
this.nativeCommandsSender,
this.layoutTreeParser,
Expand All @@ -69,7 +76,7 @@ export class NavigationRoot {
* The component itself is a traditional React component extending React.Component.
*/
public registerComponent(componentName: string | number, componentProvider: ComponentProvider, concreteComponentProvider?: ComponentProvider): ComponentProvider {
return this.componentRegistry.registerComponent(componentName, componentProvider, this.componentWrapper, concreteComponentProvider);
return this.componentRegistry.registerComponent(componentName, componentProvider, concreteComponentProvider);
}

/**
Expand All @@ -82,7 +89,7 @@ export class NavigationRoot {
ReduxProvider: any,
reduxStore: any
): ComponentProvider {
return this.componentRegistry.registerComponent(componentName, getComponentClassFunc, this.componentWrapper, undefined, ReduxProvider, reduxStore);
return this.componentRegistry.registerComponent(componentName, getComponentClassFunc, undefined, ReduxProvider, reduxStore);
}

/**
Expand Down
7 changes: 7 additions & 0 deletions lib/src/adapters/AppRegistryService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ComponentProvider, AppRegistry } from 'react-native';

export class AppRegistryService {
registerComponent(appKey: string, getComponentFunc: ComponentProvider) {
AppRegistry.registerComponent(appKey, getComponentFunc);
}
}
10 changes: 3 additions & 7 deletions lib/src/adapters/Element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import * as React from 'react';
import * as PropTypes from 'prop-types';
import { requireNativeComponent } from 'react-native';

let RNNElement: React.ComponentType<any>;

export class Element extends React.Component<{ elementId: any; resizeMode?: any }> {
export class Element extends React.Component<{ elementId: string; resizeMode?: string }> {
static propTypes = {
elementId: PropTypes.string.isRequired,
resizeMode: PropTypes.string
Expand All @@ -19,8 +17,6 @@ export class Element extends React.Component<{ elementId: any; resizeMode?: any
}
}

RNNElement = requireNativeComponent('RNNElement', Element, {
nativeOnly: {
nativeID: true
}
const RNNElement = requireNativeComponent('RNNElement', Element, {
nativeOnly: { nativeID: true }
});
27 changes: 13 additions & 14 deletions lib/src/adapters/NativeEventsReceiver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { NativeModules, NativeEventEmitter } from 'react-native';
import { EventSubscription } from '../interfaces/EventSubscription';
import { NativeModules, NativeEventEmitter, EventEmitter, EmitterSubscription } from 'react-native';
import {
ComponentDidAppearEvent,
ComponentDidDisappearEvent,
Expand All @@ -12,7 +11,7 @@ import {
import { CommandCompletedEvent, BottomTabSelectedEvent } from '../interfaces/Events';

export class NativeEventsReceiver {
private emitter: { addListener(event: string, callback: any): EventSubscription };
private emitter: EventEmitter;
constructor() {
// NOTE: This try catch is workaround for integration tests
// TODO: mock NativeEventEmitter in integration tests rather done adding try catch in source code
Expand All @@ -25,47 +24,47 @@ export class NativeEventsReceiver {
remove: () => undefined
};
}
};
} as any as EventEmitter;
}
}

public registerAppLaunchedListener(callback: () => void): EventSubscription {
public registerAppLaunchedListener(callback: () => void): EmitterSubscription {
return this.emitter.addListener('RNN.AppLaunched', callback);
}

public registerComponentDidAppearListener(callback: (event: ComponentDidAppearEvent) => void): EventSubscription {
public registerComponentDidAppearListener(callback: (event: ComponentDidAppearEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.ComponentDidAppear', callback);
}

public registerComponentDidDisappearListener(callback: (event: ComponentDidDisappearEvent) => void): EventSubscription {
public registerComponentDidDisappearListener(callback: (event: ComponentDidDisappearEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.ComponentDidDisappear', callback);
}

public registerNavigationButtonPressedListener(callback: (event: NavigationButtonPressedEvent) => void): EventSubscription {
public registerNavigationButtonPressedListener(callback: (event: NavigationButtonPressedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.NavigationButtonPressed', callback);
}

public registerModalDismissedListener(callback: (event: ModalDismissedEvent) => void): EventSubscription {
public registerModalDismissedListener(callback: (event: ModalDismissedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.ModalDismissed', callback);
}

public registerSearchBarUpdatedListener(callback: (event: SearchBarUpdatedEvent) => void): EventSubscription {
public registerSearchBarUpdatedListener(callback: (event: SearchBarUpdatedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.SearchBarUpdated', callback);
}

public registerSearchBarCancelPressedListener(callback: (event: SearchBarCancelPressedEvent) => void): EventSubscription {
public registerSearchBarCancelPressedListener(callback: (event: SearchBarCancelPressedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.SearchBarCancelPressed', callback);
}

public registerPreviewCompletedListener(callback: (event: PreviewCompletedEvent) => void): EventSubscription {
public registerPreviewCompletedListener(callback: (event: PreviewCompletedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.PreviewCompleted', callback);
}

public registerCommandCompletedListener(callback: (data: CommandCompletedEvent) => void): EventSubscription {
public registerCommandCompletedListener(callback: (data: CommandCompletedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.CommandCompleted', callback);
}

public registerBottomTabSelectedListener(callback: (data: BottomTabSelectedEvent) => void): EventSubscription {
public registerBottomTabSelectedListener(callback: (data: BottomTabSelectedEvent) => void): EmitterSubscription {
return this.emitter.addListener('RNN.BottomTabSelected', callback);
}
}
2 changes: 1 addition & 1 deletion lib/src/adapters/UniqueIdProvider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as _ from 'lodash';

export class UniqueIdProvider {
generate(prefix: string): string {
generate(prefix?: string): string {
return _.uniqueId(prefix);
}
}
2 changes: 1 addition & 1 deletion lib/src/commands/Commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Commands', () => {

beforeEach(() => {
store = new Store();
commandsObserver = new CommandsObserver();
commandsObserver = new CommandsObserver(new UniqueIdProvider());
mockedNativeCommandsSender = mock(NativeCommandsSender);
nativeCommandsSender = instance(mockedNativeCommandsSender);

Expand Down
12 changes: 6 additions & 6 deletions lib/src/commands/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ export class Commands {
this.commandsObserver.notify('mergeOptions', { componentId, options });
}

public showModal(simpleApi: Layout) {
const input = _.cloneDeep(simpleApi);
const layout = this.layoutTreeParser.parse(input);
this.layoutTreeCrawler.crawl(layout);
public showModal(layout: Layout) {
const layoutCloned = _.cloneDeep(layout);
const layoutNode = this.layoutTreeParser.parse(layoutCloned);
this.layoutTreeCrawler.crawl(layoutNode);

const commandId = this.uniqueIdProvider.generate('showModal');
const result = this.nativeCommandsSender.showModal(commandId, layout);
this.commandsObserver.notify('showModal', { commandId, layout });
const result = this.nativeCommandsSender.showModal(commandId, layoutNode);
this.commandsObserver.notify('showModal', { commandId, layout: layoutNode });
return result;
}

Expand Down
Loading

0 comments on commit ee6dc78

Please sign in to comment.