Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road to implicitAny part 4 #4497

Merged
merged 12 commits into from
Dec 25, 2018
5 changes: 2 additions & 3 deletions lib/src/adapters/AssetResolver.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import { ImageRequireSource } from 'react-native';
import { ImageRequireSource, Image } from 'react-native';

export class AssetService {
resolveFromRequire(value: ImageRequireSource) {
return resolveAssetSource(value);
return Image.resolveAssetSource(value);
}
}
24 changes: 9 additions & 15 deletions lib/src/adapters/Element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,23 @@ import { requireNativeComponent } from 'react-native';

let RNNElement: React.ComponentType<any>;

export class Element extends React.Component<{ elementId: any; resizeMode?: any; }, any> {
export class Element extends React.Component<{ elementId: any; resizeMode?: any }> {
static propTypes = {
elementId: PropTypes.string.isRequired,
resizeMode: PropTypes.string
resizeMode: PropTypes.string,
};

static defaultProps = {
resizeMode: ''
resizeMode: '',
};

render() {
return (
<RNNElement {...this.props} />
);
return <RNNElement {...this.props} />;
}
}

RNNElement = requireNativeComponent(
'RNNElement',
Element,
{
nativeOnly: {
nativeID: true
}
}
);
RNNElement = requireNativeComponent('RNNElement', Element, {
nativeOnly: {
nativeID: true,
},
});
21 changes: 19 additions & 2 deletions lib/src/adapters/NativeCommandsSender.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import { NativeModules } from 'react-native';

interface NativeCommandsModule {
setRoot(commandId: string, layout: { root: any; modals: any[]; overlays: any[] }): Promise<any>;
setDefaultOptions(options: object): void;
mergeOptions(componentId: string, options: object): void;
push(commandId: string, onComponentId: string, layout: object): Promise<any>;
pop(commandId: string, componentId: string, options?: object): Promise<any>;
popTo(commandId: string, componentId: string, options?: object): Promise<any>;
popToRoot(commandId: string, componentId: string, options?: object): Promise<any>;
setStackRoot(commandId: string, onComponentId: string, layout: object): Promise<any>;
showModal(commandId: string, layout: object): Promise<any>;
dismissModal(commandId: string, componentId: string, options?: object): Promise<any>;
dismissAllModals(commandId: string, options?: object): Promise<any>;
showOverlay(commandId: string, layout: object): Promise<any>;
dismissOverlay(commandId: string, componentId: string): Promise<any>;
getLaunchArgs(commandId: string): Promise<any>;
}

export class NativeCommandsSender {
private readonly nativeCommandsModule;
private readonly nativeCommandsModule: NativeCommandsModule;
constructor() {
this.nativeCommandsModule = NativeModules.RNNBridgeModule;
}

setRoot(commandId: string, layout: { root: any, modals: any[], overlays: any[] }) {
setRoot(commandId: string, layout: { root: any; modals: any[]; overlays: any[] }) {
guyca marked this conversation as resolved.
Show resolved Hide resolved
return this.nativeCommandsModule.setRoot(commandId, layout);
}

Expand Down
46 changes: 33 additions & 13 deletions lib/src/adapters/NativeEventsReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@ import {
SearchBarUpdatedEvent,
SearchBarCancelPressedEvent,
PreviewCompletedEvent,
ModalDismissedEvent
ModalDismissedEvent,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid adding comma character where it's avoidable?

} from '../interfaces/ComponentEvents';
import { CommandCompletedEvent, BottomTabSelectedEvent } from '../interfaces/Events';

export class NativeEventsReceiver {
private emitter;
private emitter: { addListener(event: string, callback: any): EventSubscription };
constructor() {
// NOTE: This try catch is workaround for integration tests
// TODO: mock NativeEventEmitter in integration tests rather done adding try catch in source code
try {
this.emitter = new NativeEventEmitter(NativeModules.RNNEventEmitter);
} catch (e) {
this.emitter = {
addListener: () => {
return {
remove: () => undefined
remove: () => undefined,
};
}
},
};
}
}
Expand All @@ -31,39 +33,57 @@ export class NativeEventsReceiver {
return this.emitter.addListener('RNN.AppLaunched', callback);
}

public registerComponentDidAppearListener(callback: (event: ComponentDidAppearEvent) => void): EventSubscription {
public registerComponentDidAppearListener(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets return these method declarations to single line - I think it's readable enough in a single line.

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

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

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

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

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

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

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

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

public registerBottomTabSelectedListener(callback: (data: BottomTabSelectedEvent) => void): EventSubscription {
public registerBottomTabSelectedListener(
callback: (data: BottomTabSelectedEvent) => void,
): EventSubscription {
return this.emitter.addListener('RNN.BottomTabSelected', callback);
}
}
38 changes: 19 additions & 19 deletions lib/src/adapters/TouchablePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,21 @@ import {
} from 'react-native';

// Polyfill GestureResponderEvent type with additional `force` property (iOS)
interface NativeTouchEventWithForce extends NativeTouchEvent { force: number; }
interface NativeTouchEventWithForce extends NativeTouchEvent {
force: number;
}
interface GestureResponderEventWithForce extends NativeSyntheticEvent<NativeTouchEventWithForce> {}

export interface Props {
children: React.ReactNode;
touchableComponent?: TouchableHighlight | TouchableOpacity | TouchableNativeFeedback | TouchableWithoutFeedback | React.ReactNode;
touchableComponent?:
| TouchableHighlight
| TouchableOpacity
| TouchableNativeFeedback
| TouchableWithoutFeedback
| React.ReactNode;
onPress?: () => void;
onPressIn?: (reactTag?) => void;
onPressIn?: (payload: { reactTag: number | null }) => void;
onPeekIn?: () => void;
onPeekOut?: () => void;
}
Expand All @@ -30,8 +37,7 @@ const PREVIEW_DELAY = 350;
const PREVIEW_MIN_FORCE = 0.1;
const PREVIEW_TIMEOUT = 1250;

export class TouchablePreview extends React.PureComponent<Props, any> {

export class TouchablePreview extends React.PureComponent<Props> {
static propTypes = {
children: PropTypes.node,
touchableComponent: PropTypes.func,
Expand All @@ -48,7 +54,7 @@ export class TouchablePreview extends React.PureComponent<Props, any> {
static peeking = false;

private timeout: number | undefined;
private ts: number = 0;
private touchStartedAt: number = 0;
private onRef = React.createRef<any>();
onPress = () => {
const { onPress } = this.props;
Expand Down Expand Up @@ -79,13 +85,13 @@ export class TouchablePreview extends React.PureComponent<Props, any> {

onTouchStart = (event: GestureResponderEvent) => {
// Store a timstamp of the initial touch start
this.ts = event.nativeEvent.timestamp;
this.touchStartedAt = event.nativeEvent.timestamp;
}

onTouchMove = (event: GestureResponderEventWithForce) => {
clearTimeout(this.timeout);
const { force, timestamp } = event.nativeEvent;
const diff = (timestamp - this.ts);
const diff = timestamp - this.touchStartedAt;

if (force > PREVIEW_MIN_FORCE && diff > PREVIEW_DELAY) {
TouchablePreview.peeking = true;
Expand All @@ -111,21 +117,15 @@ export class TouchablePreview extends React.PureComponent<Props, any> {
const { children, touchableComponent, onPress, onPressIn, ...props } = this.props;

// Default to TouchableWithoutFeedback for iOS if set to TouchableNativeFeedback
const Touchable = (
Platform.OS === 'ios' && touchableComponent instanceof TouchableNativeFeedback
? TouchableWithoutFeedback
: touchableComponent
) as typeof TouchableWithoutFeedback;
const Touchable = (Platform.OS === 'ios' &&
touchableComponent instanceof TouchableNativeFeedback
? TouchableWithoutFeedback
: touchableComponent) as typeof TouchableWithoutFeedback;

// Wrap component with Touchable for handling platform touches
// and a single react View for detecting force and timing.
return (
<Touchable
ref={this.onRef}
onPress={this.onPress}
onPressIn={this.onPressIn}
{...props}
>
<Touchable ref={this.onRef} onPress={this.onPress} onPressIn={this.onPressIn} {...props}>
<View
onTouchStart={this.onTouchStart}
onTouchMove={this.onTouchMove as (event: GestureResponderEvent) => void}
Expand Down
16 changes: 12 additions & 4 deletions lib/src/commands/OptionsProcessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ describe('navigation options', () => {

beforeEach(() => {
const mockedAssetService = mock(AssetService);
when(mockedAssetService.resolveFromRequire(anyNumber())).thenReturn('lol');
when(mockedAssetService.resolveFromRequire(anyNumber())).thenReturn({
height: 100,
scale: 1,
uri: 'lol',
width: 100,
});
const assetService = instance(mockedAssetService);

const mockedColorService = mock(ColorService);
Expand Down Expand Up @@ -60,9 +65,12 @@ describe('navigation options', () => {
};
uut.processOptions(options);
expect(options).toEqual({
backgroundImage: 'lol',
rootBackgroundImage: 'lol',
bottomTab: { icon: 'lol', selectedIcon: 'lol' },
backgroundImage: { height: 100, scale: 1, uri: 'lol', width: 100 },
rootBackgroundImage: { height: 100, scale: 1, uri: 'lol', width: 100 },
bottomTab: {
icon: { height: 100, scale: 1, uri: 'lol', width: 100 },
selectedIcon: { height: 100, scale: 1, uri: 'lol', width: 100 },
},
});
});

Expand Down