Merge pull request #1827 from mattermost/merge-1.9
Merge release 1.9 into master
This commit is contained in:
commit
f273d26435
16 changed files with 74 additions and 171 deletions
10
Makefile
10
Makefile
|
|
@ -177,10 +177,6 @@ run-android: | check-device-android pre-run prepare-android-build ## Runs the ap
|
|||
fi
|
||||
|
||||
build-ios: | pre-run check-style ## Creates an iOS build
|
||||
ifneq ($(IOS_APP_GROUP),)
|
||||
@mkdir -p assets/override
|
||||
@echo "{\n\t\"AppGroupId\": \"$$IOS_APP_GROUP\"\n}" > assets/override/config.json
|
||||
endif
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
npm start & echo; \
|
||||
|
|
@ -188,7 +184,6 @@ endif
|
|||
@echo "Building iOS app"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane ios build
|
||||
@ps -e | grep -i "cli.js start" | grep -iv grep | awk '{print $$1}' | xargs kill -9
|
||||
@rm -rf assets/override
|
||||
|
||||
build-android: | pre-run check-style prepare-android-build ## Creates an Android build
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
|
|
@ -205,17 +200,12 @@ unsigned-ios: pre-run check-style
|
|||
npm start & echo; \
|
||||
fi
|
||||
@echo "Building unsigned iOS app"
|
||||
ifneq ($(IOS_APP_GROUP),)
|
||||
@mkdir -p assets/override
|
||||
@echo "{\n\t\"AppGroupId\": \"$$IOS_APP_GROUP\"\n}" > assets/override/config.json
|
||||
endif
|
||||
@cd fastlane && NODE_ENV=production bundle exec fastlane ios unsigned
|
||||
@mkdir -p build-ios
|
||||
@cd ios/ && xcodebuild -workspace Mattermost.xcworkspace/ -scheme Mattermost -sdk iphoneos -configuration Relase -parallelizeTargets -resultBundlePath ../build-ios/result -derivedDataPath ../build-ios/ CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
|
||||
@cd build-ios/ && mkdir -p Payload && cp -R Build/Products/Release-iphoneos/Mattermost.app Payload/ && zip -r Mattermost-unsigned.ipa Payload/
|
||||
@mv build-ios/Mattermost-unsigned.ipa .
|
||||
@rm -rf build-ios/
|
||||
@rm -rf assets/override
|
||||
@ps -e | grep -i "cli.js start" | grep -iv grep | awk '{print $$1}' | xargs kill -9
|
||||
|
||||
unsigned-android: pre-run check-style prepare-android-build
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ android {
|
|||
applicationId "com.mattermost.rnbeta"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 114
|
||||
versionName "1.9.1"
|
||||
versionCode 115
|
||||
versionName "1.9.2"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export function loadFromPushNotification(notification) {
|
|||
// we should get the posts
|
||||
if (channelId === currentChannelId) {
|
||||
dispatch(markChannelAsRead(channelId, null, false));
|
||||
await dispatch(retryGetPostsAction(getPosts(channelId)));
|
||||
await retryGetPostsAction(getPosts(channelId), dispatch, getState);
|
||||
} else {
|
||||
// when the notification is from a channel other than the current channel
|
||||
dispatch(markChannelAsRead(channelId, currentChannelId, false));
|
||||
|
|
|
|||
|
|
@ -168,6 +168,9 @@ export default class AttachmentButton extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
// Decode file uri to get the actual path
|
||||
res.uri = decodeURIComponent(res.uri);
|
||||
|
||||
this.uploadFiles([res]);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Alert, BackHandler, Keyboard, Platform, Text, TouchableOpacity, View} from 'react-native';
|
||||
import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, TouchableOpacity, View} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {General, RequestStatus} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
|
@ -11,7 +11,6 @@ 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 {confirmOutOfOfficeDisabled} from 'app/utils/status';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
|
@ -527,7 +526,7 @@ export default class PostTextbox extends PureComponent {
|
|||
<View style={style.inputWrapper}>
|
||||
{!channelIsReadOnly && attachmentButton}
|
||||
<View style={[inputContainerStyle, (channelIsReadOnly && {marginLeft: 10})]}>
|
||||
<QuickTextInput
|
||||
<TextInput
|
||||
ref='input'
|
||||
value={textValue}
|
||||
onChangeText={this.handleTextChange}
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
// 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
|
||||
export default class QuickTextInput extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
||||
/**
|
||||
* Whether to delay updating the value of the textbox from props. Should only be used
|
||||
* on textboxes that require it to properly compose CJK characters as the user types.
|
||||
*/
|
||||
delayInputUpdate: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The string value displayed in this input
|
||||
*/
|
||||
value: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
delayInputUpdate: false,
|
||||
value: '',
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.value !== this.props.value) {
|
||||
if (this.props.delayInputUpdate) {
|
||||
requestAnimationFrame(this.updateInputFromProps);
|
||||
} else {
|
||||
this.updateInputFromProps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateInputFromProps = () => {
|
||||
if (!this.input) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.input.setNativeProps({text: this.props.value});
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this.input.value;
|
||||
}
|
||||
|
||||
set value(value) {
|
||||
this.input.setNativeProps({text: this.props.value});
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
getInput = () => {
|
||||
return this.input;
|
||||
};
|
||||
|
||||
setInput = (input) => {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {value, ...props} = this.props;
|
||||
|
||||
Reflect.deleteProperty(props, 'delayInputUpdate');
|
||||
|
||||
// Only set the defaultValue since the real one will be updated using componentDidUpdate if necessary
|
||||
return (
|
||||
<TextInput
|
||||
{...props}
|
||||
ref={this.setInput}
|
||||
defaultValue={value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -278,67 +278,53 @@ export default class Downloader extends PureComponent {
|
|||
startDownload = async () => {
|
||||
const {file, downloadPath, prompt, saveToCameraRoll} = this.props;
|
||||
const {data} = file;
|
||||
let downloadFile = true;
|
||||
|
||||
try {
|
||||
if (this.state.didCancel) {
|
||||
this.setState({didCancel: false});
|
||||
}
|
||||
|
||||
let path;
|
||||
let res;
|
||||
if (data && data.localPath) {
|
||||
path = data.localPath;
|
||||
downloadFile = false;
|
||||
this.setState({
|
||||
progress: 100,
|
||||
started: true,
|
||||
});
|
||||
}
|
||||
const certificate = await mattermostBucket.getPreference('cert', LocalConfig.AppGroupId);
|
||||
const imageUrl = Client4.getFileUrl(data.id);
|
||||
const options = {
|
||||
session: data.id,
|
||||
timeout: 10000,
|
||||
indicator: true,
|
||||
overwrite: true,
|
||||
certificate,
|
||||
};
|
||||
|
||||
if (downloadFile) {
|
||||
const certificate = await mattermostBucket.getPreference('cert', LocalConfig.AppGroupId);
|
||||
const imageUrl = Client4.getFileUrl(data.id);
|
||||
const options = {
|
||||
session: data.id,
|
||||
timeout: 10000,
|
||||
indicator: true,
|
||||
overwrite: true,
|
||||
certificate,
|
||||
};
|
||||
|
||||
if (downloadPath && prompt) {
|
||||
const isDir = await RNFetchBlob.fs.isDir(downloadPath);
|
||||
if (!isDir) {
|
||||
try {
|
||||
await RNFetchBlob.fs.mkdir(downloadPath);
|
||||
} catch (error) {
|
||||
this.showDownloadFailedAlert();
|
||||
return;
|
||||
}
|
||||
if (downloadPath && prompt) {
|
||||
const isDir = await RNFetchBlob.fs.isDir(downloadPath);
|
||||
if (!isDir) {
|
||||
try {
|
||||
await RNFetchBlob.fs.mkdir(downloadPath);
|
||||
} catch (error) {
|
||||
this.showDownloadFailedAlert();
|
||||
return;
|
||||
}
|
||||
|
||||
options.path = `${downloadPath}/${data.id}-${file.caption}`;
|
||||
} else {
|
||||
options.fileCache = true;
|
||||
options.appendExt = data.extension;
|
||||
}
|
||||
|
||||
this.downloadTask = RNFetchBlob.config(options).fetch('GET', imageUrl);
|
||||
this.downloadTask.progress((received, total) => {
|
||||
const progress = (received / total) * 100;
|
||||
if (this.mounted) {
|
||||
this.setState({
|
||||
progress,
|
||||
started: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
res = await this.downloadTask;
|
||||
path = res.path();
|
||||
options.path = `${downloadPath}/${data.id}-${file.caption}`;
|
||||
} else {
|
||||
options.fileCache = true;
|
||||
options.appendExt = data.extension;
|
||||
}
|
||||
|
||||
this.downloadTask = RNFetchBlob.config(options).fetch('GET', imageUrl);
|
||||
this.downloadTask.progress((received, total) => {
|
||||
const progress = (received / total) * 100;
|
||||
if (this.mounted) {
|
||||
this.setState({
|
||||
progress,
|
||||
started: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const res = await this.downloadTask;
|
||||
let path = res.path();
|
||||
|
||||
if (saveToCameraRoll) {
|
||||
path = await CameraRoll.saveToCameraRoll(path, 'photo');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@ export default class VideoPreview extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let path = null;
|
||||
const {file} = props;
|
||||
if (file && file.data && file.data.localPath) {
|
||||
path = file.data.localPath;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
isFullScreen: false,
|
||||
|
|
@ -47,7 +53,7 @@ export default class VideoPreview extends PureComponent {
|
|||
paused: true,
|
||||
currentTime: 0,
|
||||
duration: 0,
|
||||
path: null,
|
||||
path,
|
||||
showDownloader: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -84,7 +90,7 @@ export default class VideoPreview extends PureComponent {
|
|||
|
||||
onDownloadSuccess = () => {
|
||||
const {file} = this.props;
|
||||
const path = `${VIDEOS_PATH}/${file.data.id}-${file.caption}`;
|
||||
const path = file.data.localPath || `${VIDEOS_PATH}/${file.data.id}-${file.caption}`;
|
||||
|
||||
this.setState({showDownloader: false, path});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,23 +19,22 @@ export function createSentryMiddleware() {
|
|||
}
|
||||
|
||||
function makeBreadcrumbFromAction(action) {
|
||||
if (!action.type) {
|
||||
console.warn('dispatching action with undefined type', action); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
const breadcrumb = {
|
||||
category: BREADCRUMB_REDUX_ACTION,
|
||||
message: action.type,
|
||||
message: action.type || 'undefined action',
|
||||
};
|
||||
|
||||
if (action.type === BATCH) {
|
||||
// Attach additional information so that batched actions display what they're doing
|
||||
breadcrumb.data = action.payload.map((a) => a.type);
|
||||
}
|
||||
|
||||
if (action.type === BATCH) {
|
||||
// Attach additional information so that batched actions display what they're doing, and make it
|
||||
// into an object because that's what is expected
|
||||
breadcrumb.data = {};
|
||||
|
||||
action.payload.forEach((a, index) => {
|
||||
breadcrumb.data[index] = a.type;
|
||||
breadcrumb.data[index] = a.type || 'undefined action';
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,12 @@ platform :ios do
|
|||
entitlements_file: './ios/MattermostShare/MattermostShare.entitlements',
|
||||
app_group_identifiers: [ENV['IOS_APP_GROUP']]
|
||||
)
|
||||
|
||||
find_replace_string(
|
||||
path_to_file: './dist/assets/config.json',
|
||||
old_string: 'group.com.mattermost.rnbeta',
|
||||
new_string: ENV['IOS_APP_GROUP']
|
||||
)
|
||||
end
|
||||
|
||||
unless ENV['IOS_EXTENSION_APP_IDENTIFIER'].nil? || ENV['IOS_EXTENSION_APP_IDENTIFIER'].empty? || ENV['IOS_EXTENSION_APP_IDENTIFIER'] == 'com.mattermost.rnbeta.MattermostShare'
|
||||
|
|
|
|||
|
|
@ -2533,7 +2533,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 114;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -2583,7 +2583,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 114;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.1</string>
|
||||
<string>1.9.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>114</string>
|
||||
<string>115</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.1</string>
|
||||
<string>1.9.2</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>114</string>
|
||||
<string>115</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.1</string>
|
||||
<string>1.9.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>114</string>
|
||||
<string>115</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -10100,8 +10100,8 @@
|
|||
}
|
||||
},
|
||||
"mattermost-redux": {
|
||||
"version": "github:mattermost/mattermost-redux#023c043afea98ca35e9c0724d280eef09541da40",
|
||||
"from": "github:mattermost/mattermost-redux#023c043afea98ca35e9c0724d280eef09541da40",
|
||||
"version": "github:mattermost/mattermost-redux#ab7fa589f8bbad4f1b2e39f13342dc12d0df98fa",
|
||||
"from": "github:mattermost/mattermost-redux#ab7fa589f8bbad4f1b2e39f13342dc12d0df98fa",
|
||||
"requires": {
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint-plugin-header": "1.2.0",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"intl": "1.2.5",
|
||||
"jail-monkey": "1.0.0",
|
||||
"jsc-android": "216113.0.3",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#023c043afea98ca35e9c0724d280eef09541da40",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#ab7fa589f8bbad4f1b2e39f13342dc12d0df98fa",
|
||||
"mime-db": "1.33.0",
|
||||
"prop-types": "15.6.1",
|
||||
"react": "16.3.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue