RN-137 Team sidebar (#577)

* Team sidebar

* Update NOTICES.txt

* feedback review
This commit is contained in:
enahum 2017-05-29 15:51:11 -04:00 committed by GitHub
parent f6266c10c5
commit 5b1a68db74
42 changed files with 7097 additions and 191 deletions

View file

@ -12,9 +12,9 @@ android_target := $(filter-out build-android,$(MAKECMDGOALS))
exit 1; \
fi
@echo Getting dependencies using npm
@echo Getting dependencies using yarn
yarn install
yarn install --pure-lockfile
touch $@

View file

@ -8,6 +8,39 @@ This document includes a list of open source components used in Mattermost Mobil
--------
## react-native-swiper
This product contains 'react-native-swiper', A Swiper component for React Native.
* HOMEPAGE:
* https://github.com/leecade/react-native-swiper
* LICENSE:
The MIT License (MIT)
Copyright (c) 2015 斯人
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
## react-native-search-bar
This product contains a modified portion of 'react-native-search-bar', a high-quality iOS native search bar for react native by Zhao Han.
@ -875,22 +908,3 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
## react-native-sentry
Official Sentry client for react-native
* HOMEPAGE
* https://github.com/getsentry/react-native-sentry
* LICENSE
The MIT License (MIT)
Copyright (c) 2017 Sentry
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -3,13 +3,22 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {BackHandler, InteractionManager, Keyboard} from 'react-native';
import {
BackHandler,
InteractionManager,
Keyboard,
View
} from 'react-native';
import Drawer from 'app/components/drawer';
import ChannelDrawerList from 'app/components/channel_drawer_list';
import ChannelDrawerSwiper from 'app/components/channel_drawer_swiper';
import ChannelDrawerTeams from 'app/components/channel_drawer_teams';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
const DRAWER_INITIAL_OFFSET = 40;
export default class ChannelDrawer extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
@ -25,6 +34,7 @@ export default class ChannelDrawer extends PureComponent {
currentChannel: PropTypes.object,
channels: PropTypes.object,
channelMembers: PropTypes.object,
myTeamMembers: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired
};
@ -34,9 +44,12 @@ export default class ChannelDrawer extends PureComponent {
};
state = {
openDrawer: false
openDrawer: false,
openDrawerOffset: DRAWER_INITIAL_OFFSET
};
swiperIndex = 1;
componentDidMount() {
EventEmitter.on('open_channel_drawer', this.openChannelDrawer);
EventEmitter.on('close_channel_drawer', this.closeChannelDrawer);
@ -63,6 +76,7 @@ export default class ChannelDrawer extends PureComponent {
};
handleDrawerClose = () => {
this.resetDrawer();
setTimeout(() => {
InteractionManager.clearInteractionHandle(this.closeLeftHandle);
});
@ -128,20 +142,85 @@ export default class ChannelDrawer extends PureComponent {
});
};
render() {
onPageSelected = (index) => {
this.swiperIndex = index;
};
showTeams = () => {
const teamsCount = Object.keys(this.props.myTeamMembers).length;
if (this.swiperIndex === 1 && teamsCount > 1) {
this.refs.swiper.showTeamsPage();
}
};
resetDrawer = () => {
const teamsCount = Object.keys(this.props.myTeamMembers).length;
if (this.swiperIndex === 0 && teamsCount > 1) {
this.refs.swiper.resetPage();
}
};
renderContent = () => {
const {
children,
currentChannel,
currentTeam,
channels,
channelMembers,
navigator,
myTeamMembers,
theme
} = this.props;
const showTeams = Object.keys(myTeamMembers).length > 1;
let teams;
if (showTeams) {
teams = (
<View style={{flex: 1, marginBottom: 10}}>
<ChannelDrawerTeams
closeChannelDrawer={this.closeChannelDrawer}
myTeamMembers={myTeamMembers}
/>
</View>
);
}
const channelsList = (
<View style={{flex: 1, marginBottom: 10}}>
<ChannelDrawerList
currentTeam={currentTeam}
currentChannel={currentChannel}
channels={channels}
channelMembers={channelMembers}
myTeamMembers={myTeamMembers}
theme={theme}
onSelectChannel={this.selectChannel}
navigator={navigator}
onShowTeams={this.showTeams}
/>
</View>
);
return (
<ChannelDrawerSwiper
ref='swiper'
onPageSelected={this.onPageSelected}
openDrawerOffset={this.state.openDrawerOffset}
showTeams={showTeams}
theme={theme}
>
{teams}
{channelsList}
</ChannelDrawerSwiper>
);
};
render() {
const {children} = this.props;
const {openDrawer, openDrawerOffset} = this.state;
return (
<Drawer
open={this.state.openDrawer}
open={openDrawer}
onOpenStart={this.handleDrawerOpenStart}
onOpen={this.handleDrawerOpen}
onCloseStart={this.handleDrawerCloseStart}
@ -150,22 +229,12 @@ export default class ChannelDrawer extends PureComponent {
type='static'
acceptTap={true}
disabled={false}
content={
<ChannelDrawerList
currentTeam={currentTeam}
currentChannel={currentChannel}
channels={channels}
channelMembers={channelMembers}
theme={theme}
onSelectChannel={this.selectChannel}
navigator={navigator}
/>
}
content={this.renderContent()}
tapToClose={true}
openDrawerOffset={40}
openDrawerOffset={openDrawerOffset}
onRequestClose={this.closeChannelDrawer}
panOpenMask={0.2}
panCloseMask={40}
panCloseMask={openDrawerOffset}
panThreshold={0.25}
acceptPan={true}
negotiatePan={true}

View file

@ -8,7 +8,7 @@ import {handleSelectChannel, setChannelLoading} from 'app/actions/views/channel'
import {getChannelsWithUnreadSection, getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentTeam, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams';
import {viewChannel, markChannelAsRead} from 'mattermost-redux/actions/channels';
@ -21,6 +21,7 @@ function mapStateToProps(state, ownProps) {
currentChannel: getCurrentChannel(state),
channels: getChannelsWithUnreadSection(state),
channelMembers: state.entities.channels.myMembers,
myTeamMembers: getTeamMemberships(state),
theme: getTheme(state)
};
}

View file

@ -16,6 +16,7 @@ import {injectIntl, intlShape} from 'react-intl';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import Badge from 'app/components/badge';
import FormattedText from 'app/components/formatted_text';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@ -33,8 +34,10 @@ class ChannelDrawerList extends Component {
currentTeam: PropTypes.object.isRequired,
currentChannel: PropTypes.object,
intl: intlShape.isRequired,
myTeamMembers: PropTypes.object.isRequired,
navigator: PropTypes.object,
onSelectChannel: PropTypes.func.isRequired,
onShowTeams: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired
};
@ -210,20 +213,20 @@ class ChannelDrawerList extends Component {
if (unreadChannels.length) {
data.push(
this.renderTitle(styles, 'mobile.channel_list.unreads', 'UNREADS', null, unreadChannels.length > 0),
this.renderTitle(styles, 'mobile.channel_list.unreads', 'UNREADS', null, false, unreadChannels.length > 0),
...unreadChannels
);
}
if (favoriteChannels.length) {
data.push(
this.renderTitle(styles, 'sidebar.favorite', 'FAVORITES', null, favoriteChannels.length > 0),
this.renderTitle(styles, 'sidebar.favorite', 'FAVORITES', null, unreadChannels.length > 0, favoriteChannels.length > 0),
...favoriteChannels
);
}
data.push(
this.renderTitle(styles, 'sidebar.channels', 'CHANNELS', this.showMoreChannelsModal, publicChannels.length > 0),
this.renderTitle(styles, 'sidebar.channels', 'CHANNELS', this.showMoreChannelsModal, favoriteChannels.length > 0, publicChannels.length > 0),
...publicChannels
);
@ -232,12 +235,12 @@ class ChannelDrawerList extends Component {
createPrivateChannel = this.createPrivateChannel;
}
data.push(
this.renderTitle(styles, 'sidebar.pg', 'PRIVATE CHANNELS', createPrivateChannel, privateChannels.length > 0),
this.renderTitle(styles, 'sidebar.pg', 'PRIVATE CHANNELS', createPrivateChannel, true, privateChannels.length > 0),
...privateChannels
);
data.push(
this.renderTitle(styles, 'sidebar.direct', 'DIRECT MESSAGES', this.showDirectMessagesModal, directAndGroupChannels.length > 0),
this.renderTitle(styles, 'sidebar.direct', 'DIRECT MESSAGES', this.showDirectMessagesModal, true, directAndGroupChannels.length > 0),
...directAndGroupChannels
);
@ -349,14 +352,15 @@ class ChannelDrawerList extends Component {
return item.title;
};
renderTitle = (styles, id, defaultMessage, action, bottomDivider) => {
renderTitle = (styles, id, defaultMessage, action, topDivider, bottomDivider) => {
const {formatMessage} = this.props.intl;
return {
id,
isTitle: true,
title: (
<View>
{this.renderDivider(styles, 0)}
{topDivider && this.renderDivider(styles, 0)}
<View style={styles.titleContainer}>
<Text style={styles.title}>
{formatMessage({id, defaultMessage}).toUpperCase()}
@ -370,11 +374,20 @@ class ChannelDrawerList extends Component {
};
render() {
if (!this.props.currentChannel) {
const {
currentChannel,
currentTeam,
myTeamMembers,
onShowTeams,
theme
} = this.props;
const {dataSource, showAbove, showBelow} = this.state;
const teamMembers = Object.values(myTeamMembers);
if (!currentChannel) {
return <Text>{'Loading'}</Text>;
}
const {theme} = this.props;
const styles = getStyleSheet(theme);
const settings = (
@ -391,8 +404,7 @@ class ChannelDrawerList extends Component {
);
let above;
let below;
if (this.state.showAbove) {
if (showAbove) {
above = (
<UnreadIndicator
style={[styles.above, {width: (this.width - 40)}]}
@ -407,7 +419,8 @@ class ChannelDrawerList extends Component {
);
}
if (this.state.showBelow) {
let below;
if (showBelow) {
below = (
<UnreadIndicator
style={[styles.below, {width: (this.width - 40)}]}
@ -422,6 +435,66 @@ class ChannelDrawerList extends Component {
);
}
const title = (
<Text
ellipsizeMode='tail'
numberOfLines={1}
style={styles.header}
onPress={onShowTeams}
>
{currentTeam.display_name}
</Text>
);
let badge;
let switcher;
if (teamMembers.length > 1) {
let mentionCount = 0;
let messageCount = 0;
teamMembers.forEach((m) => {
if (m.team_id !== currentTeam.id) {
mentionCount = mentionCount + m.mention_count;
messageCount = messageCount + m.msg_count;
}
});
let badgeCount = mentionCount;
if (!badgeCount && messageCount) {
badgeCount = -1;
}
if (badgeCount !== 0) {
badge = (
<Badge
style={styles.badge}
countStyle={styles.mention}
count={badgeCount}
minHeight={5}
minWidth={5}
/>
);
}
switcher = (
<TouchableHighlight
onPress={() => preventDoubleTap(onShowTeams)}
underlayColor={changeOpacity(theme.sidebarHeaderBg, 0.5)}
>
<View style={styles.switcherContainer}>
<AwesomeIcon
name='chevron-left'
size={12}
color={theme.sidebarHeaderBg}
/>
<View style={styles.switcherDivider}/>
<Text style={styles.switcherTeam}>
{currentTeam.display_name.substr(0, 2).toUpperCase()}
</Text>
</View>
</TouchableHighlight>
);
}
return (
<View
style={styles.container}
@ -429,19 +502,15 @@ class ChannelDrawerList extends Component {
>
<View style={styles.statusBar}>
<View style={styles.headerContainer}>
<Text
ellipsizeMode='tail'
numberOfLines={1}
style={styles.header}
>
{this.props.currentTeam.display_name}
</Text>
{switcher}
{title}
{settings}
{badge}
</View>
</View>
<FlatList
ref='list'
data={this.state.dataSource}
data={dataSource}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
onViewableItemsChanged={this.updateUnreadIndicators}
@ -472,22 +541,27 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
}
})
},
scrollContainer: {
flex: 1
},
headerContainer: {
alignItems: 'center',
backgroundColor: theme.sidebarHeaderBg,
flexDirection: 'row',
height: 44,
paddingLeft: 16
borderBottomWidth: 1,
borderBottomColor: changeOpacity(theme.sidebarHeaderTextColor, 0.10),
...Platform.select({
android: {
height: 46
},
ios: {
height: 44
}
})
},
header: {
color: theme.sidebarHeaderTextColor,
flex: 1,
fontSize: 14,
fontSize: 17,
fontWeight: 'normal',
lineHeight: 16
paddingLeft: 16
},
settingsContainer: {
alignItems: 'center',
@ -516,6 +590,44 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
letterSpacing: 0.8,
lineHeight: 18
},
switcherContainer: {
alignItems: 'center',
backgroundColor: theme.sidebarHeaderTextColor,
borderRadius: 2,
flexDirection: 'row',
height: 32,
justifyContent: 'center',
marginLeft: 16,
paddingHorizontal: 6
},
switcherDivider: {
backgroundColor: theme.sidebarHeaderBg,
height: 15,
marginHorizontal: 6,
width: 1
},
switcherTeam: {
color: theme.sidebarHeaderBg,
fontFamily: 'OpenSans',
fontSize: 14
},
badge: {
backgroundColor: theme.mentionBj,
borderColor: theme.sidebarHeaderBg,
borderRadius: 10,
borderWidth: 1,
flexDirection: 'row',
height: 20,
padding: 3,
position: 'absolute',
left: 5,
top: 0,
width: 20
},
mention: {
color: theme.mentionColor,
fontSize: 10
},
divider: {
backgroundColor: changeOpacity(theme.sidebarText, 0.1),
height: 1

View file

@ -0,0 +1,51 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {ViewPagerAndroid} from 'react-native';
export default class ChannelDrawerSwiper extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired,
onPageSelected: PropTypes.func,
showTeams: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired
};
static defaultProps = {
onPageSelected: () => true
};
swiperPageSelected = (event) => {
this.props.onPageSelected(event.nativeEvent.position);
};
showTeamsPage = () => {
this.refs.swiper.setPage(0);
};
resetPage = () => {
this.refs.swiper.setPageWithoutAnimation(1);
};
render() {
const {
children,
showTeams,
theme
} = this.props;
return (
<ViewPagerAndroid
ref='swiper'
style={{flex: 1, backgroundColor: theme.sidebarBg}}
initialPage={1}
scrollEnabled={showTeams}
onPageSelected={this.swiperPageSelected}
>
{children}
</ViewPagerAndroid>
);
}
}

View file

@ -0,0 +1,69 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Dimensions} from 'react-native';
import Swiper from 'react-native-swiper';
import {changeOpacity} from 'app/utils/theme';
const {height: deviceHeight, width: deviceWidth} = Dimensions.get('window');
export default class ChannelDrawerSwiper extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired,
onPageSelected: PropTypes.func,
openDrawerOffset: PropTypes.number,
showTeams: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired
};
static defaultProps = {
onPageSelected: () => true,
openDrawerOffset: 0
};
swiperPageSelected = (e, state, context) => {
this.props.onPageSelected(context.state.index);
};
showTeamsPage = () => {
this.refs.swiper.scrollBy(-1, true);
};
resetPage = () => {
this.refs.swiper.scrollBy(1, false);
};
render() {
const {
children,
openDrawerOffset,
showTeams,
theme
} = this.props;
return (
<Swiper
ref='swiper'
horizontal={true}
loop={false}
index={1}
onMomentumScrollEnd={this.swiperPageSelected}
paginationStyle={{position: 'relative', bottom: 10}}
width={deviceWidth - openDrawerOffset}
height={deviceHeight}
style={{backgroundColor: theme.sidebarBg}}
activeDotColor={theme.sidebarText}
dotColor={changeOpacity(theme.sidebarText, 0.5)}
removeClippedSubviews={true}
automaticallyAdjustContentInsets={true}
scrollEnabled={showTeams}
showsPagination={showTeams}
>
{children}
</Swiper>
);
}
}

View file

@ -0,0 +1,6 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
// Used to leverage the platform specific components
import ChannelDrawerSwiper from './channel_drawer_swiper';
export default ChannelDrawerSwiper;

View file

@ -0,0 +1,249 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
InteractionManager,
FlatList,
Platform,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import IonIcon from 'react-native-vector-icons/Ionicons';
import Badge from 'app/components/badge';
import FormattedText from 'app/components/formatted_text';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
export default class ChannelDrawerTeams extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
handleTeamChange: PropTypes.func.isRequired
}).isRequired,
canCreateTeams: PropTypes.bool.isRequired,
canJoinTeams: PropTypes.bool.isRequired,
closeChannelDrawer: PropTypes.func.isRequired,
currentTeamId: PropTypes.string.isRequired,
currentUrl: PropTypes.string.isRequired,
myTeamMembers: PropTypes.object.isRequired,
teams: PropTypes.array.isRequired,
theme: PropTypes.object.isRequired
};
selectTeam = (team) => {
const {actions, closeChannelDrawer, currentTeamId} = this.props;
if (team.id === currentTeamId) {
closeChannelDrawer();
} else {
closeChannelDrawer();
InteractionManager.runAfterInteractions(() => {
actions.handleTeamChange(team);
});
}
};
renderItem = ({item}) => {
const {currentTeamId, currentUrl, myTeamMembers, theme} = this.props;
const styles = getStyleSheet(theme);
let current;
let badge;
if (item.id === currentTeamId) {
current = (
<View style={styles.checkmarkContainer}>
<IonIcon
name='md-checkmark'
style={styles.checkmark}
/>
</View>
);
} else {
const member = myTeamMembers[item.id];
let badgeCount = member.mention_count;
if (!badgeCount && member.msg_count) {
badgeCount = -1;
}
if (badgeCount !== 0) {
badge = (
<Badge
style={styles.badge}
countStyle={styles.mention}
count={badgeCount}
minHeight={5}
minWidth={5}
/>
);
}
}
return (
<View style={styles.teamWrapper}>
<TouchableHighlight
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
onPress={() => preventDoubleTap(this.selectTeam, this, item)}
>
<View style={styles.teamContainer}>
<View style={styles.teamIconContainer}>
<Text style={styles.teamIcon}>
{item.display_name.substr(0, 2).toUpperCase()}
</Text>
</View>
<View style={styles.teamNameContainer}>
<Text
numberOfLines={1}
ellipsizeMode='tail'
style={styles.teamName}
>
{item.display_name}
</Text>
<Text
numberOfLines={1}
ellipsizeMode='tail'
style={styles.teamUrl}
>
{`${currentUrl}/${item.name}`}
</Text>
</View>
{current}
</View>
</TouchableHighlight>
{badge}
</View>
);
};
render() {
const {teams, theme} = this.props;
const styles = getStyleSheet(theme);
let moreAction;
return (
<View style={styles.container}>
<View style={styles.statusBar}>
<View style={styles.headerContainer}>
<FormattedText
id='mobile.drawer.teamsTitle'
defaultMessage='Teams'
style={styles.header}
/>
{moreAction}
</View>
</View>
<FlatList
data={teams}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
viewabilityConfig={{
viewAreaCoveragePercentThreshold: 3,
waitForInteraction: false
}}
/>
</View>
);
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return StyleSheet.create({
container: {
backgroundColor: theme.sidebarBg,
flex: 1
},
statusBar: {
backgroundColor: theme.sidebarHeaderBg,
...Platform.select({
ios: {
paddingTop: 20
}
})
},
headerContainer: {
alignItems: 'center',
backgroundColor: theme.sidebarHeaderBg,
flexDirection: 'row',
paddingLeft: 16,
borderBottomWidth: 1,
borderBottomColor: changeOpacity(theme.sidebarHeaderTextColor, 0.10),
...Platform.select({
android: {
height: 46
},
ios: {
height: 44
}
})
},
header: {
color: theme.sidebarHeaderTextColor,
flex: 1,
fontSize: 17,
fontWeight: 'normal'
},
teamWrapper: {
marginTop: 20
},
teamContainer: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
marginHorizontal: 16
},
teamIconContainer: {
alignItems: 'center',
backgroundColor: theme.sidebarText,
borderRadius: 2,
height: 40,
justifyContent: 'center',
width: 40
},
teamIcon: {
color: theme.sidebarBg,
fontFamily: 'OpenSans',
fontSize: 18,
fontWeight: '600'
},
teamNameContainer: {
flex: 1,
flexDirection: 'column',
marginLeft: 10
},
teamName: {
color: theme.sidebarText,
fontSize: 18
},
teamUrl: {
color: changeOpacity(theme.sidebarText, 0.5),
fontSize: 12
},
checkmarkContainer: {
alignItems: 'flex-end'
},
checkmark: {
color: theme.sidebarText,
fontSize: 20
},
badge: {
backgroundColor: theme.mentionBj,
borderColor: theme.sidebarHeaderBg,
borderRadius: 10,
borderWidth: 1,
flexDirection: 'row',
height: 20,
padding: 3,
position: 'absolute',
left: 45,
top: -7.5,
width: 20
},
mention: {
color: theme.mentionColor,
fontSize: 10
}
});
});

View file

@ -0,0 +1,47 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
import {getCurrentTeamId, getMyTeams} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {handleTeamChange} from 'app/actions/views/select_team';
import {getTheme} from 'app/selectors/preferences';
import {removeProtocol} from 'app/utils/url';
import ChannelDrawerTeams from './channel_drawer_teams';
function mapStateToProps(state, ownProps) {
const user = getCurrentUser(state);
function sortTeams(locale, a, b) {
if (a.display_name !== b.display_name) {
return a.display_name.toLowerCase().localeCompare(b.display_name.toLowerCase(), locale, {numeric: true});
}
return a.name.toLowerCase().localeCompare(b.name.toLowerCase(), locale, {numeric: true});
}
return {
canCreateTeams: false,
canJoinTeams: false,
currentTeamId: getCurrentTeamId(state),
currentUrl: removeProtocol(getCurrentUrl(state)),
teams: getMyTeams(state).sort(sortTeams.bind(null, (user.locale))),
theme: getTheme(state),
...ownProps
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
handleTeamChange
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelDrawerTeams);

View file

@ -81,12 +81,9 @@ export default class Mattermost {
handleVersionUpgrade = async () => {
const {dispatch, getState} = store;
// const {closeDrawers, logout, unrenderDrawer} = this.props.actions;
Client4.serverVersion = '';
PushNotification.setApplicationIconBadgeNumber(0);
// closeDrawers();
// unrenderDrawer();
if (getState().entities.general.credentials.token) {
InteractionManager.runAfterInteractions(() => {
logout()(dispatch, getState);

View file

@ -19,11 +19,14 @@ import {getTheme} from 'app/selectors/preferences';
import {preventDoubleTap} from 'app/utils/tap';
import {getUnreadsInCurrentTeam} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
class ChannelDrawerButton extends PureComponent {
static propTypes = {
applicationInitializing: PropTypes.bool.isRequired,
currentTeamId: PropTypes.string.isRequired,
myTeamMembers: PropTypes.object,
theme: PropTypes.object,
messageCount: PropTypes.number,
mentionCount: PropTypes.number
@ -75,14 +78,32 @@ class ChannelDrawerButton extends PureComponent {
};
render() {
if (this.props.applicationInitializing) {
const {
applicationInitializing,
currentTeamId,
mentionCount,
messageCount,
myTeamMembers,
theme
} = this.props;
if (applicationInitializing) {
return null;
}
let badge;
let badgeCount = this.props.mentionCount;
let mentions = mentionCount;
let messages = messageCount;
if (!badgeCount && this.props.messageCount) {
const members = Object.values(myTeamMembers).filter((m) => m.team_id !== currentTeamId);
members.forEach((m) => {
mentions = mentions + m.mention_count;
messages = messages + m.msg_count;
});
let badge;
let badgeCount = mentions;
if (!badgeCount && messages) {
badgeCount = -1;
}
@ -109,7 +130,7 @@ class ChannelDrawerButton extends PureComponent {
<Icon
name='md-menu'
size={25}
color={this.props.theme.sidebarHeaderTextColor}
color={theme.sidebarHeaderTextColor}
/>
{badge}
</View>
@ -158,6 +179,8 @@ const style = StyleSheet.create({
function mapStateToProps(state) {
return {
applicationInitializing: state.views.root.appInitializing,
currentTeamId: getCurrentTeamId(state),
myTeamMembers: getTeamMemberships(state),
theme: getTheme(state),
...getUnreadsInCurrentTeam(state)
};

View file

@ -12,7 +12,6 @@ import {getTheme} from 'app/selectors/preferences';
import Settings from './settings';
function mapStateToProps(state, ownProps) {
const showTeamSelection = Object.keys(state.entities.teams.teams).length > 1;
const {config} = state.entities.general;
return {
@ -21,8 +20,7 @@ function mapStateToProps(state, ownProps) {
theme: getTheme(state),
errors: state.errors,
currentUserId: state.entities.users.currentUserId,
currentTeamId: state.entities.teams.currentTeamId,
showTeamSelection
currentTeamId: state.entities.teams.currentTeamId
};
}

View file

@ -30,7 +30,6 @@ class Settings extends PureComponent {
errors: PropTypes.array.isRequired,
intl: intlShape.isRequired,
navigator: PropTypes.object,
showTeamSelection: PropTypes.bool.isRequired,
theme: PropTypes.object
};
@ -89,21 +88,6 @@ class Settings extends PureComponent {
});
};
goToSelectTeam = () => {
const {intl, navigator, theme} = this.props;
navigator.push({
screen: 'SelectTeam',
title: intl.formatMessage({id: 'mobile.routes.selectTeam', defaultMessage: 'Select Team'}),
animated: true,
backButtonTitle: '',
navigatorStyle: {
navBarTextColor: theme.sidebarHeaderTextColor,
navBarBackgroundColor: theme.sidebarHeaderBg,
navBarButtonColor: theme.sidebarHeaderTextColor
}
});
};
handlePress = (action) => {
preventDoubleTap(action, this);
};
@ -138,7 +122,7 @@ class Settings extends PureComponent {
};
render() {
const {config, showTeamSelection, theme} = this.props;
const {config, theme} = this.props;
const style = getStyleSheet(theme);
return (
@ -153,17 +137,6 @@ class Settings extends PureComponent {
separator={true}
theme={theme}
/>
{showTeamSelection &&
<SettingsItem
defaultMessage='Team Selection'
i18nId='mobile.settings.team_selection'
iconName='ios-people'
iconType='ion'
onPress={() => this.handlePress(this.goToSelectTeam)}
separator={true}
theme={theme}
/>
}
{config.HelpLink &&
<SettingsItem
defaultMessage='Help'

View file

@ -9,3 +9,7 @@ export function isValidUrl(url) {
export function stripTrailingSlashes(url) {
return url.replace(/\/+$/, '').trim();
}
export function removeProtocol(url) {
return url.replace(/(^\w+:|^)\/\//, '');
}

View file

@ -1756,7 +1756,6 @@
"mobile.server_ping_failed": "Cannot connect to the server. Please check your server URL and internet connection.",
"mobile.server_url.invalid_format": "URL must start with http:// or https://",
"mobile.session_expired": "Session Expired: Please log in to continue receiving notifications.",
"mobile.settings.team_selection": "Team Selection",
"more_channels.close": "Close",
"more_channels.create": "Create New Channel",
"more_channels.createClick": "Click 'Create New Channel' to make a new one",

6234
assets/base/i18n/tr.json Normal file

File diff suppressed because it is too large Load diff

BIN
assets/fonts/OpenSans-Bold.ttf Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/fonts/OpenSans-Italic.ttf Executable file

Binary file not shown.

BIN
assets/fonts/OpenSans-Light.ttf Executable file

Binary file not shown.

Binary file not shown.

BIN
assets/fonts/OpenSans-Regular.ttf Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -46,6 +46,16 @@
C035DB50ED2045F09923FFAE /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 04AA5E8EF3B54735A11E3B95 /* MaterialCommunityIcons.ttf */; };
C337E8708D2845C6A8DBB47E /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2DCFD31D3F4A4154822AB532 /* Ionicons.ttf */; };
F006936FC2884C24A1321FC0 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 356C9186FA374641A00EB2EA /* MaterialIcons.ttf */; };
9358B95F95184EE0A4DCE629 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */; };
55C6561DDBBA45929D88B6D1 /* OpenSans-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */; };
D719A67137964F08BE47A5FC /* OpenSans-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3647DF63D6764CF093375861 /* OpenSans-ExtraBold.ttf */; };
0111A42B7F264BCF8CBDE3ED /* OpenSans-ExtraBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FBBEC29EE2D3418D9AC33BD5 /* OpenSans-ExtraBoldItalic.ttf */; };
0C0D24F53F254F75869E5951 /* OpenSans-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 41F3AFE83AAF4B74878AB78A /* OpenSans-Italic.ttf */; };
2D5296A8926B4D7FBAF2D6E2 /* OpenSans-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6561AEAC21CC40B8A72ABB93 /* OpenSans-Light.ttf */; };
F083DB472349411A8E6E7AAD /* OpenSans-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */; };
A08D512E7ADC40CCAD055A9E /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */; };
62A8448264674B4D95A5A7C2 /* OpenSans-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */; };
69AC753E496743BABB7A7124 /* OpenSans-SemiboldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -387,6 +397,16 @@
EE671DF7637347CD8C069819 /* libRNDeviceInfo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNDeviceInfo.a; sourceTree = "<group>"; };
F1F071EE85494E269A50AE88 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
F81F6DC42D394831B4549928 /* libRNSearchBar.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSearchBar.a; sourceTree = "<group>"; };
D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */ = {isa = PBXFileReference; name = "OpenSans-Bold.ttf"; path = "../assets/fonts/OpenSans-Bold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */ = {isa = PBXFileReference; name = "OpenSans-BoldItalic.ttf"; path = "../assets/fonts/OpenSans-BoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
3647DF63D6764CF093375861 /* OpenSans-ExtraBold.ttf */ = {isa = PBXFileReference; name = "OpenSans-ExtraBold.ttf"; path = "../assets/fonts/OpenSans-ExtraBold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
FBBEC29EE2D3418D9AC33BD5 /* OpenSans-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; name = "OpenSans-ExtraBoldItalic.ttf"; path = "../assets/fonts/OpenSans-ExtraBoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
41F3AFE83AAF4B74878AB78A /* OpenSans-Italic.ttf */ = {isa = PBXFileReference; name = "OpenSans-Italic.ttf"; path = "../assets/fonts/OpenSans-Italic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
6561AEAC21CC40B8A72ABB93 /* OpenSans-Light.ttf */ = {isa = PBXFileReference; name = "OpenSans-Light.ttf"; path = "../assets/fonts/OpenSans-Light.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */ = {isa = PBXFileReference; name = "OpenSans-LightItalic.ttf"; path = "../assets/fonts/OpenSans-LightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; name = "OpenSans-Regular.ttf"; path = "../assets/fonts/OpenSans-Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */ = {isa = PBXFileReference; name = "OpenSans-Semibold.ttf"; path = "../assets/fonts/OpenSans-Semibold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */ = {isa = PBXFileReference; name = "OpenSans-SemiboldItalic.ttf"; path = "../assets/fonts/OpenSans-SemiboldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -502,6 +522,16 @@
EDC04CBCF81642219D199CBB /* Octicons.ttf */,
F1F071EE85494E269A50AE88 /* SimpleLineIcons.ttf */,
0A091BF1A3D04650AD306A0D /* Zocial.ttf */,
D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */,
32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */,
3647DF63D6764CF093375861 /* OpenSans-ExtraBold.ttf */,
FBBEC29EE2D3418D9AC33BD5 /* OpenSans-ExtraBoldItalic.ttf */,
41F3AFE83AAF4B74878AB78A /* OpenSans-Italic.ttf */,
6561AEAC21CC40B8A72ABB93 /* OpenSans-Light.ttf */,
BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */,
BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */,
C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */,
0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */,
);
name = Resources;
sourceTree = "<group>";
@ -1191,6 +1221,16 @@
7F292A711E8AB73400A450A3 /* SplashScreenResource in Resources */,
2B4C9B708010475DA575B81D /* SimpleLineIcons.ttf in Resources */,
1BCA51319AC6442991C6A208 /* Zocial.ttf in Resources */,
9358B95F95184EE0A4DCE629 /* OpenSans-Bold.ttf in Resources */,
55C6561DDBBA45929D88B6D1 /* OpenSans-BoldItalic.ttf in Resources */,
D719A67137964F08BE47A5FC /* OpenSans-ExtraBold.ttf in Resources */,
0111A42B7F264BCF8CBDE3ED /* OpenSans-ExtraBoldItalic.ttf in Resources */,
0C0D24F53F254F75869E5951 /* OpenSans-Italic.ttf in Resources */,
2D5296A8926B4D7FBAF2D6E2 /* OpenSans-Light.ttf in Resources */,
F083DB472349411A8E6E7AAD /* OpenSans-LightItalic.ttf in Resources */,
A08D512E7ADC40CCAD055A9E /* OpenSans-Regular.ttf in Resources */,
62A8448264674B4D95A5A7C2 /* OpenSans-Semibold.ttf in Resources */,
69AC753E496743BABB7A7124 /* OpenSans-SemiboldItalic.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -1,84 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>30</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSCameraUsageDescription</key>
<string>Take a Photo or Video and upload it to your mattermost instance</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Upload Photos and Videos to your Mattermost instance</string>
<key>UIAppFonts</key>
<array>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Zocial.ttf</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>30</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSCameraUsageDescription</key>
<string>Take a Photo or Video and upload it to your mattermost instance</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Upload Photos and Videos to your Mattermost instance</string>
<key>UIAppFonts</key>
<array>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Zocial.ttf</string>
<string>OpenSans-Bold.ttf</string>
<string>OpenSans-BoldItalic.ttf</string>
<string>OpenSans-ExtraBold.ttf</string>
<string>OpenSans-ExtraBoldItalic.ttf</string>
<string>OpenSans-Italic.ttf</string>
<string>OpenSans-Light.ttf</string>
<string>OpenSans-LightItalic.ttf</string>
<string>OpenSans-Regular.ttf</string>
<string>OpenSans-Semibold.ttf</string>
<string>OpenSans-SemiboldItalic.ttf</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View file

@ -31,6 +31,7 @@
"react-native-push-notification": "3.0.0",
"react-native-search-bar": "enahum/react-native-search-bar.git",
"react-native-svg": "5.1.8",
"react-native-swiper": "1.5.4",
"react-native-tooltip": "5.0.0",
"react-native-vector-icons": "4.1.1",
"react-redux": "5.0.4",
@ -81,5 +82,10 @@
"start": "node node_modules/react-native/local-cli/cli.js start -- --reset-cache",
"test": "NODE_ENV=test mocha --opts test/mocha.opts",
"postinstall": "make post-install"
},
"rnpm": {
"assets": [
"./assets/fonts"
]
}
}

View file

@ -3526,7 +3526,7 @@ makeerror@1.0.x:
mattermost-redux@mattermost/mattermost-redux#master:
version "0.0.1"
resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/dd0d59b2b29aea9c9e6407b72c8eb6e6e0ba091f"
resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/1755fccae9f6e11899e128f29023b0f7e1475bef"
dependencies:
deep-equal "1.0.1"
harmony-reflect "1.5.1"
@ -4391,6 +4391,10 @@ react-native-svg@5.1.8:
color "^0.11.1"
lodash "^4.16.6"
react-native-swiper@1.5.4:
version "1.5.4"
resolved "https://registry.yarnpkg.com/react-native-swiper/-/react-native-swiper-1.5.4.tgz#a85535b5374ef8d605a7a720e447ac46816ac448"
react-native-tooltip@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-native-tooltip/-/react-native-tooltip-5.0.0.tgz#90477f257081ce168d2a27d2ac29e74759b7a7d6"