Platform dependent search bar and ui fixes (#205)

* Platform dependent search bar and ui fixes

* Set events in default props

* Update NOTICE.txt

* Channel info favorite (#210)

* Enable toggling of favorite channel from channel_info

* Change this binding

* Handle favorite toggle with state

* feedback review

* removed unnecessary view
This commit is contained in:
enahum 2017-02-01 11:38:32 -03:00 committed by GitHub
parent a7d7c4b459
commit 71b2ecd394
13 changed files with 550 additions and 131 deletions

View file

@ -8,6 +8,8 @@ This document includes a list of open source components used in Mattermost Mobil
--------
## fbjs
This product contains a modified portion of 'fbjs', a collection of JavaScript utilities by Facebook, Inc.
* HOMEPAGE:
@ -49,6 +51,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
## 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.
* HOMEPAGE:
* https://github.com/umhan35/react-native-search-bar
* LICENSE:
The MIT License (MIT)
Copyright (c) 2015-2016 Zhao Han
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.
---
## harmony-reflect
[Note: the software referenced below is made available under two licenses. Mattermost, Inc. has elected to license the software pursuant to the Apache License, Version 2.0.]

View file

@ -3,7 +3,7 @@
import React from 'react';
import {Alert, StyleSheet, Text, View, ListView} from 'react-native';
import {Alert, ListView, Platform, StyleSheet, Text, View} from 'react-native';
import {injectIntl, intlShape} from 'react-intl';
import {buildDisplayNameAndTypeComparable} from 'service/utils/channel_utils';
import {Constants} from 'service/constants';
@ -16,7 +16,11 @@ import deepEqual from 'deep-equal';
const Styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
...Platform.select({
ios: {
marginTop: 20
}
})
},
scrollContainer: {
flex: 1

View file

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

View file

@ -0,0 +1,173 @@
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PropTypes, PureComponent} from 'react';
import {
Keyboard,
TextInput,
StyleSheet,
View,
TouchableOpacity
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
const styles = StyleSheet.create({
searchBar: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'transparent',
margin: 8
},
searchBarInput: {
flex: 1,
fontWeight: 'normal',
backgroundColor: 'transparent'
}
});
export default class SearchBarAndroid extends PureComponent {
static propTypes = {
height: PropTypes.number.isRequired,
fontSize: PropTypes.number.isRequired,
text: PropTypes.string,
placeholder: PropTypes.string,
showCancelButton: PropTypes.bool,
textFieldBackgroundColor: PropTypes.string,
placeholderTextColor: PropTypes.string,
textColor: PropTypes.string,
onChange: PropTypes.func,
onChangeText: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onSearchButtonPress: PropTypes.func,
onCancelButtonPress: PropTypes.func
};
static defaultProps = {
placeholder: 'Search',
showCancelButton: true,
placeholderTextColor: '#bdbdbd',
textColor: '#212121',
onSearchButtonPress: () => true,
onCancelButtonPress: () => true,
onChangeText: () => true,
onFocus: () => true,
onBlur: () => true
};
constructor(props) {
super(props);
this.state = {
isOnFocus: false,
value: this.props.text
};
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onCancelButtonPress = this.onCancelButtonPress.bind(this);
this.onSearchButtonPress = this.onSearchButtonPress.bind(this);
this.onChangeText = this.onChangeText.bind(this);
}
onSearchButtonPress() {
const onSearchButtonPress = this.props.onSearchButtonPress;
if (this.state.value) {
onSearchButtonPress(this.state.value);
}
}
onCancelButtonPress() {
const onCancelButtonPress = this.props.onCancelButtonPress;
this.setState({
isOnFocus: false,
value: ''
});
onCancelButtonPress();
Keyboard.dismiss();
}
onChangeText(value) {
const onChangeText = this.props.onChangeText;
this.setState({value});
onChangeText(value);
}
onFocus() {
const onFocus = this.props.onFocus;
this.setState({isOnFocus: true});
onFocus();
}
onBlur() {
const onBlur = this.props.onBlur;
this.setState({isOnFocus: false});
onBlur();
Keyboard.dismiss();
}
render() {
const {
height,
placeholder,
fontSize,
placeholderTextColor,
textColor,
textFieldBackgroundColor
} = this.props;
const searchBarStyle = {
height: height + 10,
paddingLeft: height * 0.25,
backgroundColor: textFieldBackgroundColor
};
const inputStyle = {
paddingLeft: height * 0.5,
fontSize,
color: textColor
};
return (
<View
style={[styles.searchBar, searchBarStyle]}
>
{this.state.isOnFocus && this.props.showCancelButton ?
<TouchableOpacity onPress={this.onCancelButtonPress}>
<Icon
name='arrow-back'
size={height}
color={placeholderTextColor}
/>
</TouchableOpacity> :
<Icon
name={'search'}
size={height}
color={placeholderTextColor}
/>
}
<TextInput
value={this.state.value}
returnKeyType='search'
onFocus={this.onFocus}
onBlur={this.onBlur}
onChange={this.props.onChange}
onChangeText={this.onChangeText}
onSubmitEditing={this.onSearchButtonPress}
placeholder={placeholder}
placeholderTextColor={placeholderTextColor}
underlineColorAndroid='transparent'
style={[styles.searchBarInput, inputStyle]}
/>
{this.state.isOnFocus && this.state.value ?
<TouchableOpacity onPress={() => this.setState({value: ''})}>
<Icon
style={{paddingRight: (height * 0.2)}}
name='close'
size={height}
color={placeholderTextColor}
/>
</TouchableOpacity> : null
}
</View>
);
}
}

View file

@ -0,0 +1,86 @@
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PropTypes, PureComponent} from 'react';
import SearchBar from 'react-native-search-bar';
export default class SearchBarIos extends PureComponent {
static propTypes = {
barStyle: PropTypes.oneOf(['default', 'black']),
searchBarStyle: PropTypes.oneOf(['default', 'prominent', 'minimal']),
text: PropTypes.string,
placeholder: PropTypes.string,
showCancelButton: PropTypes.bool,
hideBackground: PropTypes.bool,
textFieldBackgroundColor: PropTypes.string,
placeholderTextColor: PropTypes.string,
textColor: PropTypes.string,
barTintColor: PropTypes.string, //color of the background container
tintColor: PropTypes.string, // color of the carret and the cancel button
onChange: PropTypes.func,
onChangeText: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onSearchButtonPress: PropTypes.func,
onCancelButtonPress: PropTypes.func
};
static defaultProps = {
barStyle: 'default',
searchBarStyle: 'default',
placeholder: 'Search',
showCancelButton: true,
hideBackground: true,
onFocus: () => true,
onBlur: () => true
};
constructor(props) {
super(props);
this.state = {
displayCancelButton: false
};
}
onFocus = (event) => {
const onFocus = this.props.onFocus;
if (this.props.showCancelButton) {
this.setState({displayCancelButton: true});
}
onFocus(event);
};
onBlur = (event) => {
const onBlur = this.props.onBlur;
if (this.props.showCancelButton) {
this.setState({displayCancelButton: false});
}
onBlur(event);
};
render() {
return (
<SearchBar
barStyle={this.props.barStyle}
searchBarStyle={this.props.searchBarStyle}
text={this.props.text}
placeholder={this.props.placeholder}
showsCancelButton={this.state.displayCancelButton}
hideBackground={this.props.hideBackground}
textFieldBackgroundColor={this.props.textFieldBackgroundColor}
placeholderTextColor={this.props.placeholderTextColor}
textColor={this.props.textColor}
barTintColor={this.props.barTintColor}
tintColor={this.props.tintColor}
onChange={this.props.onChange}
onChangeText={this.props.onChangeText}
onFocus={this.onFocus}
onBlur={this.onBlur}
onSearchButtonPress={this.props.onSearchButtonPress}
onCancelButtonPress={this.props.onCancelButtonPress}
/>
);
}
}

View file

@ -14,16 +14,24 @@ class TextInputWithLocalizedPlaceholder extends React.PureComponent {
blur = () => {
this.refs.input.blur();
}
};
focus = () => {
this.refs.input.focus();
};
render() {
const {intl, placeholder, ...otherProps} = this.props;
let placeholderString = '';
if (placeholder.id) {
placeholderString = intl.formatMessage(placeholder);
}
return (
<TextInput
ref='input'
{...otherProps}
placeholder={intl.formatMessage(placeholder)}
placeholder={placeholderString}
/>
);
}

View file

@ -4,6 +4,7 @@
import React from 'react';
import {
Text,
Platform,
TouchableHighlight,
View
} from 'react-native';
@ -24,8 +25,19 @@ export default class ChannelHeader extends React.PureComponent {
theme
} = this.props;
const containerStyle = {
backgroundColor: theme.sidebarHeaderBg,
flexDirection: 'row',
justifyContent: 'flex-start',
...Platform.select({
ios: {
marginTop: 20
}
})
};
return (
<View style={{backgroundColor: theme.sidebarHeaderBg, flexDirection: 'row', justifyContent: 'flex-start', marginTop: 20}}>
<View style={containerStyle}>
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center'}}>
<TouchableHighlight
onPress={this.props.openLeftDrawer}

View file

@ -3,7 +3,14 @@
import React, {Component, PropTypes} from 'react';
import {injectIntl, intlShape} from 'react-intl';
import {Text, TextInput, Image, KeyboardAvoidingView} from 'react-native';
import {
Image,
KeyboardAvoidingView,
Text,
TextInput,
TouchableWithoutFeedback,
View
} from 'react-native';
import Button from 'react-native-button';
import FormattedText from 'app/components/formatted_text';
@ -58,6 +65,11 @@ class Login extends Component {
}
}
blur = () => {
this.loginId.blur();
this.passwd.blur();
};
preSignIn = () => {
this.setState({error: null});
if (!this.props.loginId) {
@ -152,52 +164,67 @@ class Login extends Component {
return (
<KeyboardAvoidingView
behavior='padding'
style={[GlobalStyles.container, GlobalStyles.signupContainer]}
style={{flex: 1}}
keyboardVerticalOffset={65}
>
<Image
source={logo}
/>
<Text style={GlobalStyles.header}>
{this.props.config.SiteName}
</Text>
<FormattedText
style={GlobalStyles.subheader}
id='web.root.signup_info'
defaultMessage='All team communication in one place, searchable and accessible anywhere'
/>
<ErrorText error={this.props.loginRequest.error || this.props.checkMfaRequest.error || this.state.error}/>
<TextInput
ref='loginId'
value={this.props.loginId}
onChangeText={this.props.actions.handleLoginIdChanged}
style={GlobalStyles.inputBox}
placeholder={this.createLoginPlaceholder()}
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'
/>
<TextInput
value={this.props.password}
onChangeText={this.props.actions.handlePasswordChanged}
style={GlobalStyles.inputBox}
placeholder={this.props.intl.formatMessage({id: 'login.password', defaultMessage: 'Password'})}
secureTextEntry={true}
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'
returnKeyType='go'
onSubmitEditing={this.preSignIn}
/>
<Button
onPress={this.preSignIn}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
id='login.signIn'
defaultMessage='Sign in'
style={GlobalStyles.signupButtonText}
/>
</Button>
<TouchableWithoutFeedback onPress={this.blur}>
<View style={[GlobalStyles.container, GlobalStyles.signupContainer]}>
<Image
source={logo}
/>
<Text style={GlobalStyles.header}>
{this.props.config.SiteName}
</Text>
<FormattedText
style={GlobalStyles.subheader}
id='web.root.signup_info'
defaultMessage='All team communication in one place, searchable and accessible anywhere'
/>
<ErrorText error={this.props.loginRequest.error || this.props.checkMfaRequest.error || this.state.error}/>
<TextInput
ref={(ref) => {
this.loginId = ref;
}}
value={this.props.loginId}
onChangeText={this.props.actions.handleLoginIdChanged}
style={GlobalStyles.inputBox}
placeholder={this.createLoginPlaceholder()}
autoCorrect={false}
autoCapitalize='none'
keyboardType='email-address'
returnKeyType='next'
underlineColorAndroid='transparent'
onSubmitEditing={() => {
this.passwd.focus();
}}
/>
<TextInput
ref={(ref) => {
this.passwd = ref;
}}
value={this.props.password}
onChangeText={this.props.actions.handlePasswordChanged}
style={GlobalStyles.inputBox}
placeholder={this.props.intl.formatMessage({id: 'login.password', defaultMessage: 'Password'})}
secureTextEntry={true}
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'
returnKeyType='go'
onSubmitEditing={this.preSignIn}
/>
<Button
onPress={this.preSignIn}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
id='login.signIn'
defaultMessage='Sign in'
style={GlobalStyles.signupButtonText}
/>
</Button>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}

View file

@ -2,7 +2,12 @@
// See License.txt for license information.
import React, {Component} from 'react';
import {Image, KeyboardAvoidingView} from 'react-native';
import {
Image,
KeyboardAvoidingView,
TouchableWithoutFeedback,
View
} from 'react-native';
import Button from 'react-native-button';
import ErrorText from 'app/components/error_text';
@ -49,6 +54,10 @@ export default class Mfa extends Component {
});
};
blur = () => {
this.textInput.refs.wrappedInstance.blur();
};
submit = () => {
if (!this.state.token) {
this.setState({
@ -67,40 +76,48 @@ export default class Mfa extends Component {
return (
<KeyboardAvoidingView
behavior='padding'
style={[GlobalStyles.container, GlobalStyles.signupContainer]}
style={{flex: 1}}
keyboardVerticalOffset={0}
>
<Image
source={logo}
/>
<FormattedText
style={[GlobalStyles.header, GlobalStyles.label]}
id='login_mfa.enterToken'
defaultMessage="To complete the sign in process, please enter a token from your smartphone's authenticator"
/>
<ErrorText error={this.state.error}/>
<TextInputWithLocalizedPlaceholder
value={this.state.token}
onChangeText={this.handleInput}
onSubmitEditing={this.submit}
style={GlobalStyles.inputBox}
autoCapitalize='none'
autoCorrect={false}
keyboardType='numeric'
placeholder={{id: 'login_mfa.token', defaultMessage: 'MFA Token'}}
returnKeyType='go'
underlineColorAndroid='transparent'
/>
<Button
onPress={this.submit}
loading={false}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
style={GlobalStyles.signupButtonText}
id='mobile.components.select_server_view.proceed'
defaultMessage='Proceed'
/>
</Button>
<TouchableWithoutFeedback onPress={this.blur}>
<View style={[GlobalStyles.container, GlobalStyles.signupContainer]}>
<Image
source={logo}
/>
<FormattedText
style={[GlobalStyles.header, GlobalStyles.label]}
id='login_mfa.enterToken'
defaultMessage="To complete the sign in process, please enter a token from your smartphone's authenticator"
/>
<ErrorText error={this.state.error}/>
<TextInputWithLocalizedPlaceholder
ref={(ref) => {
this.textInput = ref;
}}
value={this.state.token}
onChangeText={this.handleInput}
onSubmitEditing={this.submit}
style={GlobalStyles.inputBox}
autoCapitalize='none'
autoCorrect={false}
keyboardType='numeric'
placeholder={{id: 'login_mfa.token', defaultMessage: 'MFA Token'}}
returnKeyType='go'
underlineColorAndroid='transparent'
/>
<Button
onPress={this.submit}
loading={false}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
style={GlobalStyles.signupButtonText}
id='mobile.components.select_server_view.proceed'
defaultMessage='Proceed'
/>
</Button>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}

View file

@ -6,6 +6,7 @@ import {
ScrollView,
StyleSheet,
Text,
Platform,
View
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
@ -18,7 +19,11 @@ const Styles = StyleSheet.create({
container: {
backgroundColor: '#2071a7',
flex: 1,
paddingTop: 20
...Platform.select({
ios: {
marginTop: 20
}
})
},
itemText: {
color: 'white'

View file

@ -2,12 +2,17 @@
// See License.txt for license information.
import React, {Component} from 'react';
import {injectIntl, intlShape} from 'react-intl';
import {TextInput, Image, KeyboardAvoidingView} from 'react-native';
import {
Image,
KeyboardAvoidingView,
TouchableWithoutFeedback,
View
} from 'react-native';
import Button from 'react-native-button';
import ErrorText from 'app/components/error_text';
import FormattedText from 'app/components/formatted_text';
import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_localized_placeholder';
import {GlobalStyles} from 'app/styles';
import logo from 'assets/images/logo.png';
@ -15,9 +20,8 @@ import logo from 'assets/images/logo.png';
import Client from 'service/client';
import RequestStatus from 'service/constants/request_status';
class SelectServer extends Component {
export default class SelectServer extends Component {
static propTypes = {
intl: intlShape.isRequired,
serverUrl: React.PropTypes.string.isRequired,
server: React.PropTypes.object.isRequired,
actions: React.PropTypes.object.isRequired
@ -33,49 +37,57 @@ class SelectServer extends Component {
});
};
render() {
const {formatMessage} = this.props.intl;
blur = () => {
this.textInput.refs.wrappedInstance.blur();
};
render() {
return (
<KeyboardAvoidingView
behavior='padding'
style={[GlobalStyles.container, GlobalStyles.signupContainer]}
style={{flex: 1}}
keyboardVerticalOffset={0}
>
<Image
source={logo}
/>
<FormattedText
style={[GlobalStyles.header, GlobalStyles.label]}
id='mobile.components.select_server_view.enterServerUrl'
defaultMessage='Enter Server URL'
/>
<TextInput
value={this.props.serverUrl}
onChangeText={this.props.actions.handleServerUrlChanged}
onSubmitEditing={this.onClick}
style={GlobalStyles.inputBox}
autoCapitalize='none'
autoCorrect={false}
keyboardType='url'
placeholder={formatMessage({id: 'mobile.components.select_server_view.siteUrlPlaceholder', defaultMessage: 'https://mattermost.example.com'})}
returnKeyType='go'
underlineColorAndroid='transparent'
/>
<Button
onPress={this.onClick}
loading={this.props.server.loading}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
style={GlobalStyles.signupButtonText}
id='mobile.components.select_server_view.proceed'
defaultMessage='Proceed'
/>
</Button>
<ErrorText error={this.props.server.error}/>
<TouchableWithoutFeedback onPress={this.blur}>
<View style={[GlobalStyles.container, GlobalStyles.signupContainer]}>
<Image
source={logo}
/>
<FormattedText
style={[GlobalStyles.header, GlobalStyles.label]}
id='mobile.components.select_server_view.enterServerUrl'
defaultMessage='Enter Server URL'
/>
<TextInputWithLocalizedPlaceholder
ref={(ref) => {
this.textInput = ref;
}}
value={this.props.serverUrl}
onChangeText={this.props.actions.handleServerUrlChanged}
onSubmitEditing={this.onClick}
style={GlobalStyles.inputBox}
autoCapitalize='none'
autoCorrect={false}
keyboardType='url'
placeholder={{id: 'mobile.components.select_server_view.siteUrlPlaceholder', defaultMessage: 'https://mattermost.example.com'}}
returnKeyType='go'
underlineColorAndroid='transparent'
/>
<Button
onPress={this.onClick}
loading={this.props.server.loading}
containerStyle={GlobalStyles.signupButton}
>
<FormattedText
style={GlobalStyles.signupButtonText}
id='mobile.components.select_server_view.proceed'
defaultMessage='Proceed'
/>
</Button>
<ErrorText error={this.props.server.error}/>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
}
export default injectIntl(SelectServer);

View file

@ -33,6 +33,7 @@
7FBB5E9B1E1F5A4B000DE18A /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FDF290C1E1F4B4E00DBBE56 /* libRNVectorIcons.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
895C9A56B94A45C1BAF568FE /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AC6EB561E1F64C17A69D2FAD /* Entypo.ttf */; };
B50561A109B4442299F82327 /* libRNSearchBar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F81F6DC42D394831B4549928 /* libRNSearchBar.a */; };
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 */; };
@ -214,6 +215,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTLinking;
};
7F4890681E3B7D3B008EDBEA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 59954D479A89488091EB588F /* RNSearchBar.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNSearchBar;
};
7FDF28E01E1F4B1F00DBBE56 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 2CBE9C0FB56E4FDA96C30792 /* RNSVG.xcodeproj */;
@ -265,12 +273,14 @@
349FBA7338E74D9BBD709528 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; };
356C9186FA374641A00EB2EA /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; };
51F5A483EA9F4A9A87ACFB59 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = "<group>"; };
59954D479A89488091EB588F /* RNSearchBar.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSearchBar.xcodeproj; path = "../node_modules/react-native-search-bar/RNSearchBar.xcodeproj"; sourceTree = "<group>"; };
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
AC6EB561E1F64C17A69D2FAD /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
EDC04CBCF81642219D199CBB /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; 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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -299,6 +309,7 @@
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
B50561A109B4442299F82327 /* libRNSearchBar.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -445,6 +456,14 @@
name = Products;
sourceTree = "<group>";
};
7F48904C1E3B7D3B008EDBEA /* Products */ = {
isa = PBXGroup;
children = (
7F4890691E3B7D3B008EDBEA /* libRNSearchBar.a */,
);
name = Products;
sourceTree = "<group>";
};
7FDF28C41E1F4B1F00DBBE56 /* Products */ = {
isa = PBXGroup;
children = (
@ -477,6 +496,7 @@
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
2CBE9C0FB56E4FDA96C30792 /* RNSVG.xcodeproj */,
2B25899FDAC149EB96ED3305 /* RNVectorIcons.xcodeproj */,
59954D479A89488091EB588F /* RNSearchBar.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@ -625,6 +645,10 @@
ProductGroup = 146834001AC3E56700842450 /* Products */;
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
},
{
ProductGroup = 7F48904C1E3B7D3B008EDBEA /* Products */;
ProjectRef = 59954D479A89488091EB588F /* RNSearchBar.xcodeproj */;
},
{
ProductGroup = 7FDF28C41E1F4B1F00DBBE56 /* Products */;
ProjectRef = 2CBE9C0FB56E4FDA96C30792 /* RNSVG.xcodeproj */;
@ -811,6 +835,13 @@
remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F4890691E3B7D3B008EDBEA /* libRNSearchBar.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNSearchBar.a;
remoteRef = 7F4890681E3B7D3B008EDBEA /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7FDF28E11E1F4B1F00DBBE56 /* libRNSVG.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -925,7 +956,7 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@ -937,6 +968,7 @@
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -949,7 +981,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
INFOPLIST_FILE = MattermostTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@ -957,6 +989,7 @@
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -971,7 +1004,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 7;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
INFOPLIST_FILE = Mattermost/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
@ -994,7 +1027,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 7;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
INFOPLIST_FILE = Mattermost/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (

View file

@ -14,6 +14,7 @@
"react-native-button": "1.7.1",
"react-native-drawer": "2.3.0",
"react-native-keyboard-spacer": "0.3.1",
"react-native-search-bar": "enahum/react-native-search-bar.git",
"react-native-svg": "4.5.0",
"react-native-vector-icons": "4.0.0",
"react-redux": "5.0.1",