Upgrade to RN 0.50.4 (#1303)
* Update to RN 0.50.4 * Fix intl context in post textbox
This commit is contained in:
parent
6681ae3de7
commit
2e951cbfca
25 changed files with 497 additions and 422 deletions
|
|
@ -37,12 +37,12 @@ suppress_type=$FlowFixMeProps
|
|||
suppress_type=$FlowFixMeState
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-3]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-3]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
unsafe.enable_getters_and_setters=true
|
||||
|
||||
[version]
|
||||
^0.53.0
|
||||
^0.56.0
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -82,3 +82,6 @@ ios/sentry.properties
|
|||
# Pods
|
||||
.podinstall
|
||||
ios/Pods/
|
||||
|
||||
#editor-settings
|
||||
.vscode
|
||||
3
Makefile
3
Makefile
|
|
@ -125,12 +125,11 @@ post-install:
|
|||
@sed -i'' -e 's|"./locale-data/complete.js": false|"./locale-data/complete.js": "./locale-data/complete.js"|g' node_modules/intl/package.json
|
||||
@sed -i'' -e 's|auto("auto", Configuration.ORIENTATION_UNDEFINED, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);|auto("auto", Configuration.ORIENTATION_UNDEFINED, ActivityInfo.SCREEN_ORIENTATION_FULL_USER);|g' node_modules/react-native-navigation/android/app/src/main/java/com/reactnativenavigation/params/Orientation.java
|
||||
@sed -i'' -e "s|var AndroidTextInput = requireNativeComponent('AndroidTextInput', null);|var AndroidTextInput = requireNativeComponent('CustomTextInput', null);|g" node_modules/react-native/Libraries/Components/TextInput/TextInput.js
|
||||
@sed -i'' -e 's^getItemLayout || index <= this._highestMeasuredFrameIndex,^!getItemLayout || index !== -1,^g' node_modules/react-native/Libraries/Lists/VirtualizedList.js
|
||||
@if [ $(shell grep "const Platform" node_modules/react-native/Libraries/Lists/VirtualizedList.js | grep -civ grep) -eq 0 ]; then \
|
||||
sed $ -i'' -e "s|const ReactNative = require('ReactNative');|const ReactNative = require('ReactNative');`echo $\\\\\\r;`const Platform = require('Platform');|g" node_modules/react-native/Libraries/Lists/VirtualizedList.js; \
|
||||
fi
|
||||
@sed -i'' -e 's|transform: \[{scaleY: -1}\],|...Platform.select({android: {transform: \[{perspective: 1}, {scaleY: -1}\]}, ios: {transform: \[{scaleY: -1}\]}}),|g' node_modules/react-native/Libraries/Lists/VirtualizedList.js
|
||||
@cd ./node_modules/react-native-svg/ios && rm -rf PerformanceBezier && git clone https://github.com/adamwulf/PerformanceBezier.git
|
||||
@cd ./node_modules/react-native-svg/ios && rm -rf PerformanceBezier QuartzBookPack && yarn run postinstall
|
||||
@cd ./node_modules/mattermost-redux && yarn run build
|
||||
|
||||
start-packager: ## Starts the package server
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ import {sortChannelsByDisplayName} from 'mattermost-redux/utils/channel_utils';
|
|||
import {displayUsername} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import ChannelDrawerItem from 'app/components/channel_drawer/channels_list/channel_item';
|
||||
import {ListTypes} from 'app/constants';
|
||||
|
||||
const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
|
||||
|
||||
class FilteredList extends Component {
|
||||
static propTypes = {
|
||||
|
|
@ -387,10 +390,7 @@ class FilteredList extends Component {
|
|||
onViewableItemsChanged={this.updateUnreadIndicators}
|
||||
keyboardDismissMode='on-drag'
|
||||
maxToRenderPerBatch={10}
|
||||
viewabilityConfig={{
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: false
|
||||
}}
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -18,9 +18,15 @@ import {debounce} from 'mattermost-redux/actions/helpers';
|
|||
|
||||
import ChannelItem from 'app/components/channel_drawer/channels_list/channel_item';
|
||||
import UnreadIndicator from 'app/components/channel_drawer/channels_list/unread_indicator';
|
||||
import {ListTypes} from 'app/constants';
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity} from 'app/utils/theme';
|
||||
|
||||
const VIEWABILITY_CONFIG = {
|
||||
...ListTypes.VISIBILITY_CONFIG_DEFAULTS,
|
||||
waitForInteraction: true
|
||||
};
|
||||
|
||||
export default class List extends PureComponent {
|
||||
static propTypes = {
|
||||
canCreatePrivateChannels: PropTypes.bool.isRequired,
|
||||
|
|
@ -340,10 +346,7 @@ export default class List extends PureComponent {
|
|||
keyboardDismissMode='on-drag'
|
||||
maxToRenderPerBatch={10}
|
||||
stickySectionHeadersEnabled={false}
|
||||
viewabilityConfig={{
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: true
|
||||
}}
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
<UnreadIndicator
|
||||
show={showIndicator}
|
||||
|
|
|
|||
|
|
@ -15,12 +15,18 @@ import {injectIntl, intlShape} from 'react-intl';
|
|||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import {ListTypes} from 'app/constants';
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
||||
import TeamsListItem from './teams_list_item';
|
||||
|
||||
const VIEWABILITY_CONFIG = {
|
||||
...ListTypes.VISIBILITY_CONFIG_DEFAULTS,
|
||||
waitForInteraction: true
|
||||
};
|
||||
|
||||
class TeamsList extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -135,10 +141,7 @@ class TeamsList extends PureComponent {
|
|||
data={teamIds}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={this.keyExtractor}
|
||||
viewabilityConfig={{
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: false
|
||||
}}
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -88,13 +88,11 @@ export default class CustomSectionList extends React.PureComponent {
|
|||
initialNumToRender: PropTypes.number
|
||||
};
|
||||
|
||||
static defaultKeyExtractor = (item) => {
|
||||
return item.id;
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
showNoResults: true,
|
||||
keyExtractor: CustomSectionList.defaultKeyExtractor,
|
||||
keyExtractor: (item) => {
|
||||
return item.id;
|
||||
},
|
||||
onListEndReached: () => true,
|
||||
onListEndReachedThreshold: 50,
|
||||
loadingText: null,
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ export default class EditChannelInfo extends PureComponent {
|
|||
placeholder={{id: 'channel_modal.nameEx', defaultMessage: 'E.g.: "Bugs", "Marketing", "客户支持"'}}
|
||||
placeholderTextColor={changeOpacity('#000', 0.5)}
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -279,6 +280,7 @@ export default class EditChannelInfo extends PureComponent {
|
|||
placeholder={{id: 'rename_channel.handleHolder', defaultMessage: 'lowercase alphanumeric characters'}}
|
||||
placeholderTextColor={changeOpacity('#000', 0.5)}
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -311,6 +313,7 @@ export default class EditChannelInfo extends PureComponent {
|
|||
blurOnSubmit={false}
|
||||
textAlignVertical='top'
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
|
|
@ -349,6 +352,7 @@ export default class EditChannelInfo extends PureComponent {
|
|||
onFocus={this.scrollToEnd}
|
||||
textAlignVertical='top'
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
</View>
|
||||
<View ref={this.lastTextRef}>
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
const emojiSectionIndexByOffset = this.measureEmojiSections(emojis);
|
||||
|
||||
this.isX = DeviceInfo.getModel() === 'iPhone X';
|
||||
this.scrollToSectionTries = 0;
|
||||
this.state = {
|
||||
emojis,
|
||||
emojiSectionIndexByOffset,
|
||||
|
|
@ -264,6 +265,15 @@ export default class EmojiPicker extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
handleScrollToSectionFailed = ({index}) => {
|
||||
if (this.scrollToSectionTries < 1) {
|
||||
setTimeout(() => {
|
||||
this.scrollToSectionTries++;
|
||||
this.scrollToSection(index);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
renderSectionHeader = ({section}) => {
|
||||
const {theme} = this.props;
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
|
|
@ -282,12 +292,17 @@ export default class EmojiPicker extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
handleSectionIconPress = (index) => {
|
||||
this.scrollToSectionTries = 0;
|
||||
this.scrollToSection(index);
|
||||
}
|
||||
|
||||
renderSectionIcons = () => {
|
||||
const {theme} = this.props;
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
|
||||
return this.state.emojis.map((section, index) => {
|
||||
const onPress = () => this.scrollToSection(index);
|
||||
const onPress = () => this.handleSectionIconPress(index);
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
|
|
@ -342,6 +357,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
getItemLayout={this.sectionListGetItemLayout}
|
||||
removeClippedSubviews={true}
|
||||
onScroll={this.onScroll}
|
||||
onScrollToIndexFailed={this.handleScrollToSectionFailed}
|
||||
onMomentumScrollEnd={this.onMomentumScrollEnd}
|
||||
pageSize={30}
|
||||
/>
|
||||
|
|
@ -416,8 +432,7 @@ const getStyleSheetFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
left: 0,
|
||||
right: 0,
|
||||
height: 35,
|
||||
width: '100%',
|
||||
backgroundColor: 'white'
|
||||
width: '100%'
|
||||
},
|
||||
columnStyle: {
|
||||
alignSelf: 'stretch',
|
||||
|
|
|
|||
|
|
@ -46,17 +46,13 @@ export default class PostList extends PureComponent {
|
|||
loadMore: () => true
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
newMessagesIndex = -1;
|
||||
scrollToMessageTries = 0;
|
||||
makeExtraData = makeExtraData();
|
||||
|
||||
this.newMessagesIndex = -1;
|
||||
|
||||
this.makeExtraData = makeExtraData();
|
||||
|
||||
this.state = {
|
||||
managedConfig: {}
|
||||
};
|
||||
}
|
||||
state = {
|
||||
managedConfig: {}
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.listenerId = mattermostManaged.addEventListener('change', this.setManagedConfig);
|
||||
|
|
@ -76,6 +72,7 @@ export default class PostList extends PureComponent {
|
|||
componentDidUpdate(prevProps) {
|
||||
const initialPosts = !prevProps.postIds.length && prevProps.postIds !== this.props.postIds;
|
||||
if ((prevProps.channelId !== this.props.channelId || initialPosts || this.props.isSearchResult) && this.refs.list) {
|
||||
this.scrollToMessageTries = 0;
|
||||
this.scrollList();
|
||||
}
|
||||
}
|
||||
|
|
@ -86,7 +83,7 @@ export default class PostList extends PureComponent {
|
|||
|
||||
scrollList = () => {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
if (this.props.postIds.length && this.newMessagesIndex !== -1 && this.newMessagesIndex <= this.props.postIds.length) {
|
||||
if (this.props.postIds.length && this.newMessagesIndex !== -1) {
|
||||
if (this.refs.list) {
|
||||
this.refs.list.scrollToIndex({
|
||||
index: this.newMessagesIndex,
|
||||
|
|
@ -95,13 +92,22 @@ export default class PostList extends PureComponent {
|
|||
animated: true
|
||||
});
|
||||
}
|
||||
this.newMessagesIndex = -1;
|
||||
} else if (this.refs.list) {
|
||||
this.refs.list.scrollToOffset({y: 0, animated: false});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
scrollListFailed = ({index}) => {
|
||||
if (this.scrollToMessageTries < 3) {
|
||||
this.scrollToMessageTries++;
|
||||
setTimeout(() => {
|
||||
this.newMessagesIndex = index;
|
||||
this.scrollList();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
setManagedConfig = async (config) => {
|
||||
let nextConfig = config;
|
||||
if (!nextConfig) {
|
||||
|
|
@ -244,6 +250,7 @@ export default class PostList extends PureComponent {
|
|||
ListFooterComponent={this.renderFooter}
|
||||
onEndReached={loadMore}
|
||||
onEndReachedThreshold={Platform.OS === 'ios' ? 0 : 1}
|
||||
onScrollToIndexFailed={this.scrollListFailed}
|
||||
{...refreshControl}
|
||||
renderItem={this.renderItem}
|
||||
contentContainerStyle={styles.postListContent}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, TouchableOpacity, View} from 'react-native';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import {Alert, BackHandler, Keyboard, Platform, TextInput, TouchableOpacity, View} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
import Autocomplete from 'app/components/autocomplete';
|
||||
|
|
@ -21,7 +21,7 @@ const MAX_MESSAGE_LENGTH = 4000;
|
|||
const MAX_FILE_COUNT = 5;
|
||||
const IS_REACTION_REGEX = /(^\+:([^:\s]*):)$/i;
|
||||
|
||||
class PostTextbox extends PureComponent {
|
||||
export default class PostTextbox extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
addReactionToLatestPost: PropTypes.func.isRequired,
|
||||
|
|
@ -42,7 +42,6 @@ class PostTextbox extends PureComponent {
|
|||
channelIsLoading: PropTypes.bool.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
files: PropTypes.array,
|
||||
intl: intlShape.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
rootId: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -56,12 +55,15 @@ class PostTextbox extends PureComponent {
|
|||
value: ''
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
contentHeight: INITIAL_HEIGHT,
|
||||
inputWidth: null,
|
||||
keyboardType: 'default',
|
||||
value: props.value,
|
||||
showFileMaxWarning: false
|
||||
|
|
@ -131,7 +133,7 @@ class PostTextbox extends PureComponent {
|
|||
};
|
||||
|
||||
checkMessageLength = (value) => {
|
||||
const {intl} = this.props;
|
||||
const {intl} = this.context;
|
||||
const valueLength = value.trim().length;
|
||||
|
||||
if (valueLength > MAX_MESSAGE_LENGTH) {
|
||||
|
|
@ -173,9 +175,11 @@ class PostTextbox extends PureComponent {
|
|||
};
|
||||
|
||||
handleContentSizeChange = (event) => {
|
||||
let contentHeight = event.nativeEvent.layout.height;
|
||||
let contentHeight = event.nativeEvent.contentSize.height;
|
||||
if (contentHeight < INITIAL_HEIGHT) {
|
||||
contentHeight = INITIAL_HEIGHT;
|
||||
} else if (Platform.OS === 'ios') {
|
||||
contentHeight += 5;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
|
@ -197,12 +201,6 @@ class PostTextbox extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleInputSizeChange = (event) => {
|
||||
this.setState({
|
||||
inputWidth: event.nativeEvent.layout.width
|
||||
});
|
||||
};
|
||||
|
||||
handlePostDraftSelectionChanged = (event) => {
|
||||
const cursorPosition = event.nativeEvent.selection.end;
|
||||
if (this.props.rootId) {
|
||||
|
|
@ -231,7 +229,7 @@ class PostTextbox extends PureComponent {
|
|||
|
||||
const hasFailedAttachments = files.some((f) => f.failed);
|
||||
if (hasFailedAttachments) {
|
||||
const {intl} = this.props;
|
||||
const {intl} = this.context;
|
||||
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
|
|
@ -316,7 +314,8 @@ class PostTextbox extends PureComponent {
|
|||
};
|
||||
|
||||
sendMessage = () => {
|
||||
const {actions, currentUserId, channelId, files, rootId, intl} = this.props;
|
||||
const {actions, currentUserId, channelId, files, rootId} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {value} = this.state;
|
||||
|
||||
if (files.length === 0 && !value) {
|
||||
|
|
@ -374,7 +373,8 @@ class PostTextbox extends PureComponent {
|
|||
};
|
||||
|
||||
sendCommand = async (msg) => {
|
||||
const {actions, channelId, intl, rootId} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {actions, channelId, rootId} = this.props;
|
||||
const {error} = await actions.executeCommand(msg, channelId, rootId);
|
||||
|
||||
if (error) {
|
||||
|
|
@ -386,7 +386,7 @@ class PostTextbox extends PureComponent {
|
|||
error.message
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sendReaction = (emoji) => {
|
||||
const {actions, rootId} = this.props;
|
||||
|
|
@ -404,12 +404,12 @@ class PostTextbox extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {intl} = this.context;
|
||||
const {
|
||||
canUploadFiles,
|
||||
channelId,
|
||||
channelIsLoading,
|
||||
files,
|
||||
intl,
|
||||
navigator,
|
||||
rootId,
|
||||
theme
|
||||
|
|
@ -448,12 +448,6 @@ class PostTextbox extends PureComponent {
|
|||
|
||||
return (
|
||||
<View>
|
||||
<Text
|
||||
style={[style.input, style.hidden, {width: this.state.inputWidth}]}
|
||||
onLayout={this.handleContentSizeChange}
|
||||
>
|
||||
{textValue + ' '}
|
||||
</Text>
|
||||
<Typing/>
|
||||
<FileUploadPreview
|
||||
channelId={channelId}
|
||||
|
|
@ -483,7 +477,7 @@ class PostTextbox extends PureComponent {
|
|||
blurOnSubmit={false}
|
||||
underlineColorAndroid='transparent'
|
||||
style={[style.input, {height: textInputHeight}]}
|
||||
onLayout={this.handleInputSizeChange}
|
||||
onContentSizeChange={this.handleContentSizeChange}
|
||||
keyboardType={this.state.keyboardType}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
|
|
@ -554,5 +548,3 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
}
|
||||
};
|
||||
});
|
||||
|
||||
export default injectIntl(PostTextbox, {withRef: true});
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export default class SafeAreaIos extends PureComponent {
|
|||
|
||||
componentWillMount() {
|
||||
this.getSafeAreaInsets();
|
||||
this.mounted = true;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
@ -62,13 +63,16 @@ export default class SafeAreaIos extends PureComponent {
|
|||
Orientation.removeOrientationListener(this.getSafeAreaInsets);
|
||||
this.keyboardDidShowListener.remove();
|
||||
this.keyboardDidHideListener.remove();
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
getStatusBarHeight = () => {
|
||||
try {
|
||||
StatusBarManager.getHeight(
|
||||
(statusBarFrameData) => {
|
||||
this.setState({statusBarHeight: statusBarFrameData.height});
|
||||
if (this.mounted) {
|
||||
this.setState({statusBarHeight: statusBarFrameData.height});
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
import DeviceTypes from './device';
|
||||
import ListTypes from './list';
|
||||
import NavigationTypes from './navigation';
|
||||
import ViewTypes from './view';
|
||||
|
||||
export {
|
||||
DeviceTypes,
|
||||
ListTypes,
|
||||
NavigationTypes,
|
||||
ViewTypes
|
||||
};
|
||||
|
|
|
|||
11
app/constants/list.js
Normal file
11
app/constants/list.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
const VISIBILITY_CONFIG_DEFAULTS = {
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: false
|
||||
};
|
||||
|
||||
export default {
|
||||
VISIBILITY_CONFIG_DEFAULTS
|
||||
};
|
||||
|
|
@ -105,7 +105,7 @@ export default class Mattermost {
|
|||
registerScreens(this.store, Provider);
|
||||
|
||||
setJSExceptionHandler(this.errorHandler, false);
|
||||
setNativeExceptionHandler(this.nativeErrorHandler);
|
||||
setNativeExceptionHandler(this.nativeErrorHandler, false);
|
||||
}
|
||||
|
||||
errorHandler = (e, isFatal) => {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class Channel extends PureComponent {
|
|||
};
|
||||
|
||||
blurPostTextBox = () => {
|
||||
this.postTextbox.getWrappedInstance().getWrappedInstance().blur();
|
||||
this.postTextbox.getWrappedInstance().blur();
|
||||
};
|
||||
|
||||
channelDrawerRef = (ref) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// See License.txt for license information.
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {
|
||||
Dimensions,
|
||||
Platform,
|
||||
|
|
@ -17,19 +17,22 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
|
|||
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
class EditPost extends PureComponent {
|
||||
export default class EditPost extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
editPost: PropTypes.func.isRequired
|
||||
}),
|
||||
closeButton: PropTypes.object,
|
||||
editPostRequest: PropTypes.object.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
post: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
leftButton = {
|
||||
id: 'close-edit-post'
|
||||
};
|
||||
|
|
@ -39,11 +42,11 @@ class EditPost extends PureComponent {
|
|||
showAsAction: 'always'
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
this.state = {message: props.post.message};
|
||||
this.rightButton.title = props.intl.formatMessage({id: 'edit_post.save', defaultMessage: 'Save'});
|
||||
this.rightButton.title = context.intl.formatMessage({id: 'edit_post.save', defaultMessage: 'Save'});
|
||||
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
|
||||
props.navigator.setButtons({
|
||||
|
|
@ -106,20 +109,6 @@ class EditPost extends PureComponent {
|
|||
this.messageInput.refs.wrappedInstance.focus();
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
// Workaround for android as the multiline is not working
|
||||
if (Platform.OS === 'android') {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
let {message: msg} = this.state;
|
||||
msg += '\n';
|
||||
this.setState({message: msg});
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
messageRef = (ref) => {
|
||||
this.messageInput = ref;
|
||||
};
|
||||
|
|
@ -198,7 +187,7 @@ class EditPost extends PureComponent {
|
|||
placeholder={{id: 'edit_post.editPost', defaultMessage: 'Edit the post...'}}
|
||||
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
underlineColorAndroid='transparent'
|
||||
onSubmitEditing={this.handleSubmit}
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -239,5 +228,3 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
}
|
||||
};
|
||||
});
|
||||
|
||||
export default injectIntl(EditPost);
|
||||
|
|
|
|||
|
|
@ -528,6 +528,7 @@ export default class ImagePreview extends PureComponent {
|
|||
<SafeAreaView
|
||||
backgroundColor='#000'
|
||||
navBarBackgroundColor='#000'
|
||||
excludeHeader={true}
|
||||
>
|
||||
<View
|
||||
style={[style.wrapper]}
|
||||
|
|
@ -622,7 +623,8 @@ const style = StyleSheet.create({
|
|||
headerControls: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around',
|
||||
flexDirection: 'row'
|
||||
flexDirection: 'row',
|
||||
marginTop: 18
|
||||
},
|
||||
headerIcon: {
|
||||
height: 44,
|
||||
|
|
@ -640,7 +642,7 @@ const style = StyleSheet.create({
|
|||
footerContainer: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
height: 40,
|
||||
height: 64,
|
||||
zIndex: 2
|
||||
},
|
||||
footer: {
|
||||
|
|
@ -648,13 +650,14 @@ const style = StyleSheet.create({
|
|||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 40,
|
||||
height: 64,
|
||||
justifyContent: 'flex-end',
|
||||
paddingHorizontal: 24,
|
||||
paddingBottom: 5
|
||||
},
|
||||
filename: {
|
||||
color: 'white',
|
||||
fontSize: 14
|
||||
fontSize: 14,
|
||||
marginBottom: 10
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ export default class Mfa extends PureComponent {
|
|||
placeholder={{id: 'login_mfa.token', defaultMessage: 'MFA Token'}}
|
||||
returnKeyType='go'
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
{proceed}
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ class SelectServer extends PureComponent {
|
|||
placeholder={{id: 'mobile.components.select_server_view.siteUrlPlaceholder', defaultMessage: 'https://mattermost.example.com'}}
|
||||
returnKeyType='go'
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
/>
|
||||
<Button
|
||||
onPress={this.onClick}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,12 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
|||
import FormattedText from 'app/components/formatted_text';
|
||||
import Loading from 'app/components/loading';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
|
||||
import {ListTypes} from 'app/constants';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme';
|
||||
|
||||
const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
|
||||
|
||||
export default class SelectTeam extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -225,10 +227,7 @@ export default class SelectTeam extends PureComponent {
|
|||
data={teams}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={(item) => item.id}
|
||||
viewabilityConfig={{
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: false
|
||||
}}
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const oneLoginFormScalingJS = `
|
|||
document.getElementById('body-main').setAttribute('style', 'height: auto; padding: 10px 0;');
|
||||
submitButton.removeEventListener('click', resetPadding);
|
||||
}
|
||||
resetPadding();
|
||||
submitButton.addEventListener('click', resetPadding);
|
||||
})();
|
||||
`;
|
||||
|
|
|
|||
45
package.json
45
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mattermost-mobile",
|
||||
"version": "0.0.1",
|
||||
"version": "1.3.2",
|
||||
"description": "Mattermost Mobile with React Native",
|
||||
"repository": "git@github.com:mattermost/mattermost-mobile.git",
|
||||
"author": "Mattermost, Inc.",
|
||||
|
|
@ -16,25 +16,25 @@
|
|||
"jail-monkey": "0.1.0",
|
||||
"mattermost-redux": "mattermost/mattermost-redux",
|
||||
"prop-types": "15.6.0",
|
||||
"react": "16.0.0",
|
||||
"react": "16.2.0",
|
||||
"react-intl": "2.4.0",
|
||||
"react-native": "0.49.5",
|
||||
"react-native": "0.50.4",
|
||||
"react-native-animatable": "1.2.4",
|
||||
"react-native-bottom-sheet": "1.0.2",
|
||||
"react-native-button": "2.1.0",
|
||||
"react-native-circular-progress": "jaystramel/react-native-circular-progress",
|
||||
"react-native-circular-progress": "0.1.0",
|
||||
"react-native-cookies": "3.2.0",
|
||||
"react-native-device-info": "0.12.1",
|
||||
"react-native-doc-viewer": "philipphecht/react-native-doc-viewer",
|
||||
"react-native-device-info": "0.13.0",
|
||||
"react-native-doc-viewer": "2.6.8",
|
||||
"react-native-drawer": "2.5.0",
|
||||
"react-native-exception-handler": "2.3.0",
|
||||
"react-native-fast-image": "1.0.0",
|
||||
"react-native-exception-handler": "2.4.3",
|
||||
"react-native-fast-image": "2.0.1",
|
||||
"react-native-fetch-blob": "0.10.8",
|
||||
"react-native-image-picker": "0.26.7",
|
||||
"react-native-keyboard-aware-scroll-view": "0.4.1",
|
||||
"react-native-linear-gradient": "2.3.0",
|
||||
"react-native-local-auth": "enahum/react-native-local-auth.git",
|
||||
"react-native-navigation": "1.1.295",
|
||||
"react-native-navigation": "v1.1.313",
|
||||
"react-native-notifications": "enahum/react-native-notifications.git",
|
||||
"react-native-orientation": "enahum/react-native-orientation.git",
|
||||
"react-native-passcode-status": "1.1.0",
|
||||
|
|
@ -42,8 +42,8 @@
|
|||
"react-native-section-list-get-item-layout": "2.1.0",
|
||||
"react-native-sentry": "0.15.1",
|
||||
"react-native-slider": "0.11.0",
|
||||
"react-native-status-bar-size": "0.3.2",
|
||||
"react-native-svg": "6.0.0",
|
||||
"react-native-status-bar-size": "0.3.3",
|
||||
"react-native-svg": "6.0.1-rc.0",
|
||||
"react-native-tooltip": "enahum/react-native-tooltip",
|
||||
"react-native-vector-icons": "4.4.2",
|
||||
"react-native-video": "2.0.0",
|
||||
|
|
@ -51,21 +51,21 @@
|
|||
"react-redux": "5.0.6",
|
||||
"redux": "3.7.2",
|
||||
"redux-batched-actions": "0.2.0",
|
||||
"redux-persist": "4.9.1",
|
||||
"redux-persist": "4.10.2",
|
||||
"redux-persist-transform-filter": "0.0.16",
|
||||
"redux-thunk": "2.2.0",
|
||||
"reselect": "3.0.1",
|
||||
"semver": "5.4.1",
|
||||
"shallow-equals": "1.0.0",
|
||||
"socketcluster": "9.1.1",
|
||||
"socketcluster": "9.1.4",
|
||||
"tinycolor2": "1.4.1",
|
||||
"url-parse": "1.2.0",
|
||||
"youtube-video-id": "0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "6.26.0",
|
||||
"babel-eslint": "8.0.1",
|
||||
"babel-plugin-module-resolver": "2.7.1",
|
||||
"babel-eslint": "8.0.3",
|
||||
"babel-plugin-module-resolver": "3.0.0",
|
||||
"babel-plugin-transform-remove-console": "6.8.5",
|
||||
"babel-preset-env": "1.6.1",
|
||||
"babel-preset-es2015": "6.24.1",
|
||||
|
|
@ -78,23 +78,24 @@
|
|||
"chai-enzyme": "0.8.0",
|
||||
"chai-fetch-mock": "1.0.1",
|
||||
"deep-freeze": "0.0.1",
|
||||
"enzyme": "3.1.1",
|
||||
"eslint": "4.10.0",
|
||||
"enzyme": "3.2.0",
|
||||
"eslint": "4.12.1",
|
||||
"eslint-plugin-mocha": "4.11.0",
|
||||
"eslint-plugin-react": "7.4.0",
|
||||
"eslint-plugin-react": "7.5.1",
|
||||
"fetch-mock": "5.13.1",
|
||||
"form-data": "2.3.1",
|
||||
"jsdom": "11.3.0",
|
||||
"jsdom": "11.5.1",
|
||||
"jsdom-global": "3.0.2",
|
||||
"mocha": "4.0.1",
|
||||
"mocha-react-native": "0.6.0",
|
||||
"mock-async-storage": "2.0.2",
|
||||
"mockery": "2.1.0",
|
||||
"nyc": "11.3.0",
|
||||
"react-addons-test-utils": "15.6.2",
|
||||
"react-dom": "16.0.0",
|
||||
"react-dom": "16.2.0",
|
||||
"react-native-mock": "0.3.1",
|
||||
"react-native-svg-mock": "1.1.0",
|
||||
"react-test-renderer": "16.0.0",
|
||||
"react-native-svg-mock": "2.0.0",
|
||||
"react-test-renderer": "16.2.0",
|
||||
"remote-redux-devtools": "0.5.12",
|
||||
"remotedev-rn-debugger": "0.8.3",
|
||||
"underscore": "1.8.3"
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import fs from 'fs';
|
|||
import path from 'path';
|
||||
import register from 'babel-core/register';
|
||||
import mockery from 'mockery';
|
||||
import MockAsyncStorage from 'mock-async-storage';
|
||||
|
||||
mockery.enable({
|
||||
warnOnReplace: false,
|
||||
|
|
@ -21,6 +22,7 @@ mockery.registerMock('react-native', {
|
|||
return {width: 0, height: 0}
|
||||
}
|
||||
},
|
||||
AsyncStorage: new MockAsyncStorage(),
|
||||
NativeModules: {},
|
||||
NetInfo: {
|
||||
isConnected: {
|
||||
|
|
@ -32,7 +34,9 @@ mockery.registerMock('react-native', {
|
|||
mockery.registerMock('react-native-device-info', {
|
||||
getDeviceLocale() {
|
||||
return 'en';
|
||||
}
|
||||
},
|
||||
getBuildNumber: () => true,
|
||||
getVersion: () => true
|
||||
});
|
||||
mockery.registerMock('react-native-sentry', {
|
||||
Sentry: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue