Add Icons class (#611)

Creates Icons class to manage when to load icons from native side or react-native-vector-icons.
It also fixes `react-native run-android` #517
This commit is contained in:
Diego Mello 2019-02-07 14:04:41 -02:00 committed by GitHub
parent 2585038112
commit 0f516083f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 91 additions and 59 deletions

View File

@ -1,25 +0,0 @@
import Ionicons from 'react-native-vector-icons/Ionicons';
import { isIOS } from './utils/deviceInfo';
const prefix = isIOS ? 'ios' : 'md';
// icon name from provider: [ size of the uri, icon provider, name to be used later ]
const icons = {
[`${ prefix }-star`]: [25, Ionicons, 'star'],
[`${ prefix }-star-outline`]: [25, Ionicons, 'starOutline'],
[`${ prefix }-more`]: [25, Ionicons, 'more'],
[isIOS ? 'ios-create' : 'md-create']: [25, Ionicons, 'create'],
[`${ prefix }-close`]: [25, Ionicons, 'close']
};
const iconsMap = {};
const iconsLoaded = async() => {
const promises = Object.keys(icons).map((icon) => {
const Provider = icons[icon][1];
return Provider.getImageSource(icon, icons[icon][0], '#FFF');
});
const sources = await Promise.all(promises);
Object.keys(icons).forEach((icon, i) => (iconsMap[icons[icon][2]] = sources[i]));
};
export { iconsLoaded, iconsMap };

View File

@ -1,11 +1,11 @@
import { Component } from 'react';
import { Linking } from 'react-native';
import store from './lib/createStore';
import { appInit } from './actions';
import { iconsLoaded } from './Icons';
import Navigation from './lib/Navigation';
import { deepLinkingOpen } from './actions/deepLinking';
import store from './lib/createStore';
import Icons from './lib/Icons';
import Navigation from './lib/Navigation';
import parseQuery from './lib/methods/helpers/parseQuery';
import { initializePushNotifications } from './push';
import { DEFAULT_HEADER } from './constants/headerOptions';
@ -95,7 +95,7 @@ const handleOpenURL = ({ url }) => {
}
};
iconsLoaded();
Icons.configure();
export default class App extends Component {
constructor(props) {

50
app/lib/Icons.js Normal file
View File

@ -0,0 +1,50 @@
import { Dimensions } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { isIOS, isAndroid } from '../utils/deviceInfo';
const prefix = isIOS ? 'ios' : 'md';
// icon name from provider: [ size of the uri, icon provider, name to be used later ]
const icons = {
[`${ prefix }-star`]: [25, Ionicons, 'star'],
[`${ prefix }-star-outline`]: [25, Ionicons, 'starOutline'],
[`${ prefix }-more`]: [25, Ionicons, 'more'],
[`${ prefix }-create`]: [25, Ionicons, 'create'],
[`${ prefix }-close`]: [25, Ionicons, 'close']
};
if (__DEV__) {
icons[`${ prefix }-settings`] = [25, Ionicons, 'settings'];
icons[`${ prefix }-add`] = [25, Ionicons, 'new_channel'];
icons[`${ prefix }-more`] = [25, Ionicons, 'more'];
if (isAndroid) {
icons[`${ prefix }-search`] = [25, Ionicons, 'search'];
icons[`${ prefix }-arrow-back`] = [25, Ionicons, 'back'];
}
}
class Icons {
constructor() {
this.icons = {};
}
async configure() {
const promises = Object.keys(icons).map((icon) => {
const Provider = icons[icon][1];
return Provider.getImageSource(icon, icons[icon][0], '#FFF');
});
const sources = await Promise.all(promises);
Object.keys(icons).forEach((icon, i) => (this.icons[icons[icon][2]] = sources[i]));
}
isAndroidDev = () => __DEV__ && isAndroid
getSource(icon, native = true) {
if (this.isAndroidDev() || !native) {
return this.icons[icon];
}
return { uri: icon, scale: Dimensions.get('window').scale };
}
}
export default new Icons();

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Text, ScrollView, View, StyleSheet, Image, Dimensions
Text, ScrollView, View, StyleSheet, Image
} from 'react-native';
import SafeAreaView from 'react-native-safe-area-view';
import { RectButton } from 'react-native-gesture-handler';
@ -13,6 +13,7 @@ import { isIOS, isAndroid } from '../utils/deviceInfo';
import LoggedView from './View';
import I18n from '../i18n';
import { DARK_HEADER } from '../constants/headerOptions';
import Icons from '../lib/Icons';
const styles = StyleSheet.create({
container: {
@ -68,7 +69,7 @@ export default class LegalView extends LoggedView {
},
leftButtons: [{
id: 'close',
icon: isAndroid ? { uri: 'back', scale: Dimensions.get('window').scale } : undefined,
icon: isAndroid ? Icons.getSource('back') : undefined,
text: isIOS ? I18n.t('Close') : undefined,
testID: 'legal-view-close'
}]

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Text, View, ScrollView, Image, StyleSheet, Dimensions, Animated, Easing
Text, View, ScrollView, Image, StyleSheet, Animated, Easing
} from 'react-native';
import { connect } from 'react-redux';
import { Base64 } from 'js-base64';
@ -17,6 +17,7 @@ import random from '../utils/random';
import Button from '../containers/Button';
import I18n from '../i18n';
import { DARK_HEADER } from '../constants/headerOptions';
import Icons from '../lib/Icons';
const styles = StyleSheet.create({
container: {
@ -102,7 +103,7 @@ export default class LoginSignupView extends LoggedView {
...DARK_HEADER.topBar,
rightButtons: [{
id: 'more',
icon: { uri: 'more', scale: Dimensions.get('window').scale },
icon: Icons.getSource('more'),
testID: 'welcome-view-more'
}]
}

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Keyboard, Text, ScrollView, View, StyleSheet, Alert, LayoutAnimation, Dimensions
Keyboard, Text, ScrollView, View, StyleSheet, Alert, LayoutAnimation
} from 'react-native';
import { connect } from 'react-redux';
import { Answers } from 'react-native-fabric';
@ -18,6 +18,7 @@ import LoggedView from './View';
import I18n from '../i18n';
import { DARK_HEADER } from '../constants/headerOptions';
import { loginRequest as loginRequestAction } from '../actions/login';
import Icons from '../lib/Icons';
const styles = StyleSheet.create({
buttonsContainer: {
@ -64,7 +65,7 @@ export default class LoginView extends LoggedView {
...DARK_HEADER.topBar,
rightButtons: [{
id: 'more',
icon: { uri: 'more', scale: Dimensions.get('window').scale },
icon: Icons.getSource('more'),
testID: 'login-view-more'
}]
}

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
View, StyleSheet, FlatList, Text, Image, Dimensions
View, StyleSheet, FlatList, Text, Image
} from 'react-native';
import { connect } from 'react-redux';
import SafeAreaView from 'react-native-safe-area-view';
@ -18,6 +18,7 @@ import I18n from '../i18n';
import Touch from '../utils/touch';
import { isIOS, isAndroid } from '../utils/deviceInfo';
import SearchBox from '../containers/SearchBox';
import Icons from '../lib/Icons';
const styles = StyleSheet.create({
safeAreaView: {
@ -57,7 +58,7 @@ export default class NewMessageView extends LoggedView {
topBar: {
leftButtons: [{
id: 'cancel',
icon: isAndroid ? { uri: 'back', scale: Dimensions.get('window').scale } : undefined,
icon: isAndroid ? Icons.getSource('back') : undefined,
text: isIOS ? I18n.t('Cancel') : undefined
}]
}

View File

@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { WebView, Dimensions } from 'react-native';
import { WebView } from 'react-native';
import { connect } from 'react-redux';
import Navigation from '../lib/Navigation';
@ -8,6 +8,7 @@ import RocketChat from '../lib/rocketchat';
import I18n from '../i18n';
import { DARK_HEADER } from '../constants/headerOptions';
import { isIOS, isAndroid } from '../utils/deviceInfo';
import Icons from '../lib/Icons';
const userAgentAndroid = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1';
const userAgent = isIOS ? 'UserAgent' : userAgentAndroid;
@ -23,7 +24,7 @@ export default class OAuthView extends React.PureComponent {
...DARK_HEADER.topBar,
leftButtons: [{
id: 'cancel',
icon: isAndroid ? { uri: 'back', scale: Dimensions.get('window').scale } : undefined,
icon: isAndroid ? Icons.getSource('back') : undefined,
text: isIOS ? I18n.t('Cancel') : undefined
}]
}

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
View, ScrollView, Keyboard, Dimensions, BackHandler
View, ScrollView, Keyboard, BackHandler
} from 'react-native';
import { connect } from 'react-redux';
import Dialog from 'react-native-dialog';
@ -28,6 +28,7 @@ import Avatar from '../../containers/Avatar';
import Touch from '../../utils/touch';
import { appStart as appStartAction } from '../../actions';
import { setUser as setUserAction } from '../../actions/login';
import Icons from '../../lib/Icons';
@connect(state => ({
user: {
@ -50,7 +51,7 @@ export default class ProfileView extends LoggedView {
topBar: {
leftButtons: [{
id: 'settings',
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
icon: Icons.getSource('settings'),
testID: 'rooms-list-view-sidebar'
}],
title: {

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Keyboard, Text, ScrollView, Dimensions, Alert
Keyboard, Text, ScrollView, Alert
} from 'react-native';
import { connect } from 'react-redux';
import SafeAreaView from 'react-native-safe-area-view';
@ -18,6 +18,7 @@ import { DARK_HEADER } from '../constants/headerOptions';
import RocketChat from '../lib/rocketchat';
import { loginRequest as loginRequestAction } from '../actions/login';
import isValidEmail from '../utils/isValidEmail';
import Icons from '../lib/Icons';
const shouldUpdateState = ['name', 'email', 'password', 'username', 'saving'];
@ -33,7 +34,7 @@ export default class RegisterView extends LoggedView {
...DARK_HEADER.topBar,
rightButtons: [{
id: 'more',
icon: { uri: 'more', scale: Dimensions.get('window').scale },
icon: Icons.getSource('more'),
testID: 'register-view-more'
}]
}

View File

@ -17,7 +17,7 @@ import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import { iconsMap } from '../../Icons';
import Icons from '../../lib/Icons';
const PERMISSION_EDIT_ROOM = 'edit-room';
@ -94,7 +94,7 @@ export default class RoomInfoView extends LoggedView {
topBar: {
rightButtons: [{
id: 'edit',
icon: iconsMap.create,
icon: Icons.getSource('create', false),
testID: 'room-info-view-edit-button'
}]
}

View File

@ -25,7 +25,7 @@ import styles from './styles';
import log from '../../utils/log';
import { isIOS } from '../../utils/deviceInfo';
import I18n from '../../i18n';
import { iconsMap } from '../../Icons';
import Icons from '../../lib/Icons';
import ConnectionBadge from '../../containers/ConnectionBadge';
@connect(state => ({
@ -59,11 +59,11 @@ export default class RoomView extends LoggedView {
rightButtons: [{
id: 'more',
testID: 'room-view-header-actions',
icon: iconsMap.more
icon: Icons.getSource('more', false)
}, {
id: 'star',
testID: 'room-view-header-star',
icon: iconsMap.starOutline
icon: Icons.getSource('starOutline', false)
}]
},
blurOnUnmount: true
@ -156,13 +156,13 @@ export default class RoomView extends LoggedView {
const rightButtons = [{
id: 'star',
testID: 'room-view-header-star',
icon: room.f ? iconsMap.star : iconsMap.starOutline
icon: room.f ? Icons.getSource('star', false) : Icons.getSource('starOutline', false)
}];
if (room.t !== 'l') {
rightButtons.unshift({
id: 'more',
testID: 'room-view-header-actions',
icon: iconsMap.more
icon: Icons.getSource('more', false)
});
}
Navigation.mergeOptions(componentId, {

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
View, FlatList, BackHandler, ActivityIndicator, Text, Image, Dimensions, ScrollView, Keyboard, LayoutAnimation
View, FlatList, BackHandler, ActivityIndicator, Text, Image, ScrollView, Keyboard, LayoutAnimation
} from 'react-native';
import { connect } from 'react-redux';
import { isEqual } from 'lodash';
@ -24,6 +24,7 @@ import { toggleSortDropdown as toggleSortDropdownAction, openSearchHeader as ope
import { appStart as appStartAction } from '../../actions';
import debounce from '../../utils/debounce';
import { isIOS, isAndroid } from '../../utils/deviceInfo';
import Icons from '../../lib/Icons';
const ROW_HEIGHT = 70;
const SCROLL_OFFSET = 56;
@ -34,19 +35,19 @@ const keyExtractor = item => item.rid;
const leftButtons = [{
id: 'settings',
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
icon: Icons.getSource('settings'),
testID: 'rooms-list-view-sidebar'
}];
const rightButtons = [{
id: 'newMessage',
icon: { uri: 'new_channel', scale: Dimensions.get('window').scale },
icon: Icons.getSource('new_channel'),
testID: 'rooms-list-view-create-channel'
}];
if (isAndroid) {
rightButtons.push({
id: 'search',
icon: { uri: 'search', scale: Dimensions.get('window').scale }
icon: Icons.getSource('search')
});
}
@ -378,7 +379,7 @@ export default class RoomsListView extends LoggedView {
topBar: {
leftButtons: [{
id: 'back',
icon: { uri: 'back', scale: Dimensions.get('window').scale },
icon: Icons.getSource('back'),
testID: 'rooms-list-view-cancel-search'
}],
rightButtons: []

View File

@ -1,8 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
View, ScrollView, Dimensions, BackHandler
} from 'react-native';
import { View, ScrollView, BackHandler } from 'react-native';
import RNPickerSelect from 'react-native-picker-select';
import { connect } from 'react-redux';
import SafeAreaView from 'react-native-safe-area-view';
@ -21,6 +19,7 @@ import { showErrorAlert, showToast } from '../../utils/info';
import log from '../../utils/log';
import { setUser as setUserAction } from '../../actions/login';
import { appStart as appStartAction } from '../../actions';
import Icons from '../../lib/Icons';
@connect(state => ({
userLanguage: state.login.user && state.login.user.language
@ -35,7 +34,7 @@ export default class SettingsView extends LoggedView {
topBar: {
leftButtons: [{
id: 'settings',
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
icon: Icons.getSource('settings'),
testID: 'rooms-list-view-sidebar'
}],
title: {