Compare commits

..

12 Commits

Author SHA1 Message Date
Elias Nahum
78aba1fcb6 Bump Android build number to 122 (#1883) 2018-07-04 10:50:39 -04:00
Elias Nahum
cba4908854 Bump iOS build number to 122 (#1882) 2018-07-04 10:41:47 -04:00
Harrison Healey
9169f6f694 Add setNativeProps to QuickTextInput (#1880) 2018-07-04 09:38:00 -04:00
Elias Nahum
bdc487ab20 Bump Android build number to 121 (#1875) 2018-07-03 19:44:54 -04:00
Elias Nahum
d7cc95c7f8 Bump iOS build number to 121 (#1874) 2018-07-03 19:39:18 -04:00
Elias Nahum
52ad889bfc Bump Android build number to 120 (#1869) 2018-07-03 19:20:07 -04:00
Elias Nahum
7be6911b2c Bump iOS build number to 120 (#1868) 2018-07-03 19:19:02 -04:00
Harrison Healey
509dfe5542 MM-11116 Re-added QuickTextInput and added another hack on top of it (#1871)
* MM-11116 Re-added updated QuickTextInput component to work around RN issue

* MM-11116 Work around setNativeProps not working for TextInputs

* Add isFocused method to QuickTextInput
2018-07-03 19:04:04 -04:00
Elias Nahum
952aeaf786 Bump Android build number to 119 (#1865) 2018-07-03 10:56:47 -04:00
Elias Nahum
8a7b27de2f Bump iOS build number to 119 (#1864) 2018-07-03 10:45:36 -04:00
Elias Nahum
2ec26e2a0a Bump app version to 1.9.3 2018-07-03 10:29:33 -04:00
Elias Nahum
8c066e0ba3 Attempt to fix some crashes (#1860)
* Attempt to fix some crashes

* remove unnecessary shareExtensionData middleware
2018-07-03 10:14:55 -04:00
19 changed files with 186 additions and 64 deletions

View File

@@ -113,8 +113,8 @@ android {
applicationId "com.mattermost.rnbeta"
minSdkVersion 21
targetSdkVersion 23
versionCode 117
versionName "1.9.2"
versionCode 122
versionName "1.9.3"
ndk {
abiFilters "armeabi-v7a", "x86"
}

View File

@@ -3,7 +3,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, TouchableOpacity, View} from 'react-native';
import {Alert, BackHandler, Keyboard, Platform, Text, TouchableOpacity, View} from 'react-native';
import {intlShape} from 'react-intl';
import {RequestStatus} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@@ -11,6 +11,7 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter';
import AttachmentButton from 'app/components/attachment_button';
import Autocomplete from 'app/components/autocomplete';
import FileUploadPreview from 'app/components/file_upload_preview';
import QuickTextInput from 'app/components/quick_text_input';
import {INITIAL_HEIGHT, INSERT_TO_COMMENT, INSERT_TO_DRAFT, IS_REACTION_REGEX, MAX_CONTENT_HEIGHT, MAX_FILE_COUNT} from 'app/constants/post_textbox';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@@ -494,7 +495,7 @@ export default class PostTextbox extends PureComponent {
<View style={style.inputWrapper}>
{!channelIsReadOnly && attachmentButton}
<View style={[inputContainerStyle, (channelIsReadOnly && {marginLeft: 10})]}>
<TextInput
<QuickTextInput
ref='input'
value={textValue}
onChangeText={this.handleTextChange}

View File

@@ -0,0 +1,124 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import PropTypes from 'prop-types';
import React from 'react';
import {TextInput} from 'react-native';
// A component that can be used to make partially-controlled inputs that can be updated
// by changing the value prop without lagging the UI.
//
// We're using this in place of a connected TextInput due to changes made in RN v0.54
// that break input in Chinese and Japanese when using a connected TextInput. See
// https://github.com/facebook/react-native/issues/18403 for more information.
//
// In addition to that, there's also an ugly hack to change the key on the TextInput
// when this is triggered because that same version made setNativeProps work inconsistently.
// See https://github.com/facebook/react-native/issues/18272 for more information on that.
export default class QuickTextInput extends React.PureComponent {
static propTypes = {
onChangeText: PropTypes.func,
/**
* The string value displayed in this input
*/
value: PropTypes.string.isRequired,
};
static defaultProps = {
delayInputUpdate: false,
value: '',
};
constructor(props) {
super(props);
this.storedValue = props.value;
this.state = {
key: 0,
};
}
componentDidMount() {
this.updateInputFromProps();
}
UNSAFE_componentWillReceiveProps(nextProps) { // eslint-disable-line camelcase
// This will force the base TextInput to re-render if the value is changing
// from something other than the user typing in it. This does however cause
// the TextInput to flicker when this happens.
if (nextProps.value !== this.storedValue) {
this.setState({
key: this.state.key + 1,
});
}
this.hadFocus = this.isFocused();
}
componentDidUpdate(prevProps, prevState) {
if (this.props.value !== this.storedValue) {
this.updateInputFromProps();
}
if (prevState.key !== this.state.key && this.hadFocus) {
this.input.focus();
}
}
updateInputFromProps = () => {
if (!this.input) {
return;
}
this.input.setNativeProps({text: this.props.value});
this.storedValue = this.props.value;
}
setNativeProps(nativeProps) {
this.input.setNativeProps(nativeProps);
}
focus() {
this.input.focus();
}
blur() {
this.input.blur();
}
isFocused() {
return this.input.isFocused();
}
handleChangeText = (value) => {
this.storedValue = value;
if (this.props.onChangeText) {
this.props.onChangeText(value);
}
}
setInput = (input) => {
this.input = input;
}
render() {
const props = {...this.props};
// Specifying a value or defaultValue cause the issues noted above
Reflect.deleteProperty(props, 'value');
Reflect.deleteProperty(props, 'defaultValue');
return (
<TextInput
{...props}
key={this.state.key}
onChangeText={this.handleChangeText}
ref={this.setInput}
/>
);
}
}

View File

@@ -5,13 +5,13 @@ import PropTypes from 'prop-types';
import {
InteractionManager,
Keyboard,
TextInput,
StyleSheet,
View,
TouchableWithoutFeedback,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import QuickTextInput from 'app/components/quick_text_input';
import CustomPropTypes from 'app/constants/custom_prop_types';
import {changeOpacity} from 'app/utils/theme';
@@ -208,7 +208,7 @@ export default class SearchBarAndroid extends PureComponent {
color={tintColorSearch || placeholderTextColor}
/>
}
<TextInput
<QuickTextInput
ref='input'
blurOnSubmit={blurOnSubmit}
value={this.state.value}

View File

@@ -6,6 +6,8 @@ import PropTypes from 'prop-types';
import {injectIntl, intlShape} from 'react-intl';
import {TextInput} from 'react-native';
import QuickTextInput from 'app/components/quick_text_input';
class TextInputWithLocalizedPlaceholder extends PureComponent {
static propTypes = {
...TextInput.propTypes,
@@ -29,7 +31,7 @@ class TextInputWithLocalizedPlaceholder extends PureComponent {
}
return (
<TextInput
<QuickTextInput
ref='input'
{...otherProps}
placeholder={placeholderString}

View File

@@ -6,10 +6,10 @@ import PropTypes from 'prop-types';
import {
View,
Text,
TextInput,
} from 'react-native';
import FormattedText from 'app/components/formatted_text';
import QuickTextInput from 'app/components/quick_text_input';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
export default class AccountSettingsItem extends PureComponent {
@@ -65,7 +65,7 @@ export default class AccountSettingsItem extends PureComponent {
)}
</View>
<View style={style.inputContainer}>
<TextInput
<QuickTextInput
ref={this.channelNameRef}
value={value}
onChangeText={this.onChangeText}

View File

@@ -12,7 +12,6 @@ import {
Keyboard,
StyleSheet,
Text,
TextInput,
TouchableWithoutFeedback,
View,
} from 'react-native';
@@ -21,6 +20,7 @@ import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import ErrorText from 'app/components/error_text';
import FormattedText from 'app/components/formatted_text';
import QuickTextInput from 'app/components/quick_text_input';
import StatusBar from 'app/components/status_bar';
import PushNotifications from 'app/push_notifications';
import {GlobalStyles} from 'app/styles';
@@ -364,7 +364,7 @@ export default class Login extends PureComponent {
/>
</View>
<ErrorText error={this.getLoginErrorMessage()}/>
<TextInput
<QuickTextInput
ref={this.loginRef}
value={this.props.loginId}
onChangeText={this.props.actions.handleLoginIdChanged}
@@ -379,7 +379,7 @@ export default class Login extends PureComponent {
blurOnSubmit={false}
disableFullscreenUI={true}
/>
<TextInput
<QuickTextInput
ref={this.passwordRef}
value={this.props.password}
onChangeText={this.props.actions.handlePasswordChanged}

View File

@@ -13,7 +13,6 @@ import {
StatusBar,
StyleSheet,
Text,
TextInput,
TouchableWithoutFeedback,
View,
} from 'react-native';
@@ -23,6 +22,7 @@ import {Client4} from 'mattermost-redux/client';
import ErrorText from 'app/components/error_text';
import FormattedText from 'app/components/formatted_text';
import QuickTextInput from 'app/components/quick_text_input';
import {UpgradeTypes} from 'app/constants/view';
import {GlobalStyles} from 'app/styles';
import checkUpgradeType from 'app/utils/client_upgrade';
@@ -346,7 +346,7 @@ export default class SelectServer extends PureComponent {
defaultMessage='Enter Server URL'
/>
</View>
<TextInput
<QuickTextInput
ref={this.inputRef}
value={url}
editable={!inputDisabled}

View File

@@ -20,7 +20,7 @@ import {createSentryMiddleware} from 'app/utils/sentry/middleware';
import mattermostBucket from 'app/mattermost_bucket';
import Config from 'assets/config';
import {messageRetention, shareExtensionData} from './middleware';
import {messageRetention} from './middleware';
import {transformSet} from './utils';
function getAppReducer() {
@@ -208,6 +208,10 @@ export default function configureAppStore(initialState) {
},
]));
// When logging out remove the data stored in the bucket
mattermostBucket.removePreference('emm', Config.AppGroupId);
mattermostBucket.removeFile('entities', Config.AppGroupId);
setTimeout(() => {
purging = false;
}, 500);
@@ -267,7 +271,7 @@ export default function configureAppStore(initialState) {
},
};
const additionalMiddleware = [createSentryMiddleware(), messageRetention, shareExtensionData];
const additionalMiddleware = [createSentryMiddleware(), messageRetention];
return configureStore(initialState, appReducer, offlineOptions, getAppReducer, {
additionalMiddleware,
});

View File

@@ -3,12 +3,8 @@
import DeviceInfo from 'react-native-device-info';
import {UserTypes} from 'mattermost-redux/action_types';
import {ViewTypes} from 'app/constants';
import initialState from 'app/initial_state';
import mattermostBucket from 'app/mattermost_bucket';
import Config from 'assets/config';
import {
captureException,
@@ -354,21 +350,6 @@ function cleanupState(action, keepCurrent = false) {
};
}
export function shareExtensionData() {
return (next) => (action) => {
// allow other middleware to do their things
const nextAction = next(action);
switch (action.type) {
case UserTypes.LOGOUT_SUCCESS:
mattermostBucket.removePreference('emm', Config.AppGroupId);
mattermostBucket.removeFile('entities', Config.AppGroupId);
break;
}
return nextAction;
};
}
function removePendingPost(pendingPostIds, id) {
const pendingIndex = pendingPostIds.indexOf(id);
if (pendingIndex !== -1) {

View File

@@ -22,16 +22,16 @@ import {
import {app, store} from 'app/mattermost';
const errorHandler = (e, isFatal) => {
console.warn('Handling Javascript error ' + JSON.stringify(e)); // eslint-disable-line no-console
const {dispatch, getState} = store;
console.warn('Handling Javascript error ', e); // eslint-disable-line no-console
const {dispatch} = store;
captureException(e, LOGGER_JAVASCRIPT, store);
const translations = app.getTranslations();
closeWebSocket()(dispatch, getState);
dispatch(closeWebSocket());
if (Client4.getUrl()) {
logError(e)(dispatch, getState);
dispatch(logError(e));
}
if (isFatal) {
@@ -42,7 +42,7 @@ const errorHandler = (e, isFatal) => {
text: translations['mobile.error_handler.button'],
onPress: () => {
// purge the store
purgeOfflineStore()(dispatch, getState);
dispatch(purgeOfflineStore());
},
}],
{cancelable: false}

View File

@@ -45,9 +45,11 @@ function getDsn() {
}
export function captureException(error, logger, store) {
capture(() => {
Sentry.captureException(error, {logger});
}, store);
if (error && logger && store) {
capture(() => {
Sentry.captureException(error, {logger});
}, store);
}
}
export function captureExceptionWithoutState(err, logger) {
@@ -55,17 +57,21 @@ export function captureExceptionWithoutState(err, logger) {
return;
}
try {
Sentry.captureException(err, {logger});
} catch (error) {
// do nothing...
if (err && logger) {
try {
Sentry.captureException(err, {logger});
} catch (error) {
// do nothing...
}
}
}
export function captureMessage(message, logger, store) {
capture(() => {
Sentry.captureMessage(message, {logger});
}, store);
if (message && logger && store) {
capture(() => {
Sentry.captureMessage(message, {logger});
}, store);
}
}
// Wrapper function to any calls to Sentry so that we can gather any necessary extra data

View File

@@ -2516,7 +2516,7 @@
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 117;
CURRENT_PROJECT_VERSION = 122;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
ENABLE_BITCODE = NO;
@@ -2566,7 +2566,7 @@
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 117;
CURRENT_PROJECT_VERSION = 122;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
ENABLE_BITCODE = NO;

View File

@@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.9.2</string>
<string>1.9.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@@ -34,7 +34,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>117</string>
<string>122</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>

View File

@@ -81,7 +81,9 @@ RCT_EXPORT_METHOD(removePreference:(NSString *) key
if(![fileManager fileExistsAtPath:filePath]) {
[fileManager createFileAtPath:filePath contents:nil attributes:nil];
}
[content writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
if ([content length] > 0) {
[content writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
}
-(NSString *)readFromFile:(NSString *)fileName appGroupId:(NSString *)appGroupId {
@@ -107,7 +109,9 @@ RCT_EXPORT_METHOD(removePreference:(NSString *) key
-(void) setPreference:(NSString *)key value:(NSString *) value appGroupId:(NSString*)appGroupId {
NSUserDefaults* bucket = [self bucketByName: appGroupId];
[bucket setObject:value forKey:key];
if ([key length] > 0 && [value length] > 0) {
[bucket setObject:value forKey:key];
}
}
-(id) getPreference:(NSString *)key appGroupId:(NSString*)appGroupId {

View File

@@ -21,9 +21,9 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.9.2</string>
<string>1.9.3</string>
<key>CFBundleVersion</key>
<string>117</string>
<string>122</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>

View File

@@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.9.2</string>
<string>1.9.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>117</string>
<string>122</string>
</dict>
</plist>

View File

@@ -13,7 +13,6 @@ import {
PermissionsAndroid,
ScrollView,
Text,
TextInput,
View,
} from 'react-native';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
@@ -24,6 +23,7 @@ import RNFetchBlob from 'react-native-fetch-blob';
import {Preferences} from 'mattermost-redux/constants';
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
import QuickTextInput from 'app/components/quick_text_input';
import PaperPlane from 'app/components/paper_plane';
import mattermostManaged from 'app/mattermost_managed';
import {getExtensionFromMime} from 'app/utils/file';
@@ -339,7 +339,7 @@ export default class ExtensionPost extends PureComponent {
contentContainerStyle={styles.scrollView}
style={styles.flex}
>
<TextInput
<QuickTextInput
ref={this.getInputRef}
autoCapitalize='sentences'
maxLength={MAX_MESSAGE_LENGTH}

View File

@@ -12,7 +12,6 @@ import {
NativeModules,
ScrollView,
Text,
TextInput,
TouchableHighlight,
View,
} from 'react-native';
@@ -27,6 +26,7 @@ import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
import QuickTextInput from 'app/components/quick_text_input';
import mattermostBucket from 'app/mattermost_bucket';
import {generateId, getAllowedServerMaxFileSize} from 'app/utils/file';
import {preventDoubleTap} from 'app/utils/tap';
@@ -358,7 +358,7 @@ export default class ExtensionPost extends PureComponent {
contentContainerStyle={styles.scrollView}
style={styles.flex}
>
<TextInput
<QuickTextInput
ref={this.getInputRef}
maxLength={MAX_MESSAGE_LENGTH}
multiline={true}