Enable Android Unbundle strategy (perf part 2) (#1700)
* Enable Android Unbundle strategy * feedback review * Update modulePaths * Add npm start and use it in the Makefile * feedback review #2
This commit is contained in:
parent
a3eeb23419
commit
c171ae4809
27 changed files with 1555 additions and 299 deletions
|
|
@ -59,7 +59,7 @@
|
|||
"func-names": 2,
|
||||
"func-style": [2, "declaration", { "allowArrowFunctions": true }],
|
||||
"generator-star-spacing": [0, {"before": false, "after": true}],
|
||||
"global-require": 2,
|
||||
"global-require": 0,
|
||||
"guard-for-in": 2,
|
||||
"id-blacklist": 0,
|
||||
"indent": [2, 4, {"SwitchCase": 0}],
|
||||
|
|
@ -261,4 +261,4 @@
|
|||
"wrap-regex": 2,
|
||||
"yoda": [2, "never", {"exceptRange": false, "onlyEquality": false}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
Makefile
14
Makefile
|
|
@ -89,7 +89,7 @@ post-install:
|
|||
start: | pre-run ## Starts the React Native packager server
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start; \
|
||||
npm start; \
|
||||
else \
|
||||
echo React Native packager server already running; \
|
||||
fi
|
||||
|
|
@ -141,7 +141,7 @@ run: run-ios ## alias for run-ios
|
|||
run-ios: | check-device-ios pre-run ## Runs the app on an iOS simulator
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo Running iOS app in development; \
|
||||
npm start & echo Running iOS app in development; \
|
||||
if [ ! -z "${SIMULATOR}" ]; then \
|
||||
react-native run-ios --simulator="${SIMULATOR}"; \
|
||||
else \
|
||||
|
|
@ -160,7 +160,7 @@ run-ios: | check-device-ios pre-run ## Runs the app on an iOS simulator
|
|||
run-android: | check-device-android pre-run prepare-android-build ## Runs the app on an Android emulator or dev device
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo Running Android app in development; \
|
||||
npm start & echo Running Android app in development; \
|
||||
if [ ! -z ${VARIANT} ]; then \
|
||||
react-native run-android --no-packager --variant=${VARIANT}; \
|
||||
else \
|
||||
|
|
@ -183,7 +183,7 @@ ifneq ($(IOS_APP_GROUP),)
|
|||
endif
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo; \
|
||||
npm start & echo; \
|
||||
fi
|
||||
@echo "Building iOS app"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane ios build
|
||||
|
|
@ -193,7 +193,7 @@ endif
|
|||
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 \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo; \
|
||||
npm start & echo; \
|
||||
fi
|
||||
@echo "Building Android app"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane android build
|
||||
|
|
@ -202,7 +202,7 @@ build-android: | pre-run check-style prepare-android-build ## Creates an Android
|
|||
unsigned-ios: pre-run check-style
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo; \
|
||||
npm start & echo; \
|
||||
fi
|
||||
@echo "Building unsigned iOS app"
|
||||
ifneq ($(IOS_APP_GROUP),)
|
||||
|
|
@ -221,7 +221,7 @@ endif
|
|||
unsigned-android: pre-run check-style prepare-android-build
|
||||
@if [ $(shell ps -e | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
node ./node_modules/react-native/local-cli/cli.js start & echo; \
|
||||
npm start & echo; \
|
||||
fi
|
||||
@echo "Building unsigned Android app"
|
||||
@cd fastlane && NODE_ENV=production bundle exec fastlane android unsigned
|
||||
|
|
|
|||
|
|
@ -73,7 +73,9 @@ import com.android.build.OutputFile
|
|||
*/
|
||||
|
||||
project.ext.react = [
|
||||
entryFile: "index.js"
|
||||
entryFile: "index.js",
|
||||
bundleCommand: "unbundle",
|
||||
bundleConfig: "packager/config.js"
|
||||
]
|
||||
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import configureStore from 'redux-mock-store';
|
||||
|
|
@ -11,9 +11,11 @@ import {
|
|||
handlePasswordChanged,
|
||||
} from 'app/actions/views/login';
|
||||
|
||||
jest.mock('react-native-fetch-blob', () => ({
|
||||
DocumentDir: () => jest.fn(),
|
||||
fs: {dirs: {CacheDir: () => jest.fn()}},
|
||||
jest.mock('react-native-fetch-blob/fs', () => ({
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockStore = configureStore([thunk]);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
|
|
@ -11,9 +11,11 @@ import {ViewTypes} from 'app/constants';
|
|||
|
||||
import {handleServerUrlChanged} from 'app/actions/views/select_server';
|
||||
|
||||
jest.mock('react-native-fetch-blob', () => ({
|
||||
DocumentDir: () => jest.fn(),
|
||||
fs: {dirs: {CacheDir: () => jest.fn()}},
|
||||
jest.mock('react-native-fetch-blob/fs', () => ({
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockStore = configureStore([thunk]);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import configureStore from 'redux-mock-store';
|
||||
|
|
@ -11,9 +11,11 @@ import {
|
|||
handleCommentDraftSelectionChanged,
|
||||
} from 'app/actions/views/thread';
|
||||
|
||||
jest.mock('react-native-fetch-blob', () => ({
|
||||
DocumentDir: () => jest.fn(),
|
||||
fs: {dirs: {CacheDir: () => jest.fn()}},
|
||||
jest.mock('react-native-fetch-blob/fs', () => ({
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockStore = configureStore([thunk]);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
|
|
@ -15,19 +15,19 @@ import {intlShape} from 'react-intl';
|
|||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import FileAttachmentList from 'app/components/file_attachment_list';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import OptionsContext from 'app/components/options_context';
|
||||
import PostAddChannelMember from 'app/components/post_add_channel_member';
|
||||
|
||||
import PostBodyAdditionalContent from 'app/components/post_body_additional_content';
|
||||
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import Reactions from 'app/components/reactions';
|
||||
|
||||
let FileAttachmentList;
|
||||
let PostAddChannelMember;
|
||||
let PostBodyAdditionalContent;
|
||||
let Reactions;
|
||||
|
||||
export default class PostBody extends PureComponent {
|
||||
static propTypes = {
|
||||
|
|
@ -229,6 +229,31 @@ export default class PostBody extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
renderAddChannelMember = (style, textStyles) => {
|
||||
const {onPermalinkPress, onPress, postProps} = this.props;
|
||||
|
||||
if (!PostAddChannelMember) {
|
||||
PostAddChannelMember = require('app/components/post_add_channel_member').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.row}>
|
||||
<View style={style.flex}>
|
||||
<PostAddChannelMember
|
||||
navigator={navigator}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
onPostPress={onPress}
|
||||
textStyles={textStyles}
|
||||
postId={postProps.add_channel_member.post_id}
|
||||
userIds={postProps.add_channel_member.user_ids}
|
||||
usernames={postProps.add_channel_member.usernames}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderFileAttachments() {
|
||||
const {
|
||||
fileIds,
|
||||
|
|
@ -246,6 +271,10 @@ export default class PostBody extends PureComponent {
|
|||
|
||||
let attachments;
|
||||
if (fileIds.length > 0) {
|
||||
if (!FileAttachmentList) {
|
||||
FileAttachmentList = require('app/components/file_attachment_list').default;
|
||||
}
|
||||
|
||||
attachments = (
|
||||
<FileAttachmentList
|
||||
fileIds={fileIds}
|
||||
|
|
@ -265,6 +294,10 @@ export default class PostBody extends PureComponent {
|
|||
renderPostAdditionalContent = (blockStyles, messageStyle, textStyles) => {
|
||||
const {isReplyPost, message, navigator, onPermalinkPress, postId, postProps} = this.props;
|
||||
|
||||
if (!PostBodyAdditionalContent) {
|
||||
PostBodyAdditionalContent = require('app/components/post_body_additional_content').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<PostBodyAdditionalContent
|
||||
baseTextStyle={messageStyle}
|
||||
|
|
@ -288,6 +321,10 @@ export default class PostBody extends PureComponent {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!Reactions) {
|
||||
Reactions = require('app/components/reactions').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<Reactions
|
||||
postId={postId}
|
||||
|
|
@ -364,7 +401,6 @@ export default class PostBody extends PureComponent {
|
|||
onFailedPostPress,
|
||||
onPermalinkPress,
|
||||
onPress,
|
||||
postProps,
|
||||
renderReplyBar,
|
||||
theme,
|
||||
toggleSelected,
|
||||
|
|
@ -397,22 +433,7 @@ export default class PostBody extends PureComponent {
|
|||
);
|
||||
body = (<View>{messageComponent}</View>);
|
||||
} else if (isPostAddChannelMember) {
|
||||
messageComponent = (
|
||||
<View style={style.row}>
|
||||
<View style={style.flex}>
|
||||
<PostAddChannelMember
|
||||
navigator={navigator}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
onPostPress={onPress}
|
||||
textStyles={textStyles}
|
||||
postId={postProps.add_channel_member.post_id}
|
||||
userIds={postProps.add_channel_member.user_ids}
|
||||
usernames={postProps.add_channel_member.usernames}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
messageComponent = this.renderAddChannelMember(style, textStyles);
|
||||
} else if (message.length) {
|
||||
messageComponent = (
|
||||
<View style={style.row}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
|
|
@ -14,10 +14,6 @@ import {
|
|||
import {YouTubeStandaloneAndroid, YouTubeStandaloneIOS} from 'react-native-youtube';
|
||||
import youTubeVideoId from 'youtube-video-id';
|
||||
|
||||
import youtubePlayIcon from 'assets/images/icons/youtube-play-icon.png';
|
||||
|
||||
import MessageAttachments from 'app/components/message_attachments';
|
||||
import PostAttachmentOpenGraph from 'app/components/post_attachment_opengraph';
|
||||
import ProgressiveImage from 'app/components/progressive_image';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
|
|
@ -27,6 +23,9 @@ import {isImageLink, isYoutubeLink} from 'app/utils/url';
|
|||
|
||||
const MAX_IMAGE_HEIGHT = 150;
|
||||
|
||||
let MessageAttachments;
|
||||
let PostAttachmentOpenGraph;
|
||||
|
||||
export default class PostBodyAdditionalContent extends PureComponent {
|
||||
static propTypes = {
|
||||
baseTextStyle: CustomPropTypes.Style,
|
||||
|
|
@ -132,6 +131,9 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
}
|
||||
|
||||
if (link && showLinkPreviews) {
|
||||
if (!PostAttachmentOpenGraph) {
|
||||
PostAttachmentOpenGraph = require('app/components/post_attachment_opengraph').default;
|
||||
}
|
||||
return (
|
||||
<PostAttachmentOpenGraph
|
||||
isReplyPost={isReplyPost}
|
||||
|
|
@ -173,7 +175,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
>
|
||||
<TouchableWithoutFeedback onPress={this.playYouTubeVideo}>
|
||||
<Image
|
||||
source={youtubePlayIcon}
|
||||
source={require('assets/images/icons/youtube-play-icon.png')}
|
||||
onPress={this.playYouTubeVideo}
|
||||
/>
|
||||
</TouchableWithoutFeedback>
|
||||
|
|
@ -261,6 +263,10 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
const {attachments} = postProps;
|
||||
|
||||
if (attachments && attachments.length) {
|
||||
if (!MessageAttachments) {
|
||||
MessageAttachments = require('app/components/message_attachments').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<MessageAttachments
|
||||
attachments={attachments}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
|
|
@ -58,15 +58,18 @@ export default class PostList extends PureComponent {
|
|||
loadMore: () => true,
|
||||
};
|
||||
|
||||
newMessagesIndex = -1;
|
||||
scrollToMessageTries = 0;
|
||||
makeExtraData = makeExtraData();
|
||||
itemMeasurements = {};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
state = {
|
||||
managedConfig: {},
|
||||
scrollToMessage: false,
|
||||
};
|
||||
this.newMessagesIndex = -1;
|
||||
this.makeExtraData = makeExtraData();
|
||||
this.itemMeasurements = {};
|
||||
|
||||
this.state = {
|
||||
managedConfig: {},
|
||||
scrollToMessage: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.listenerId = mattermostManaged.addEventListener('change', this.setManagedConfig);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
|
|
@ -11,12 +11,13 @@ 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 PaperPlane from 'app/components/paper_plane';
|
||||
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';
|
||||
|
||||
import Typing from './components/typing';
|
||||
|
||||
let PaperPlane = null;
|
||||
|
||||
export default class PostTextbox extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -282,35 +283,44 @@ export default class PostTextbox extends PureComponent {
|
|||
const {files, theme} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
const icon = (
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
);
|
||||
const canSend = this.canSend();
|
||||
const imagesLoading = files.filter((f) => f.loading).length > 0;
|
||||
|
||||
let button = null;
|
||||
const imagesLoading = files.filter((f) => f.loading).length > 0;
|
||||
if (imagesLoading) {
|
||||
button = (
|
||||
<View style={style.sendButtonContainer}>
|
||||
<View style={[style.sendButton, style.disableButton]}>
|
||||
{icon}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
if (canSend || imagesLoading) {
|
||||
if (!PaperPlane) {
|
||||
PaperPlane = require('app/components/paper_plane').default;
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
);
|
||||
} else if (this.canSend()) {
|
||||
button = (
|
||||
<TouchableOpacity
|
||||
onPress={this.handleSendMessage}
|
||||
style={style.sendButtonContainer}
|
||||
>
|
||||
<View style={style.sendButton}>
|
||||
{icon}
|
||||
|
||||
if (imagesLoading) {
|
||||
button = (
|
||||
<View style={style.sendButtonContainer}>
|
||||
<View style={[style.sendButton, style.disableButton]}>
|
||||
{icon}
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
);
|
||||
} else if (canSend) {
|
||||
button = (
|
||||
<TouchableOpacity
|
||||
onPress={this.handleSendMessage}
|
||||
style={style.sendButtonContainer}
|
||||
>
|
||||
<View style={style.sendButton}>
|
||||
{icon}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return button;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import keyMirror from 'mattermost-redux/utils/key_mirror';
|
||||
import RNFetchBlob from 'react-native-fetch-blob';
|
||||
import RNFetchBlobFS from 'react-native-fetch-blob/fs';
|
||||
|
||||
const deviceTypes = keyMirror({
|
||||
CONNECTION_CHANGED: null,
|
||||
|
|
@ -14,7 +14,7 @@ const deviceTypes = keyMirror({
|
|||
|
||||
export default {
|
||||
...deviceTypes,
|
||||
DOCUMENTS_PATH: `${RNFetchBlob.fs.dirs.CacheDir}/Documents`,
|
||||
IMAGES_PATH: `${RNFetchBlob.fs.dirs.CacheDir}/Images`,
|
||||
VIDEOS_PATH: `${RNFetchBlob.fs.dirs.CacheDir}/Videos`,
|
||||
DOCUMENTS_PATH: `${RNFetchBlobFS.dirs.CacheDir}/Documents`,
|
||||
IMAGES_PATH: `${RNFetchBlobFS.dirs.CacheDir}/Images`,
|
||||
VIDEOS_PATH: `${RNFetchBlobFS.dirs.CacheDir}/Videos`,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,70 +1,87 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import 'intl';
|
||||
import {addLocaleData} from 'react-intl';
|
||||
import deLocaleData from 'react-intl/locale-data/de';
|
||||
import enLocaleData from 'react-intl/locale-data/en';
|
||||
import esLocaleData from 'react-intl/locale-data/es';
|
||||
import frLocaleData from 'react-intl/locale-data/fr';
|
||||
import itLocaleData from 'react-intl/locale-data/it';
|
||||
import jaLocaleData from 'react-intl/locale-data/ja';
|
||||
import koLocaleData from 'react-intl/locale-data/ko';
|
||||
import nlLocaleData from 'react-intl/locale-data/nl';
|
||||
import plLocaleData from 'react-intl/locale-data/pl';
|
||||
import ptLocaleData from 'react-intl/locale-data/pt';
|
||||
import trLocaleData from 'react-intl/locale-data/tr';
|
||||
import ruLocaleData from 'react-intl/locale-data/ru';
|
||||
import zhLocaleData from 'react-intl/locale-data/zh';
|
||||
|
||||
import {DEFAULT_LOCALE} from 'mattermost-redux/constants/general';
|
||||
|
||||
import de from 'assets/i18n/de.json';
|
||||
import en from 'assets/i18n/en.json';
|
||||
import es from 'assets/i18n/es.json';
|
||||
import fr from 'assets/i18n/fr.json';
|
||||
import it from 'assets/i18n/it.json';
|
||||
import ja from 'assets/i18n/ja.json';
|
||||
import ko from 'assets/i18n/ko.json';
|
||||
import nl from 'assets/i18n/nl.json';
|
||||
import pl from 'assets/i18n/pl.json';
|
||||
import ptBR from 'assets/i18n/pt-BR.json';
|
||||
import tr from 'assets/i18n/tr.json';
|
||||
import ru from 'assets/i18n/ru.json';
|
||||
import zhCN from 'assets/i18n/zh-CN.json';
|
||||
import zhTW from 'assets/i18n/zh-TW.json';
|
||||
|
||||
const TRANSLATIONS = {
|
||||
de,
|
||||
en,
|
||||
es,
|
||||
fr,
|
||||
it,
|
||||
ja,
|
||||
ko,
|
||||
nl,
|
||||
pl,
|
||||
'pt-BR': ptBR,
|
||||
tr,
|
||||
ru,
|
||||
'zh-CN': zhCN,
|
||||
'zh-TW': zhTW,
|
||||
};
|
||||
const TRANSLATIONS = {en};
|
||||
|
||||
export const DEFAULT_LOCALE = 'en';
|
||||
|
||||
addLocaleData(deLocaleData);
|
||||
addLocaleData(enLocaleData);
|
||||
addLocaleData(esLocaleData);
|
||||
addLocaleData(frLocaleData);
|
||||
addLocaleData(itLocaleData);
|
||||
addLocaleData(jaLocaleData);
|
||||
addLocaleData(koLocaleData);
|
||||
addLocaleData(nlLocaleData);
|
||||
addLocaleData(plLocaleData);
|
||||
addLocaleData(ptLocaleData);
|
||||
addLocaleData(trLocaleData);
|
||||
addLocaleData(ruLocaleData);
|
||||
addLocaleData(zhLocaleData);
|
||||
|
||||
function loadTranslation(locale) {
|
||||
try {
|
||||
let localeData;
|
||||
switch (locale) {
|
||||
case 'de':
|
||||
TRANSLATIONS.de = require('assets/i18n/de.json');
|
||||
localeData = require('react-intl/locale-data/de');
|
||||
break;
|
||||
case 'es':
|
||||
TRANSLATIONS.es = require('assets/i18n/es.json');
|
||||
localeData = require('react-intl/locale-data/es');
|
||||
break;
|
||||
case 'fr':
|
||||
TRANSLATIONS.fr = require('assets/i18n/fr.json');
|
||||
localeData = require('react-intl/locale-data/fr');
|
||||
break;
|
||||
case 'it':
|
||||
TRANSLATIONS.it = require('assets/i18n/it.json');
|
||||
localeData = require('react-intl/locale-data/it');
|
||||
break;
|
||||
case 'ja':
|
||||
TRANSLATIONS.ja = require('assets/i18n/ja.json');
|
||||
localeData = require('react-intl/locale-data/ja');
|
||||
break;
|
||||
case 'ko':
|
||||
TRANSLATIONS.ko = require('assets/i18n/ko.json');
|
||||
localeData = require('react-intl/locale-data/ko');
|
||||
break;
|
||||
case 'nl':
|
||||
TRANSLATIONS.nl = require('assets/i18n/nl.json');
|
||||
localeData = require('react-intl/locale-data/nl');
|
||||
break;
|
||||
case 'pl':
|
||||
TRANSLATIONS.pl = require('assets/i18n/pl.json');
|
||||
localeData = require('react-intl/locale-data/pl');
|
||||
break;
|
||||
case 'pt-BT':
|
||||
TRANSLATIONS[locale] = require('assets/i18n/pt-BR.json');
|
||||
localeData = require('react-intl/locale-data/pt');
|
||||
break;
|
||||
case 'tr':
|
||||
TRANSLATIONS.tr = require('assets/i18n/tr.json');
|
||||
localeData = require('react-intl/locale-data/tr');
|
||||
break;
|
||||
case 'ru':
|
||||
TRANSLATIONS.ru = require('assets/i18n/ru.json');
|
||||
localeData = require('react-intl/locale-data/ru');
|
||||
break;
|
||||
case 'zh-CN':
|
||||
TRANSLATIONS[locale] = require('assets/i18n/zh-CN.json');
|
||||
localeData = require('react-intl/locale-data/zh');
|
||||
break;
|
||||
case 'zh-TW':
|
||||
TRANSLATIONS[locale] = require('assets/i18n/zh-TW.json');
|
||||
localeData = require('react-intl/locale-data/zh');
|
||||
break;
|
||||
}
|
||||
|
||||
if (localeData) {
|
||||
addLocaleData(localeData);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('NO Translation found', e); //eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
export function getTranslations(locale) {
|
||||
if (!TRANSLATIONS[locale]) {
|
||||
loadTranslation(locale);
|
||||
}
|
||||
return TRANSLATIONS[locale] || TRANSLATIONS[DEFAULT_LOCALE];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// 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 {
|
||||
AppState,
|
||||
Platform,
|
||||
|
|
@ -12,14 +12,10 @@ import {
|
|||
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import ClientUpgradeListener from 'app/components/client_upgrade_listener';
|
||||
import ChannelDrawer from 'app/components/channel_drawer';
|
||||
import SettingsDrawer from 'app/components/settings_drawer';
|
||||
import ChannelLoader from 'app/components/channel_loader';
|
||||
import KeyboardLayout from 'app/components/layout/keyboard_layout';
|
||||
import Loading from 'app/components/loading';
|
||||
import OfflineIndicator from 'app/components/offline_indicator';
|
||||
import PostListRetry from 'app/components/post_list_retry';
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
|
|
@ -32,7 +28,9 @@ import LocalConfig from 'assets/config';
|
|||
import ChannelNavBar from './channel_nav_bar';
|
||||
import ChannelPostList from './channel_post_list';
|
||||
|
||||
class Channel extends PureComponent {
|
||||
let ClientUpgradeListener;
|
||||
|
||||
export default class Channel extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
connection: PropTypes.func.isRequired,
|
||||
|
|
@ -49,11 +47,22 @@ class Channel extends PureComponent {
|
|||
currentChannelId: PropTypes.string,
|
||||
channelsRequestFailed: PropTypes.bool,
|
||||
currentTeamId: PropTypes.string,
|
||||
intl: intlShape.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
|
||||
ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
EventEmitter.on('leave_team', this.handleLeaveTeam);
|
||||
|
||||
|
|
@ -67,9 +76,7 @@ class Channel extends PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (Platform.OS === 'android') {
|
||||
AppState.addEventListener('change', this.handleAppStateChange);
|
||||
}
|
||||
AppState.addEventListener('change', this.handleAppStateChange);
|
||||
|
||||
if (tracker.initialLoad) {
|
||||
this.props.actions.recordLoadTime('Start time', 'initialLoad');
|
||||
|
|
@ -86,6 +93,10 @@ class Channel extends PureComponent {
|
|||
if (nextProps.currentTeamId && this.props.currentTeamId !== nextProps.currentTeamId) {
|
||||
this.loadChannels(nextProps.currentTeamId);
|
||||
}
|
||||
|
||||
if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
|
||||
ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
|
|
@ -100,20 +111,20 @@ class Channel extends PureComponent {
|
|||
EventEmitter.off('leave_team', this.handleLeaveTeam);
|
||||
this.networkListener.removeEventListener();
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
AppState.removeEventListener('change', this.handleAppStateChange);
|
||||
}
|
||||
AppState.removeEventListener('change', this.handleAppStateChange);
|
||||
|
||||
closeWebSocket();
|
||||
stopPeriodicStatusUpdates();
|
||||
}
|
||||
|
||||
attachPostTextbox = (ref) => {
|
||||
attachPostTextBox = (ref) => {
|
||||
this.postTextbox = ref;
|
||||
};
|
||||
|
||||
blurPostTextBox = () => {
|
||||
this.postTextbox.getWrappedInstance().blur();
|
||||
if (this.postTextbox && this.postTextbox.getWrappedInstance()) {
|
||||
this.postTextbox.getWrappedInstance().blur();
|
||||
}
|
||||
};
|
||||
|
||||
channelDrawerRef = (ref) => {
|
||||
|
|
@ -129,7 +140,8 @@ class Channel extends PureComponent {
|
|||
};
|
||||
|
||||
goToChannelInfo = preventDoubleTap(() => {
|
||||
const {intl, navigator, theme} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {navigator, theme} = this.props;
|
||||
const options = {
|
||||
screen: 'ChannelInfo',
|
||||
title: intl.formatMessage({id: 'mobile.routes.channelInfo', defaultMessage: 'Info'}),
|
||||
|
|
@ -150,7 +162,7 @@ class Channel extends PureComponent {
|
|||
}
|
||||
});
|
||||
|
||||
handleAppStateChange = async (appState) => {
|
||||
handleWebSocket = (open) => {
|
||||
const {actions} = this.props;
|
||||
const {
|
||||
closeWebSocket,
|
||||
|
|
@ -158,9 +170,8 @@ class Channel extends PureComponent {
|
|||
startPeriodicStatusUpdates,
|
||||
stopPeriodicStatusUpdates,
|
||||
} = actions;
|
||||
const isActive = appState === 'active';
|
||||
|
||||
if (isActive) {
|
||||
if (open) {
|
||||
initWebSocket(Platform.OS);
|
||||
startPeriodicStatusUpdates();
|
||||
} else {
|
||||
|
|
@ -169,23 +180,14 @@ class Channel extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleConnectionChange = (isConnected) => {
|
||||
const {actions} = this.props;
|
||||
const {
|
||||
closeWebSocket,
|
||||
connection,
|
||||
initWebSocket,
|
||||
startPeriodicStatusUpdates,
|
||||
stopPeriodicStatusUpdates,
|
||||
} = actions;
|
||||
handleAppStateChange = async (appState) => {
|
||||
this.handleWebSocket(appState === 'active');
|
||||
};
|
||||
|
||||
if (isConnected) {
|
||||
initWebSocket(Platform.OS);
|
||||
startPeriodicStatusUpdates();
|
||||
} else {
|
||||
closeWebSocket(true);
|
||||
stopPeriodicStatusUpdates();
|
||||
}
|
||||
handleConnectionChange = (isConnected) => {
|
||||
const {connection} = this.props.actions;
|
||||
|
||||
this.handleWebSocket(isConnected);
|
||||
connection(isConnected);
|
||||
};
|
||||
|
||||
|
|
@ -225,10 +227,10 @@ class Channel extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {intl} = this.context;
|
||||
const {
|
||||
channelsRequestFailed,
|
||||
currentChannelId,
|
||||
intl,
|
||||
navigator,
|
||||
theme,
|
||||
} = this.props;
|
||||
|
|
@ -237,6 +239,7 @@ class Channel extends PureComponent {
|
|||
|
||||
if (!currentChannelId) {
|
||||
if (channelsRequestFailed) {
|
||||
const PostListRetry = require('app/components/post_list_retry').default;
|
||||
return (
|
||||
<PostListRetry
|
||||
retry={this.retryLoadChannels}
|
||||
|
|
@ -244,9 +247,11 @@ class Channel extends PureComponent {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const Loading = require('app/components/channel_loader').default;
|
||||
return (
|
||||
<View style={style.loading}>
|
||||
<Loading/>
|
||||
<Loading channelIsLoading={true}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
@ -277,10 +282,9 @@ class Channel extends PureComponent {
|
|||
<ChannelPostList navigator={navigator}/>
|
||||
</View>
|
||||
<PostTextbox
|
||||
ref={this.attachPostTextbox}
|
||||
ref={this.attachPostTextBox}
|
||||
navigator={navigator}
|
||||
/>
|
||||
<ChannelLoader theme={theme}/>
|
||||
</KeyboardLayout>
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener navigator={navigator}/>}
|
||||
</SafeAreaView>
|
||||
|
|
@ -301,5 +305,3 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default injectIntl(Channel);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
|
|
@ -13,13 +13,14 @@ import {
|
|||
import {debounce} from 'mattermost-redux/actions/helpers';
|
||||
|
||||
import AnnouncementBanner from 'app/components/announcement_banner';
|
||||
import ChannelIntro from 'app/components/channel_intro';
|
||||
import LoadMorePosts from 'app/components/load_more_posts';
|
||||
import PostList from 'app/components/post_list';
|
||||
import PostListRetry from 'app/components/post_list_retry';
|
||||
import RetryBarIndicator from 'app/components/retry_bar_indicator';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
||||
let ChannelIntro = null;
|
||||
let LoadMorePosts = null;
|
||||
|
||||
export default class ChannelPostList extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -136,6 +137,10 @@ export default class ChannelPostList extends PureComponent {
|
|||
}
|
||||
|
||||
if (this.props.loadMorePostsVisible) {
|
||||
if (!LoadMorePosts) {
|
||||
LoadMorePosts = require('app/components/load_more_posts').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<LoadMorePosts
|
||||
channelId={this.props.channelId}
|
||||
|
|
@ -145,6 +150,10 @@ export default class ChannelPostList extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
if (!ChannelIntro) {
|
||||
ChannelIntro = require('app/components/channel_intro').default;
|
||||
}
|
||||
|
||||
return (
|
||||
<ChannelIntro
|
||||
channelId={this.props.channelId}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
/* eslint-disable global-require*/
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import Channel from 'app/screens/channel';
|
||||
import Entry from 'app/screens/entry';
|
||||
import SelectServer from 'app/screens/select_server';
|
||||
import IntlWrapper from 'app/components/root';
|
||||
|
||||
function wrapWithContextProvider(Comp, excludeEvents = true) {
|
||||
|
|
@ -21,49 +24,49 @@ function wrapWithContextProvider(Comp, excludeEvents = true) {
|
|||
}
|
||||
|
||||
export function registerScreens(store, Provider) {
|
||||
Navigation.registerComponent('About', () => wrapWithContextProvider(require('app/screens/about').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('AddReaction', () => wrapWithContextProvider(require('app/screens/add_reaction').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('AdvancedSettings', () => wrapWithContextProvider(require('app/screens/settings/advanced_settings').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Channel', () => wrapWithContextProvider(require('app/screens/channel').default, false), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ChannelAddMembers', () => wrapWithContextProvider(require('app/screens/channel_add_members').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ChannelInfo', () => wrapWithContextProvider(require('app/screens/channel_info').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ChannelMembers', () => wrapWithContextProvider(require('app/screens/channel_members').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ChannelPeek', () => wrapWithContextProvider(require('app/screens/channel_peek').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ClientUpgrade', () => wrapWithContextProvider(require('app/screens/client_upgrade').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ClockDisplay', () => wrapWithContextProvider(require('app/screens/clock_display').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Code', () => wrapWithContextProvider(require('app/screens/code').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('CreateChannel', () => wrapWithContextProvider(require('app/screens/create_channel').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('DisplaySettings', () => wrapWithContextProvider(require('app/screens/settings/display_settings').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('EditChannel', () => wrapWithContextProvider(require('app/screens/edit_channel').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('EditPost', () => wrapWithContextProvider(require('app/screens/edit_post').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('EditProfile', () => wrapWithContextProvider(require('app/screens/edit_profile').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Entry', () => wrapWithContextProvider(require('app/screens/entry').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('FlaggedPosts', () => wrapWithContextProvider(require('app/screens/flagged_posts').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('ImagePreview', () => wrapWithContextProvider(require('app/screens/image_preview').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('TextPreview', () => wrapWithContextProvider(require('app/screens/text_preview').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Login', () => wrapWithContextProvider(require('app/screens/login').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('LoginOptions', () => wrapWithContextProvider(require('app/screens/login_options').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('LongPost', () => wrapWithContextProvider(require('app/screens/long_post').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('MFA', () => wrapWithContextProvider(require('app/screens/mfa').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('MoreChannels', () => wrapWithContextProvider(require('app/screens/more_channels').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('MoreDirectMessages', () => wrapWithContextProvider(require('app/screens/more_dms').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Notification', () => wrapWithContextProvider(require('app/screens/notification').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('NotificationSettings', () => wrapWithContextProvider(require('app/screens/settings/notification_settings').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('NotificationSettingsEmail', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_email').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('NotificationSettingsMentions', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mentions').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('NotificationSettingsMentionsKeywords', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mentions_keywords').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('NotificationSettingsMobile', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mobile').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('OptionsModal', () => wrapWithContextProvider(require('app/screens/options_modal').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Permalink', () => wrapWithContextProvider(require('app/screens/permalink').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('RecentMentions', () => wrapWithContextProvider(require('app/screens/recent_mentions').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Root', () => require('app/screens/root').default, store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Search', () => wrapWithContextProvider(require('app/screens/search').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('SelectServer', () => wrapWithContextProvider(require('app/screens/select_server').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('SelectTeam', () => wrapWithContextProvider(require('app/screens/select_team').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Settings', () => wrapWithContextProvider(require('app/screens/settings/general').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('SSO', () => wrapWithContextProvider(require('app/screens/sso').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Table', () => wrapWithContextProvider(require('app/screens/table').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('TableImage', () => wrapWithContextProvider(require('app/screens/table_image').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('Thread', () => wrapWithContextProvider(require('app/screens/thread').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('UserProfile', () => wrapWithContextProvider(require('app/screens/user_profile').default), store, Provider); //eslint-disable-line global-require
|
||||
Navigation.registerComponent('About', () => wrapWithContextProvider(require('app/screens/about').default), store, Provider);
|
||||
Navigation.registerComponent('AddReaction', () => wrapWithContextProvider(require('app/screens/add_reaction').default), store, Provider);
|
||||
Navigation.registerComponent('AdvancedSettings', () => wrapWithContextProvider(require('app/screens/settings/advanced_settings').default), store, Provider);
|
||||
Navigation.registerComponent('Channel', () => wrapWithContextProvider(Channel, false), store, Provider);
|
||||
Navigation.registerComponent('ChannelAddMembers', () => wrapWithContextProvider(require('app/screens/channel_add_members').default), store, Provider);
|
||||
Navigation.registerComponent('ChannelInfo', () => wrapWithContextProvider(require('app/screens/channel_info').default), store, Provider);
|
||||
Navigation.registerComponent('ChannelMembers', () => wrapWithContextProvider(require('app/screens/channel_members').default), store, Provider);
|
||||
Navigation.registerComponent('ChannelPeek', () => wrapWithContextProvider(require('app/screens/channel_peek').default), store, Provider);
|
||||
Navigation.registerComponent('ClientUpgrade', () => wrapWithContextProvider(require('app/screens/client_upgrade').default), store, Provider);
|
||||
Navigation.registerComponent('ClockDisplay', () => wrapWithContextProvider(require('app/screens/clock_display').default), store, Provider);
|
||||
Navigation.registerComponent('Code', () => wrapWithContextProvider(require('app/screens/code').default), store, Provider);
|
||||
Navigation.registerComponent('CreateChannel', () => wrapWithContextProvider(require('app/screens/create_channel').default), store, Provider);
|
||||
Navigation.registerComponent('DisplaySettings', () => wrapWithContextProvider(require('app/screens/settings/display_settings').default), store, Provider);
|
||||
Navigation.registerComponent('EditChannel', () => wrapWithContextProvider(require('app/screens/edit_channel').default), store, Provider);
|
||||
Navigation.registerComponent('EditPost', () => wrapWithContextProvider(require('app/screens/edit_post').default), store, Provider);
|
||||
Navigation.registerComponent('EditProfile', () => wrapWithContextProvider(require('app/screens/edit_profile').default), store, Provider);
|
||||
Navigation.registerComponent('Entry', () => wrapWithContextProvider(Entry), store, Provider);
|
||||
Navigation.registerComponent('FlaggedPosts', () => wrapWithContextProvider(require('app/screens/flagged_posts').default), store, Provider);
|
||||
Navigation.registerComponent('ImagePreview', () => wrapWithContextProvider(require('app/screens/image_preview').default), store, Provider);
|
||||
Navigation.registerComponent('Login', () => wrapWithContextProvider(require('app/screens/login').default), store, Provider);
|
||||
Navigation.registerComponent('LoginOptions', () => wrapWithContextProvider(require('app/screens/login_options').default), store, Provider);
|
||||
Navigation.registerComponent('LongPost', () => wrapWithContextProvider(require('app/screens/long_post').default), store, Provider);
|
||||
Navigation.registerComponent('MFA', () => wrapWithContextProvider(require('app/screens/mfa').default), store, Provider);
|
||||
Navigation.registerComponent('MoreChannels', () => wrapWithContextProvider(require('app/screens/more_channels').default), store, Provider);
|
||||
Navigation.registerComponent('MoreDirectMessages', () => wrapWithContextProvider(require('app/screens/more_dms').default), store, Provider);
|
||||
Navigation.registerComponent('Notification', () => wrapWithContextProvider(require('app/screens/notification').default), store, Provider);
|
||||
Navigation.registerComponent('NotificationSettings', () => wrapWithContextProvider(require('app/screens/settings/notification_settings').default), store, Provider);
|
||||
Navigation.registerComponent('NotificationSettingsEmail', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_email').default), store, Provider);
|
||||
Navigation.registerComponent('NotificationSettingsMentions', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mentions').default), store, Provider);
|
||||
Navigation.registerComponent('NotificationSettingsMentionsKeywords', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mentions_keywords').default), store, Provider);
|
||||
Navigation.registerComponent('NotificationSettingsMobile', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mobile').default), store, Provider);
|
||||
Navigation.registerComponent('OptionsModal', () => wrapWithContextProvider(require('app/screens/options_modal').default), store, Provider);
|
||||
Navigation.registerComponent('Permalink', () => wrapWithContextProvider(require('app/screens/permalink').default), store, Provider);
|
||||
Navigation.registerComponent('RecentMentions', () => wrapWithContextProvider(require('app/screens/recent_mentions').default), store, Provider);
|
||||
Navigation.registerComponent('Root', () => require('app/screens/root').default, store, Provider);
|
||||
Navigation.registerComponent('Search', () => wrapWithContextProvider(require('app/screens/search').default), store, Provider);
|
||||
Navigation.registerComponent('SelectServer', () => wrapWithContextProvider(SelectServer), store, Provider);
|
||||
Navigation.registerComponent('SelectTeam', () => wrapWithContextProvider(require('app/screens/select_team').default), store, Provider);
|
||||
Navigation.registerComponent('Settings', () => wrapWithContextProvider(require('app/screens/settings/general').default), store, Provider);
|
||||
Navigation.registerComponent('SSO', () => wrapWithContextProvider(require('app/screens/sso').default), store, Provider);
|
||||
Navigation.registerComponent('Table', () => wrapWithContextProvider(require('app/screens/table').default), store, Provider);
|
||||
Navigation.registerComponent('TableImage', () => wrapWithContextProvider(require('app/screens/table_image').default), store, Provider);
|
||||
Navigation.registerComponent('TextPreview', () => wrapWithContextProvider(require('app/screens/text_preview').default), store, Provider);
|
||||
Navigation.registerComponent('Thread', () => wrapWithContextProvider(require('app/screens/thread').default), store, Provider);
|
||||
Navigation.registerComponent('UserProfile', () => wrapWithContextProvider(require('app/screens/user_profile').default), store, Provider);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// 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 {
|
||||
ActivityIndicator,
|
||||
Dimensions,
|
||||
|
|
@ -27,13 +27,10 @@ import {GlobalStyles} from 'app/styles';
|
|||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
||||
import logo from 'assets/images/logo.png';
|
||||
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
class Login extends PureComponent {
|
||||
export default class Login extends PureComponent {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object,
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -52,6 +49,10 @@ class Login extends PureComponent {
|
|||
loginRequest: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ class Login extends PureComponent {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.loginRequest.status === RequestStatus.STARTED && nextProps.loginRequest.status === RequestStatus.SUCCESS) {
|
||||
this.props.actions.handleSuccessfulLogin().then(this.props.actions.getSession).then(this.goToLoadTeam);
|
||||
this.props.actions.handleSuccessfulLogin().then(this.props.actions.getSession).then(this.goToChannel);
|
||||
} else if (this.props.loginRequest.status !== nextProps.loginRequest.status && nextProps.loginRequest.status !== RequestStatus.STARTED) {
|
||||
this.setState({isLoading: false});
|
||||
}
|
||||
|
|
@ -76,8 +77,9 @@ class Login extends PureComponent {
|
|||
Dimensions.removeEventListener('change', this.orientationDidChange);
|
||||
}
|
||||
|
||||
goToLoadTeam = (expiresAt) => {
|
||||
const {intl, navigator} = this.props;
|
||||
goToChannel = (expiresAt) => {
|
||||
const {intl} = this.context;
|
||||
const {navigator} = this.props;
|
||||
tracker.initialLoad = Date.now();
|
||||
|
||||
if (expiresAt) {
|
||||
|
|
@ -110,7 +112,8 @@ class Login extends PureComponent {
|
|||
};
|
||||
|
||||
goToMfa = () => {
|
||||
const {intl, navigator, theme} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {navigator, theme} = this.props;
|
||||
|
||||
this.setState({isLoading: false});
|
||||
|
||||
|
|
@ -152,13 +155,14 @@ class Login extends PureComponent {
|
|||
}
|
||||
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
error: {
|
||||
intl: {
|
||||
id: msgId,
|
||||
defaultMessage: '',
|
||||
values: {
|
||||
ldapUsername: this.props.config.LdapLoginFieldName ||
|
||||
this.props.intl.formatMessage({
|
||||
this.context.intl.formatMessage({
|
||||
id: 'login.ldapUsernameLower',
|
||||
defaultMessage: 'AD/LDAP username',
|
||||
}),
|
||||
|
|
@ -171,6 +175,7 @@ class Login extends PureComponent {
|
|||
|
||||
if (!this.props.password) {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
error: {
|
||||
intl: {
|
||||
id: 'login.noPassword',
|
||||
|
|
@ -202,7 +207,7 @@ class Login extends PureComponent {
|
|||
};
|
||||
|
||||
createLoginPlaceholder() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const {formatMessage} = this.context.intl;
|
||||
const license = this.props.license;
|
||||
const config = this.props.config;
|
||||
|
||||
|
|
@ -346,7 +351,7 @@ class Login extends PureComponent {
|
|||
enableOnAndroid={true}
|
||||
>
|
||||
<Image
|
||||
source={logo}
|
||||
source={require('assets/images/logo.png')}
|
||||
/>
|
||||
<View>
|
||||
<Text style={GlobalStyles.header}>
|
||||
|
|
@ -379,7 +384,7 @@ class Login extends PureComponent {
|
|||
value={this.props.password}
|
||||
onChangeText={this.props.actions.handlePasswordChanged}
|
||||
style={GlobalStyles.inputBox}
|
||||
placeholder={this.props.intl.formatMessage({id: 'login.password', defaultMessage: 'Password'})}
|
||||
placeholder={this.context.intl.formatMessage({id: 'login.password', defaultMessage: 'Password'})}
|
||||
secureTextEntry={true}
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
|
|
@ -409,5 +414,3 @@ const style = StyleSheet.create({
|
|||
paddingVertical: 50,
|
||||
},
|
||||
});
|
||||
|
||||
export default injectIntl(Login);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
|
|
@ -14,6 +14,8 @@ import {
|
|||
} from 'react-native';
|
||||
import Button from 'react-native-button';
|
||||
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
import ErrorText from 'app/components/error_text';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
|
|
@ -21,10 +23,6 @@ import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_lo
|
|||
import {GlobalStyles} from 'app/styles';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
|
||||
import logo from 'assets/images/logo.png';
|
||||
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
export default class Mfa extends PureComponent {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
|
|
@ -138,7 +136,7 @@ export default class Mfa extends PureComponent {
|
|||
<TouchableWithoutFeedback onPress={this.blur}>
|
||||
<View style={[GlobalStyles.container, GlobalStyles.signupContainer]}>
|
||||
<Image
|
||||
source={logo}
|
||||
source={require('assets/images/logo.png')}
|
||||
/>
|
||||
<View>
|
||||
<FormattedText
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// 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 {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
|
|
@ -13,27 +13,25 @@ import {
|
|||
StatusBar,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Button from 'react-native-button';
|
||||
import urlParse from 'url-parse';
|
||||
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
|
||||
import Config from 'assets/config';
|
||||
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 {preventDoubleTap} from 'app/utils/tap';
|
||||
import {isValidUrl, stripTrailingSlashes} from 'app/utils/url';
|
||||
import {UpgradeTypes} from 'app/constants/view';
|
||||
import {GlobalStyles} from 'app/styles';
|
||||
import checkUpgradeType from 'app/utils/client_upgrade';
|
||||
import {isValidUrl, stripTrailingSlashes} from 'app/utils/url';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
|
||||
import logo from 'assets/images/logo.png';
|
||||
import LocalConfig from 'assets/config';
|
||||
|
||||
class SelectServer extends PureComponent {
|
||||
export default class SelectServer extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
getPing: PropTypes.func.isRequired,
|
||||
|
|
@ -47,7 +45,6 @@ class SelectServer extends PureComponent {
|
|||
config: PropTypes.object,
|
||||
currentVersion: PropTypes.string,
|
||||
hasConfigAndLicense: PropTypes.bool.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
latestVersion: PropTypes.string,
|
||||
license: PropTypes.object,
|
||||
minVersion: PropTypes.string,
|
||||
|
|
@ -56,6 +53,10 @@ class SelectServer extends PureComponent {
|
|||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ class SelectServer extends PureComponent {
|
|||
|
||||
componentWillUpdate(nextProps, nextState) {
|
||||
if (nextState.connected && nextProps.hasConfigAndLicense && !(this.state.connected && this.props.hasConfigAndLicense)) {
|
||||
if (Config.EnableMobileClientUpgrade) {
|
||||
if (LocalConfig.EnableMobileClientUpgrade) {
|
||||
this.props.actions.setLastUpgradeCheck();
|
||||
const {currentVersion, minVersion, latestVersion} = nextProps;
|
||||
const upgradeType = checkUpgradeType(currentVersion, minVersion, latestVersion);
|
||||
|
|
@ -116,7 +117,8 @@ class SelectServer extends PureComponent {
|
|||
};
|
||||
|
||||
handleShowClientUpgrade = (upgradeType) => {
|
||||
const {intl, theme} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {theme} = this.props;
|
||||
|
||||
this.props.navigator.push({
|
||||
screen: 'ClientUpgrade',
|
||||
|
|
@ -124,7 +126,7 @@ class SelectServer extends PureComponent {
|
|||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarHidden: false,
|
||||
disabledBackGesture: Config.AutoSelectServerUrl,
|
||||
disabledBackGesture: LocalConfig.AutoSelectServerUrl,
|
||||
statusBarHidden: true,
|
||||
statusBarHideWithNavBar: true,
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
|
|
@ -132,14 +134,15 @@ class SelectServer extends PureComponent {
|
|||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
},
|
||||
passProps: {
|
||||
closeAction: () => this.handleLoginOptions(this.props),
|
||||
closeAction: this.handleLoginOptions,
|
||||
upgradeType,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
handleLoginOptions = (props) => {
|
||||
const {config, intl, license, theme} = props;
|
||||
handleLoginOptions = (props = this.props) => {
|
||||
const {intl} = this.context;
|
||||
const {config, license, theme} = props;
|
||||
const samlEnabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true';
|
||||
const gitlabEnabled = config.EnableSignUpWithGitLab === 'true';
|
||||
|
||||
|
|
@ -164,8 +167,8 @@ class SelectServer extends PureComponent {
|
|||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarHidden: Config.AutoSelectServerUrl,
|
||||
disabledBackGesture: Config.AutoSelectServerUrl,
|
||||
navBarHidden: LocalConfig.AutoSelectServerUrl,
|
||||
disabledBackGesture: LocalConfig.AutoSelectServerUrl,
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
|
|
@ -184,6 +187,7 @@ class SelectServer extends PureComponent {
|
|||
};
|
||||
|
||||
onClick = preventDoubleTap(async () => {
|
||||
const urlParse = require('url-parse');
|
||||
const preUrl = urlParse(this.state.url, true);
|
||||
const url = stripTrailingSlashes(preUrl.protocol + '//' + preUrl.host);
|
||||
|
||||
|
|
@ -272,11 +276,12 @@ class SelectServer extends PureComponent {
|
|||
|
||||
blur = () => {
|
||||
if (this.textInput) {
|
||||
this.textInput.refs.wrappedInstance.blur();
|
||||
this.textInput.blur();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {allowOtherServers} = this.props;
|
||||
const {
|
||||
connected,
|
||||
|
|
@ -331,7 +336,7 @@ class SelectServer extends PureComponent {
|
|||
<TouchableWithoutFeedback onPress={this.blur}>
|
||||
<View style={[GlobalStyles.container, GlobalStyles.signupContainer]}>
|
||||
<Image
|
||||
source={logo}
|
||||
source={require('assets/images/logo.png')}
|
||||
/>
|
||||
|
||||
<View>
|
||||
|
|
@ -341,7 +346,7 @@ class SelectServer extends PureComponent {
|
|||
defaultMessage='Enter Server URL'
|
||||
/>
|
||||
</View>
|
||||
<TextInputWithLocalizedPlaceholder
|
||||
<TextInput
|
||||
ref={this.inputRef}
|
||||
value={url}
|
||||
editable={!inputDisabled}
|
||||
|
|
@ -351,7 +356,10 @@ class SelectServer extends PureComponent {
|
|||
autoCapitalize='none'
|
||||
autoCorrect={false}
|
||||
keyboardType='url'
|
||||
placeholder={{id: 'mobile.components.select_server_view.siteUrlPlaceholder', defaultMessage: 'https://mattermost.example.com'}}
|
||||
placeholder={formatMessage({
|
||||
id: 'mobile.components.select_server_view.siteUrlPlaceholder',
|
||||
defaultMessage: 'https://mattermost.example.com',
|
||||
})}
|
||||
returnKeyType='go'
|
||||
underlineColorAndroid='transparent'
|
||||
disableFullscreenUI={true}
|
||||
|
|
@ -387,5 +395,3 @@ const style = StyleSheet.create({
|
|||
marginRight: 5,
|
||||
},
|
||||
});
|
||||
|
||||
export default injectIntl(SelectServer);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
|
|
@ -8,16 +8,12 @@ import assert from 'assert';
|
|||
import {ViewTypes} from 'app/constants';
|
||||
import {messageRetention} from 'app/store/middleware';
|
||||
|
||||
jest.mock('react-native-fetch-blob', () => {
|
||||
return {
|
||||
DocumentDir: () => null,
|
||||
polyfill: () => null,
|
||||
fs: {
|
||||
dirs: {
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
jest.mock('react-native-fetch-blob/fs', () => ({
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('react-native-device-info', () => {
|
||||
return {
|
||||
|
|
|
|||
31
index.js
31
index.js
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import 'react-native/Libraries/Core/InitializeCore';
|
||||
import {AppRegistry, Platform} from 'react-native';
|
||||
|
||||
import 'app/mattermost';
|
||||
|
|
@ -9,3 +10,33 @@ import ShareExtension from 'share_extension/android';
|
|||
if (Platform.OS === 'android') {
|
||||
AppRegistry.registerComponent('MattermostShare', () => ShareExtension);
|
||||
}
|
||||
|
||||
// Uncomment the snippet below if you want to update the modules
|
||||
// defined in packager/modulePaths.js so they are included in the main bundle.
|
||||
|
||||
/*
|
||||
/!* eslint-disable no-console *!/
|
||||
/!* eslint-disable no-undef *!/
|
||||
if (__DEV__) {
|
||||
const modules = require.getModules();
|
||||
const moduleIds = Object.keys(modules);
|
||||
const loadedModuleNames = moduleIds.
|
||||
filter((moduleId) => modules[moduleId].isInitialized).
|
||||
map((moduleId) => modules[moduleId].verboseName);
|
||||
|
||||
const waitingModuleNames = moduleIds.
|
||||
filter((moduleId) => !modules[moduleId].isInitialized).
|
||||
map((moduleId) => modules[moduleId].verboseName);
|
||||
|
||||
// make sure that the modules you expect to be waiting are actually waiting
|
||||
console.log(
|
||||
'loaded:',
|
||||
loadedModuleNames,
|
||||
'waiting:',
|
||||
waitingModuleNames
|
||||
);
|
||||
|
||||
// grab this text blob, and put it in a file named packager/moduleNames.js
|
||||
console.log(`module.exports = ${JSON.stringify(loadedModuleNames.sort())};`);
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
"underscore": "1.9.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node ./node_modules/react-native/local-cli/cli.js start --config ../../../../packager/config.js",
|
||||
"check": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet .",
|
||||
"fix": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet . --fix",
|
||||
"postinstall": "make post-install",
|
||||
|
|
|
|||
46
packager/config.js
Normal file
46
packager/config.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
/* eslint-disable no-console */
|
||||
const modulePaths = require('./modulePaths');
|
||||
const resolve = require('path').resolve;
|
||||
const fs = require('fs');
|
||||
|
||||
const platformRegex = /\.(android\.js|ios\.js)/g;
|
||||
const modulesRegex = /\/(node_modules)/;
|
||||
|
||||
// This script will let the react native packager what modules to include
|
||||
// in the main bundle and what modules to blacklist from the inline requires
|
||||
// this modules are taken from the modulePaths.js file
|
||||
|
||||
const config = {
|
||||
getTransformOptions: (entryFile, {platform}) => {
|
||||
console.log('BUILDING MODULES FOR', platform);
|
||||
const moduleMap = {};
|
||||
modulePaths.forEach((path) => {
|
||||
let realPath = path;
|
||||
if (platform && platformRegex.test(realPath)) {
|
||||
realPath = path.replace(platformRegex, `.${platform}.js`);
|
||||
}
|
||||
|
||||
let fsFile = realPath;
|
||||
if (path.match(modulesRegex).length > 1) {
|
||||
fsFile = path.replace(modulesRegex, '');
|
||||
}
|
||||
|
||||
if (fs.existsSync(fsFile)) {
|
||||
moduleMap[resolve(realPath)] = true;
|
||||
}
|
||||
});
|
||||
return {
|
||||
preloadedModules: moduleMap,
|
||||
transform: {
|
||||
inlineRequires: {
|
||||
blacklist: moduleMap,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
46
packager/generateModulePaths.js
Normal file
46
packager/generateModulePaths.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
/* eslint-disable no-console */
|
||||
const execSync = require('child_process').execSync;
|
||||
const fs = require('fs');
|
||||
const moduleNames = require('./moduleNames');
|
||||
|
||||
const pjson = require('../package.json');
|
||||
const localPrefix = `${pjson.name}/`;
|
||||
|
||||
// Transforming to Module Paths
|
||||
// This script will convert the module names found in moduleNames.js
|
||||
// to the absolute module path that we need.
|
||||
const modulePaths = moduleNames.map((moduleName) => {
|
||||
if (moduleName.startsWith(localPrefix)) {
|
||||
return `./${moduleName.substring(localPrefix.length)}`;
|
||||
}
|
||||
if (moduleName.endsWith('.js')) {
|
||||
return `./node_modules/${moduleName}`;
|
||||
}
|
||||
try {
|
||||
const result = execSync(
|
||||
`grep "@providesModule ${moduleName}" $(find . -name ${moduleName}\\\\.js) -l`
|
||||
).toString().trim().split('\n')[0];
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const paths = modulePaths.filter((path) => path != null).map((path) => `'${path}'`).join(',\n');
|
||||
|
||||
const fileData = `module.exports = [${paths}];`;
|
||||
|
||||
fs.writeFile('./packager/modulePaths.js', fileData, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
console.log('Done');
|
||||
});
|
||||
1
packager/moduleNames.js
Normal file
1
packager/moduleNames.js
Normal file
File diff suppressed because one or more lines are too long
1050
packager/modulePaths.js
Normal file
1050
packager/modulePaths.js
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue