Commit 9d7f406c authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg
Browse files

Merge branch 'fix/i18next-iphonex' into 'master'

Fix i18next-react and iPhone X notch support

See merge request !258
parents 4fe269da aa64df30
......@@ -3,8 +3,8 @@ import React from 'react';
const reacti18next = jest.genMockFromModule('react-i18next');
const translate = () => Component => props => <Component t={s => s} {...props} />;
const withTranslation = () => Component => props => <Component t={s => s} {...props} />;
reacti18next.translate = translate;
reacti18next.withTranslation = withTranslation;
module.exports = reacti18next;
......@@ -7,3 +7,7 @@ NativeModules.RNFirebase = {
NativeModules.RNShare = {
};
jest.mock('react-native-device-info', () => ({
hasNotch: () => false,
}));
......@@ -10,88 +10,97 @@ exports[`StandardHeader component renders correctly on Android 1`] = `
}
}
/>
<View
<RCTSafeAreaView
emulateUnlessSupported={true}
style={
Object {
"alignItems": "center",
"backgroundColor": "#E62272",
"borderBottomColor": "#C2185B",
"borderBottomWidth": 1,
"borderStyle": "solid",
"flexDirection": "row",
"flexWrap": "wrap",
"height": 44,
"justifyContent": "flex-start",
}
}
>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"zIndex": 2,
"alignItems": "center",
"backgroundColor": "#E62272",
"flexDirection": "row",
"flexWrap": "wrap",
"height": 44,
"justifyContent": "flex-start",
}
}
>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"zIndex": 2,
}
}
>
<Text
allowFontScaling={false}
style={
Array [
Object {
"color": undefined,
"fontSize": 24,
},
Object {
"color": "#FFFFFF",
"paddingLeft": 10,
"paddingRight": 16,
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
Object {},
]
}
>
</Text>
</View>
<Text
allowFontScaling={false}
style={
Array [
Object {
"color": undefined,
"fontSize": 24,
},
Object {
"color": "#FFFFFF",
"paddingLeft": 10,
"paddingRight": 16,
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
Object {},
]
Object {
"color": "#FFFFFF",
"fontFamily": "System",
"fontSize": 18,
"fontWeight": "600",
"left": 40,
"position": "absolute",
"right": 40,
"textAlign": "center",
"zIndex": 0,
}
}
>
ThaliApp
</Text>
</View>
<Text
style={
Object {
"color": "#FFFFFF",
"fontFamily": "System",
"fontSize": 18,
"fontWeight": "600",
"left": 40,
"position": "absolute",
"right": 40,
"textAlign": "center",
"zIndex": 0,
}
}
>
ThaliApp
</Text>
<View
style={
Object {
"position": "absolute",
"right": 0,
<View
style={
Object {
"position": "absolute",
"right": 0,
}
}
}
/>
</View>
/>
</View>
</RCTSafeAreaView>
</View>
`;
......@@ -105,87 +114,96 @@ exports[`StandardHeader component renders correctly on iOS 1`] = `
}
}
/>
<View
<RCTSafeAreaView
emulateUnlessSupported={true}
style={
Object {
"alignItems": "center",
"backgroundColor": "#E62272",
"borderBottomColor": "#C2185B",
"borderBottomWidth": 1,
"borderStyle": "solid",
"flexDirection": "row",
"flexWrap": "wrap",
"height": 44,
"justifyContent": "flex-start",
}
}
>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"zIndex": 2,
"alignItems": "center",
"backgroundColor": "#E62272",
"flexDirection": "row",
"flexWrap": "wrap",
"height": 44,
"justifyContent": "flex-start",
}
}
>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"zIndex": 2,
}
}
>
<Text
allowFontScaling={false}
style={
Array [
Object {
"color": undefined,
"fontSize": 24,
},
Object {
"color": "#FFFFFF",
"paddingLeft": 10,
"paddingRight": 16,
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
Object {},
]
}
>
</Text>
</View>
<Text
allowFontScaling={false}
style={
Array [
Object {
"color": undefined,
"fontSize": 24,
},
Object {
"color": "#FFFFFF",
"paddingLeft": 10,
"paddingRight": 16,
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
Object {},
]
Object {
"color": "#FFFFFF",
"fontFamily": "System",
"fontSize": 18,
"fontWeight": "600",
"left": 40,
"position": "absolute",
"right": 40,
"textAlign": "center",
"zIndex": 0,
}
}
>
ThaliApp
</Text>
</View>
<Text
style={
Object {
"color": "#FFFFFF",
"fontFamily": "System",
"fontSize": 18,
"fontWeight": "600",
"left": 40,
"position": "absolute",
"right": 40,
"textAlign": "center",
"zIndex": 0,
}
}
>
ThaliApp
</Text>
<View
style={
Object {
"position": "absolute",
"right": 0,
<View
style={
Object {
"position": "absolute",
"right": 0,
}
}
}
/>
</View>
/>
</View>
</RCTSafeAreaView>
</View>
`;
......@@ -2,7 +2,7 @@ import i18n from '../../app/utils/i18n';
jest.mock('react-i18next', () => ({
reactI18nextModule: {},
initReactI18next: {},
}));
describe('i18n helper', () => {
......
......@@ -76,6 +76,7 @@ android {
}
dependencies {
implementation project(':react-native-device-info')
implementation project(':react-native-screens')
implementation project(':react-native-gesture-handler')
implementation project(':react-native-sentry')
......
......@@ -3,6 +3,7 @@ package com.thaliapp;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.swmansion.rnscreens.RNScreensPackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import cl.json.ShareApplication;
......@@ -37,6 +38,7 @@ public class MainApplication extends Application implements ShareApplication, Re
protected List<ReactPackage> getPackages() {
return Arrays.asList(
new MainReactPackage(),
new RNDeviceInfo(),
new RNScreensPackage(),
new RNGestureHandlerPackage(),
new RNSharePackage(),
......
rootProject.name = 'ThaliApp'
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-screens'
project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-screens/android')
include ':react-native-gesture-handler'
......
......@@ -4,7 +4,7 @@ import {
} from 'react-native';
import { applyMiddleware, createStore } from 'redux';
import { Provider } from 'react-redux';
import { I18nextProvider, translate } from 'react-i18next';
import { I18nextProvider, withTranslation } from 'react-i18next';
import createSagaMiddleware from 'redux-saga';
import firebase from 'react-native-firebase';
import locale from 'react-native-locale-detector';
......@@ -124,4 +124,4 @@ Main.propTypes = {
t: PropTypes.func.isRequired,
};
export default translate('app/App')(Main);
export default withTranslation('app/App')(Main);
import React from 'react';
import { Image, Text, View } from 'react-native';
import { translate } from 'react-i18next';
import { withTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import styles from './style/ErrorScreen';
......@@ -29,4 +29,4 @@ ErrorScreen.propTypes = {
t: PropTypes.func.isRequired,
};
export default translate('components/errorScreen/ErrorScreen')(ErrorScreen);
export default withTranslation('components/errorScreen/ErrorScreen')(ErrorScreen);
......@@ -9,6 +9,7 @@ import {
TextInput,
TouchableOpacity,
View,
SafeAreaView,
} from 'react-native';
import PropTypes from 'prop-types';
......@@ -154,17 +155,19 @@ class SearchHeader extends Component {
animated
barStyle={isSearching ? 'dark-content' : 'light-content'}
/>
<View style={styles.appBar}>
{isAnimating && (
<Animated.View
style={[
styles.animationView, { transform: [{ scale: scaleValue }] }]}
/>
)}
{this.getLeftIcon()}
{this.getCenter()}
{this.getRightIcon()}
</View>
<SafeAreaView style={styles.safeArea}>
<View style={styles.appBar}>
{isAnimating && (
<Animated.View
style={[
styles.animationView, { transform: [{ scale: scaleValue }] }]}
/>
)}
{this.getLeftIcon()}
{this.getCenter()}
{this.getRightIcon()}
</View>
</SafeAreaView>
</View>
);
}
......
import { Dimensions } from 'react-native';
import Colors from '../../../style/Colors';
import StyleSheet from '../../../style/StyleSheet';
import Colors from '../../../style/Colors';
import { STATUSBAR_HEIGHT, APPBAR_HEIGHT }
from '../../standardHeader/style/StandardHeader';
import { APPBAR_HEIGHT, STATUSBAR_HEIGHT } from '../../standardHeader/style/StandardHeader';
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
safeArea: {
backgroundColor: Colors.magenta,
android: {
elevation: 4,
},
ios: {
borderStyle: 'solid',
borderBottomColor: Colors.darkMagenta,
borderBottomWidth: 1,
},
},
appBar: {
backgroundColor: Colors.magenta,
height: APPBAR_HEIGHT + STATUSBAR_HEIGHT,
paddingTop: STATUSBAR_HEIGHT,
justifyContent: 'flex-start',
alignItems: 'center',
flexWrap: 'wrap',
flexDirection: 'row',
elevation: 4,
android: {
height: APPBAR_HEIGHT + STATUSBAR_HEIGHT,
paddingTop: STATUSBAR_HEIGHT,
},
ios: {
height: APPBAR_HEIGHT,
},
},
title: {
color: Colors.white,
......
......@@ -4,7 +4,7 @@ import {
Alert, Image, ImageBackground, Text, TouchableHighlight, View,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { translate } from 'react-i18next';
import { withTranslation } from 'react-i18next';
import Icon from 'react-native-vector-icons/MaterialIcons';
import styles from './style/Sidebar';
import Colors from '../../style/Colors';
......@@ -125,4 +125,4 @@ Sidebar.propTypes = {
openMemberList: PropTypes.func.isRequired,
};
export default translate('components/sidebar/Sidebar')(Sidebar);
export default withTranslation('components/sidebar/Sidebar')(Sidebar);
import React from 'react';
import {
StatusBar, Text, TouchableOpacity, View,
StatusBar, Text, TouchableOpacity, View, SafeAreaView,
} from 'react-native';
import { translate } from 'react-i18next';
import { withTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/MaterialIcons';
......@@ -43,24 +43,26 @@ const StandardHeader = props => (
barStyle="light-content"
/>
</View>
<View style={styles.appBar}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => (props.menu ? props.navigation.toggleDrawer() : props.navigation.goBack())}
>
<Icon
name={props.menu ? 'menu' : 'arrow-back'}
style={styles.icon}
size={24}
/>
</TouchableOpacity>
<Text style={styles.title}>
{sceneToTitle(props.navigation.state.routeName, props.t)}
</Text>
<View style={styles.rightView}>
{props.rightView}
<SafeAreaView style={styles.safeArea}>
<View style={styles.appBar}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => (props.menu ? props.navigation.toggleDrawer() : props.navigation.goBack())}
>
<Icon
name={props.menu ? 'menu' : 'arrow-back'}
style={styles.icon}
size={24}
/>
</TouchableOpacity>
<Text style={styles.title}>
{sceneToTitle(props.navigation.state.routeName, props.t)}
</Text>
<View style={styles.rightView}>
{props.rightView}
</View>
</View>
</View>
</SafeAreaView>
</View>
);
......@@ -76,7 +78,7 @@ StandardHeader.defaultProps = {
menu: false,
};
const StandardHeaderContainer = withNavigation(translate('components/standardHeader/StandardHeader')(StandardHeader));
const StandardHeaderContainer = withNavigation(withTranslation('components/standardHeader/StandardHeader')(StandardHeader));
export default StandardHeaderContainer;
export function withStandardHeader(Component, menu) {
......
import { Platform, StatusBar } from 'react-native';
import DeviceInfo from 'react-native-device-info';
import StyleSheet from '../../../style/StyleSheet';
import Colors from '../../../style/Colors';
export const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 : StatusBar.currentHeight;
// eslint-disable-next-line no-nested-ternary
export const STATUSBAR_HEIGHT = Platform.OS === 'ios'
? DeviceInfo.hasNotch() ? 44 : 20 : StatusBar.currentHeight;
export const APPBAR_HEIGHT = Platform.OS === 'ios' ? 44 : 56;
export const TOTAL_BAR_HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT;
......@@ -19,13 +23,8 @@ const styles = StyleSheet.create({
elevation: 4,
},
},
appBar: {
safeArea: {
backgroundColor: Colors.magenta,
height: APPBAR_HEIGHT,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
flexWrap: 'wrap',
android: {
height: APPBAR_HEIGHT,
elevation: 4,
......@@ -36,6 +35,14 @@ const styles = StyleSheet.create({
borderBottomWidth: 1,
},
},