Merge pull request #2076 from mattermost/release-1.12
Merge Release 1.12 into master
This commit is contained in:
commit
74a45fd931
39 changed files with 2008 additions and 282 deletions
|
|
@ -113,7 +113,7 @@ android {
|
|||
applicationId "com.mattermost.rnbeta"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
versionCode 135
|
||||
versionCode 136
|
||||
versionName "1.12.0"
|
||||
multiDexEnabled = true
|
||||
ndk {
|
||||
|
|
|
|||
|
|
@ -14,13 +14,6 @@ import {
|
|||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import ImageCacheManager from 'app/utils/image_cache_manager';
|
||||
|
||||
const scaleEmojiBasedOnDevice = (size) => {
|
||||
if (Platform.OS === 'ios') {
|
||||
return size * 1.1; // slightly larger emojis look better on ios
|
||||
}
|
||||
return size * PixelRatio.get();
|
||||
};
|
||||
|
||||
export default class Emoji extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
||||
|
|
@ -60,30 +53,28 @@ export default class Emoji extends React.PureComponent {
|
|||
|
||||
this.state = {
|
||||
imageUrl: null,
|
||||
originalWidth: 0,
|
||||
originalHeight: 0,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {displayTextOnly, imageUrl} = this.props;
|
||||
this.mounted = true;
|
||||
if (!this.props.displayTextOnly && this.props.imageUrl) {
|
||||
ImageCacheManager.cache(this.props.imageUrl, this.props.imageUrl, this.updateImageHeight);
|
||||
if (!displayTextOnly && imageUrl) {
|
||||
ImageCacheManager.cache(imageUrl, imageUrl, this.setImageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.emojiName !== this.props.emojiName) {
|
||||
const {displayTextOnly, emojiName, imageUrl} = nextProps;
|
||||
if (emojiName !== this.props.emojiName) {
|
||||
this.setState({
|
||||
imageUrl: null,
|
||||
originalWidth: 0,
|
||||
originalHeight: 0,
|
||||
});
|
||||
}
|
||||
|
||||
if (!nextProps.displayTextOnly && nextProps.imageUrl &&
|
||||
nextProps.imageUrl !== this.props.imageUrl) {
|
||||
ImageCacheManager.cache(nextProps.imageUrl, nextProps.imageUrl, this.updateImageHeight);
|
||||
if (!displayTextOnly && imageUrl &&
|
||||
imageUrl !== this.props.imageUrl) {
|
||||
ImageCacheManager.cache(imageUrl, imageUrl, this.setImageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,21 +82,15 @@ export default class Emoji extends React.PureComponent {
|
|||
this.mounted = false;
|
||||
}
|
||||
|
||||
updateImageHeight = (imageUrl) => {
|
||||
setImageUrl = (imageUrl) => {
|
||||
let prefix = '';
|
||||
if (Platform.OS === 'android') {
|
||||
prefix = 'file://';
|
||||
}
|
||||
|
||||
const uri = `${prefix}${imageUrl}`;
|
||||
Image.getSize(uri, (originalWidth, originalHeight) => {
|
||||
if (this.mounted) {
|
||||
this.setState({
|
||||
imageUrl: uri,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
imageUrl: uri,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -122,26 +107,15 @@ export default class Emoji extends React.PureComponent {
|
|||
if (!size && textStyle) {
|
||||
const flatten = StyleSheet.flatten(textStyle);
|
||||
fontSize = flatten.fontSize;
|
||||
size = scaleEmojiBasedOnDevice(fontSize);
|
||||
size = fontSize * (Platform.OS === 'android' ? PixelRatio.get() : 1);
|
||||
}
|
||||
|
||||
if (displayTextOnly) {
|
||||
return <Text style={textStyle}>{literal}</Text>;
|
||||
}
|
||||
|
||||
let width = size;
|
||||
let height = size;
|
||||
let {originalHeight, originalWidth} = this.state;
|
||||
originalHeight = scaleEmojiBasedOnDevice(originalHeight);
|
||||
originalWidth = scaleEmojiBasedOnDevice(originalWidth);
|
||||
if (originalHeight && originalWidth) {
|
||||
if (originalWidth > originalHeight) {
|
||||
height = (size * originalHeight) / originalWidth;
|
||||
} else if (originalWidth < originalHeight) {
|
||||
// This may cause text to reflow, but its impossible to add a horizontal margin
|
||||
width = (size * originalWidth) / originalHeight;
|
||||
}
|
||||
}
|
||||
const width = size;
|
||||
const height = size;
|
||||
|
||||
let marginTop = 0;
|
||||
if (textStyle) {
|
||||
|
|
|
|||
|
|
@ -407,6 +407,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
renderItem={this.flatListRenderItem}
|
||||
pageSize={10}
|
||||
initialListSize={10}
|
||||
removeClippedSubviews={true}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
|
@ -558,6 +559,7 @@ const getStyleSheetFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
borderLeftColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
borderRightWidth: 1,
|
||||
borderRightColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
overflow: 'hidden',
|
||||
},
|
||||
listView: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default class EmojiPickerRow extends Component {
|
|||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {emojiGutter, items} = this.props;
|
||||
|
|
@ -86,6 +86,7 @@ const styles = StyleSheet.create({
|
|||
emoji: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
emojiLeft: {
|
||||
marginLeft: 0,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,19 @@ export default class FailedNetworkAction extends PureComponent {
|
|||
static propTypes = {
|
||||
onRetry: PropTypes.func,
|
||||
theme: PropTypes.object.isRequired,
|
||||
errorTitle: PropTypes.object,
|
||||
errorDescription: PropTypes.object,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
errorTitle: {
|
||||
id: 'mobile.failed_network_action.title',
|
||||
defaultMessage: 'No internet connection',
|
||||
},
|
||||
errorDescription: {
|
||||
id: 'mobile.failed_network_action.description',
|
||||
defaultMessage: 'There seems to be a problem with your internet connection. Make sure you have an active connection and try again.',
|
||||
},
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
@ -28,13 +41,13 @@ export default class FailedNetworkAction extends PureComponent {
|
|||
width={76}
|
||||
/>
|
||||
<FormattedText
|
||||
id='mobile.failed_network_action.title'
|
||||
defaultMessage='No internet connection'
|
||||
id={this.props.errorTitle.id}
|
||||
defaultMessage={this.props.errorTitle.defaultMessage}
|
||||
style={style.title}
|
||||
/>
|
||||
<FormattedText
|
||||
id='mobile.failed_network_action.description'
|
||||
defaultMessage='There seems to be a problem with your internet connection. Make sure you have an active connection and try again.'
|
||||
id={this.props.errorDescription.id}
|
||||
defaultMessage={this.props.errorDescription.message}
|
||||
style={style.description}
|
||||
/>
|
||||
{onRetry &&
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ import {
|
|||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import ProgressiveImage from 'app/components/progressive_image';
|
||||
import ShowMoreButton from 'app/components/show_more_button';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import ImageCacheManager from 'app/utils/image_cache_manager';
|
||||
import {previewImageAtIndex, calculateDimensions} from 'app/utils/images';
|
||||
|
|
@ -103,10 +104,10 @@ export default class MessageAttachment extends PureComponent {
|
|||
const {height} = event.nativeEvent.layout;
|
||||
const {height: deviceHeight} = Dimensions.get('window');
|
||||
|
||||
if (height >= (deviceHeight * 1.2)) {
|
||||
if (height >= (deviceHeight * 0.6)) {
|
||||
this.setState({
|
||||
isLongText: true,
|
||||
maxHeight: (deviceHeight * 0.6),
|
||||
maxHeight: (deviceHeight * 0.4),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -385,23 +386,6 @@ export default class MessageAttachment extends PureComponent {
|
|||
|
||||
let text;
|
||||
if (attachment.text) {
|
||||
let moreLessLocale = {id: 'post_attachment.collapse', defaultMessage: 'Show less...'};
|
||||
if (collapsed) {
|
||||
moreLessLocale = {id: 'post_attachment.more', defaultMessage: 'Show more...'};
|
||||
}
|
||||
|
||||
let moreLess;
|
||||
if (isLongText) {
|
||||
moreLess = (
|
||||
<FormattedText
|
||||
id={moreLessLocale.id}
|
||||
defaultMessage={moreLessLocale.defaultMessage}
|
||||
onPress={this.toggleCollapseState}
|
||||
style={style.moreLess}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
text = (
|
||||
<View
|
||||
onLayout={this.measurePost}
|
||||
|
|
@ -421,7 +405,12 @@ export default class MessageAttachment extends PureComponent {
|
|||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
</View>
|
||||
{moreLess}
|
||||
{isLongText &&
|
||||
<ShowMoreButton
|
||||
onPress={this.toggleCollapseState}
|
||||
showMore={collapsed}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
@ -523,11 +512,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
height: 45,
|
||||
width: 45,
|
||||
},
|
||||
moreLess: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 12,
|
||||
marginTop: 5,
|
||||
},
|
||||
headingContainer: {
|
||||
alignSelf: 'stretch',
|
||||
flexDirection: 'row',
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import RNBottomSheet from 'react-native-bottom-sheet';
|
|||
|
||||
export default class OptionsContext extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
getPostActions: PropTypes.func,
|
||||
cancelText: PropTypes.string,
|
||||
children: PropTypes.node.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
|
|
@ -16,13 +16,13 @@ export default class OptionsContext extends PureComponent {
|
|||
};
|
||||
|
||||
static defaultProps = {
|
||||
actions: [],
|
||||
getPostActions: () => [],
|
||||
cancelText: 'Cancel',
|
||||
};
|
||||
|
||||
show = (additionalAction) => {
|
||||
const {actions, cancelText} = this.props;
|
||||
const nextActions = [...actions];
|
||||
const {getPostActions, cancelText} = this.props;
|
||||
const nextActions = getPostActions();
|
||||
if (additionalAction && !additionalAction.nativeEvent && additionalAction.text) {
|
||||
const copyPostIndex = nextActions.findIndex((action) => action.copyPost);
|
||||
nextActions.splice(copyPostIndex + 1, 0, additionalAction);
|
||||
|
|
@ -45,11 +45,11 @@ export default class OptionsContext extends PureComponent {
|
|||
};
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
this.props.toggleSelected(false, this.props.actions.length > 0);
|
||||
this.props.toggleSelected(false, this.props.getPostActions().length > 0);
|
||||
};
|
||||
|
||||
handleShowUnderlay = () => {
|
||||
this.props.toggleSelected(true, this.props.actions.length > 0);
|
||||
this.props.toggleSelected(true, this.props.getPostActions().length > 0);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ import ToolTip from 'app/components/tooltip';
|
|||
|
||||
export default class OptionsContext extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
getPostActions: PropTypes.func,
|
||||
children: PropTypes.node.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
toggleSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
actions: [],
|
||||
getPostActions: () => [],
|
||||
additionalActions: [],
|
||||
};
|
||||
|
||||
|
|
@ -23,16 +23,10 @@ export default class OptionsContext extends PureComponent {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
actions: props.actions,
|
||||
actions: props.getPostActions(),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.actions !== nextProps.actions) {
|
||||
this.setState({actions: nextProps.actions});
|
||||
}
|
||||
}
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
if (!this.isShowing) {
|
||||
this.props.toggleSelected(false, false);
|
||||
|
|
@ -45,11 +39,11 @@ export default class OptionsContext extends PureComponent {
|
|||
|
||||
handleHide = () => {
|
||||
this.isShowing = false;
|
||||
this.props.toggleSelected(false, this.props.actions.length > 0);
|
||||
this.props.toggleSelected(false, this.props.getPostActions().length > 0);
|
||||
};
|
||||
|
||||
handleShow = () => {
|
||||
this.isShowing = this.props.actions.length > 0;
|
||||
this.isShowing = this.props.getPostActions().length > 0;
|
||||
this.props.toggleSelected(true, this.isShowing);
|
||||
};
|
||||
|
||||
|
|
@ -59,12 +53,12 @@ export default class OptionsContext extends PureComponent {
|
|||
}
|
||||
|
||||
this.setState({
|
||||
actions: this.props.actions,
|
||||
actions: this.props.getPostActions(),
|
||||
});
|
||||
};
|
||||
|
||||
show = (additionalAction) => {
|
||||
const nextActions = [...this.props.actions];
|
||||
const nextActions = this.props.getPostActions();
|
||||
if (additionalAction && additionalAction.text && !additionalAction.nativeEvent) {
|
||||
const copyPostIndex = nextActions.findIndex((action) => action.copyPost);
|
||||
nextActions.splice(copyPostIndex + 1, 0, additionalAction);
|
||||
|
|
@ -80,7 +74,7 @@ export default class OptionsContext extends PureComponent {
|
|||
};
|
||||
|
||||
handlePress = () => {
|
||||
this.props.toggleSelected(false, this.props.actions.length > 0);
|
||||
this.props.toggleSelected(false, this.props.getPostActions().length > 0);
|
||||
this.props.onPress();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {connect} from 'react-redux';
|
|||
import {bindActionCreators} from 'redux';
|
||||
|
||||
import {createPost, deletePost, removePost} from 'mattermost-redux/actions/posts';
|
||||
import {General, Posts} from 'mattermost-redux/constants';
|
||||
import {getCurrentChannelId, isCurrentChannelReadOnly} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getPost, makeGetCommentCountForPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
|
||||
|
|
@ -16,8 +17,6 @@ import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general
|
|||
|
||||
import {insertToDraft, setPostTooltipVisible} from 'app/actions/views/channel';
|
||||
import {addReaction} from 'app/actions/views/emoji';
|
||||
import {getDimensions} from 'app/selectors/device';
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
|
||||
import Post from './post';
|
||||
|
||||
|
|
@ -78,33 +77,36 @@ function makeMapStateToProps() {
|
|||
}
|
||||
}
|
||||
}
|
||||
const {deviceWidth} = getDimensions(state);
|
||||
|
||||
const isAdmin = checkIsAdmin(roles);
|
||||
const isSystemAdmin = checkIsSystemAdmin(roles);
|
||||
|
||||
let canDelete = false;
|
||||
let canEdit = false;
|
||||
let canEditUntil = -1;
|
||||
if (post) {
|
||||
canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin, isSystemAdmin);
|
||||
canEdit = canEditPost(state, config, license, currentTeamId, currentChannelId, currentUserId, post);
|
||||
if (canEdit && license.IsLicensed === 'true' &&
|
||||
(config.AllowEditPost === General.ALLOW_EDIT_POST_TIME_LIMIT || (config.PostEditTimeLimit !== -1 && config.PostEditTimeLimit !== '-1'))
|
||||
) {
|
||||
canEditUntil = post.create_at + (config.PostEditTimeLimit * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
channelIsReadOnly: isCurrentChannelReadOnly(state),
|
||||
config,
|
||||
canDelete,
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
currentTeamUrl: getCurrentTeamUrl(state),
|
||||
currentUserId,
|
||||
deviceWidth,
|
||||
post,
|
||||
isFirstReply,
|
||||
isLastReply,
|
||||
consecutivePost: isConsecutivePost(state, ownProps),
|
||||
hasComments: getCommentCountForPost(state, {post}) > 0,
|
||||
commentedOnPost,
|
||||
license,
|
||||
theme: getTheme(state),
|
||||
isFlagged: isPostFlagged(post.id, myPreferences),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,9 +25,8 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
|||
import {getToolTipVisible} from 'app/utils/tooltip';
|
||||
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
import DelayedAction from 'mattermost-redux/utils/delayed_action';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
import {editDisable, isPostEphemeral, isPostPendingOrFailed, isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
import {isPostEphemeral, isPostPendingOrFailed, isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
|
||||
import Config from 'assets/config';
|
||||
|
||||
|
|
@ -41,10 +40,8 @@ export default class Post extends PureComponent {
|
|||
removePost: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
channelIsReadOnly: PropTypes.bool,
|
||||
config: PropTypes.object.isRequired,
|
||||
currentTeamUrl: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
highlight: PropTypes.bool,
|
||||
style: ViewPropTypes.style,
|
||||
post: PropTypes.object,
|
||||
|
|
@ -56,10 +53,10 @@ export default class Post extends PureComponent {
|
|||
hasComments: PropTypes.bool,
|
||||
isSearchResult: PropTypes.bool,
|
||||
commentedOnPost: PropTypes.object,
|
||||
license: PropTypes.object.isRequired,
|
||||
managedConfig: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
canDelete: PropTypes.bool.isRequired,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
shouldRenderReplyButton: PropTypes.bool,
|
||||
|
|
@ -83,37 +80,6 @@ export default class Post extends PureComponent {
|
|||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const {config, license, currentUserId, post} = props;
|
||||
this.editDisableAction = new DelayedAction(this.handleEditDisable);
|
||||
if (post) {
|
||||
editDisable(config, license, currentUserId, post, this.editDisableAction);
|
||||
}
|
||||
this.state = {
|
||||
canEdit: this.props.canEdit,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.config !== this.props.config ||
|
||||
nextProps.license !== this.props.license ||
|
||||
nextProps.currentUserId !== this.props.currentUserId ||
|
||||
nextProps.post !== this.props.post) {
|
||||
const {config, license, currentUserId, post} = nextProps;
|
||||
|
||||
editDisable(config, license, currentUserId, post, this.editDisableAction);
|
||||
this.setState({
|
||||
canEdit: nextProps.canEdit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.editDisableAction.cancel();
|
||||
}
|
||||
|
||||
goToUserProfile = () => {
|
||||
const {intl} = this.context;
|
||||
const {navigator, post, theme} = this.props;
|
||||
|
|
@ -165,7 +131,6 @@ export default class Post extends PureComponent {
|
|||
text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}),
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
this.editDisableAction.cancel();
|
||||
actions.deletePost(post);
|
||||
if (post.user_id === currentUserId) {
|
||||
actions.removePost(post);
|
||||
|
|
@ -479,7 +444,8 @@ export default class Post extends PureComponent {
|
|||
<PostBody
|
||||
ref={'postBody'}
|
||||
canDelete={this.props.canDelete}
|
||||
canEdit={this.state.canEdit}
|
||||
canEdit={this.props.canEdit}
|
||||
canEditUntil={this.props.canEditUntil}
|
||||
highlight={highlight}
|
||||
channelIsReadOnly={channelIsReadOnly}
|
||||
isSearchResult={isSearchResult}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@ import PropTypes from 'prop-types';
|
|||
import {
|
||||
Dimensions,
|
||||
Platform,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
|
||||
|
|
@ -21,6 +19,7 @@ import CombinedSystemMessage from 'app/components/combined_system_message';
|
|||
import FormattedText from 'app/components/formatted_text';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import OptionsContext from 'app/components/options_context';
|
||||
import ShowMoreButton from 'app/components/show_more_button';
|
||||
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown';
|
||||
|
|
@ -41,6 +40,7 @@ export default class PostBody extends PureComponent {
|
|||
canAddReaction: PropTypes.bool,
|
||||
canDelete: PropTypes.bool,
|
||||
canEdit: PropTypes.bool,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
channelIsReadOnly: PropTypes.bool.isRequired,
|
||||
fileIds: PropTypes.array,
|
||||
hasBeenDeleted: PropTypes.bool,
|
||||
|
|
@ -120,6 +120,7 @@ export default class PostBody extends PureComponent {
|
|||
const {formatMessage} = this.context.intl;
|
||||
const {
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
canDelete,
|
||||
canAddReaction,
|
||||
channelIsReadOnly,
|
||||
|
|
@ -169,7 +170,7 @@ export default class PostBody extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
if (canEdit) {
|
||||
if (canEdit && (canEditUntil === -1 || canEditUntil > Date.now())) {
|
||||
actions.push({text: formatMessage({id: 'post_info.edit', defaultMessage: 'Edit'}), onPress: onPostEdit});
|
||||
}
|
||||
|
||||
|
|
@ -336,64 +337,12 @@ export default class PostBody extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
renderShowMoreOption = (style) => {
|
||||
const {highlight, theme} = this.props;
|
||||
const {isLongPost} = this.state;
|
||||
|
||||
if (!isLongPost) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gradientColors = [];
|
||||
if (highlight) {
|
||||
gradientColors.push(
|
||||
changeOpacity(theme.mentionHighlightBg, 0),
|
||||
changeOpacity(theme.mentionHighlightBg, 0.15),
|
||||
changeOpacity(theme.mentionHighlightBg, 0.5),
|
||||
);
|
||||
} else {
|
||||
gradientColors.push(
|
||||
changeOpacity(theme.centerChannelBg, 0),
|
||||
changeOpacity(theme.centerChannelBg, 0.75),
|
||||
theme.centerChannelBg,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<LinearGradient
|
||||
colors={gradientColors}
|
||||
locations={[0, 0.7, 1]}
|
||||
style={style.showMoreGradient}
|
||||
/>
|
||||
<View style={style.showMoreContainer}>
|
||||
<View style={style.showMoreDividerLeft}/>
|
||||
<TouchableOpacity
|
||||
onPress={this.openLongPost}
|
||||
style={style.showMoreButtonContainer}
|
||||
>
|
||||
<View style={style.showMoreButton}>
|
||||
<Text style={style.showMorePlusSign}>
|
||||
{'+'}
|
||||
</Text>
|
||||
<FormattedText
|
||||
id='mobile.post_body.show_more'
|
||||
defaultMessage='Show More'
|
||||
style={style.showMoreText}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<View style={style.showMoreDividerRight}/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {
|
||||
hasBeenDeleted,
|
||||
hasBeenEdited,
|
||||
highlight,
|
||||
isFailed,
|
||||
isPending,
|
||||
isPostAddChannelMember,
|
||||
|
|
@ -488,7 +437,7 @@ export default class PostBody extends PureComponent {
|
|||
body = (
|
||||
<View style={style.messageBody}>
|
||||
<OptionsContext
|
||||
actions={this.getPostActions()}
|
||||
getPostActions={this.getPostActions}
|
||||
ref='options'
|
||||
onPress={onPress}
|
||||
toggleSelected={toggleSelected}
|
||||
|
|
@ -496,7 +445,12 @@ export default class PostBody extends PureComponent {
|
|||
>
|
||||
<View onLayout={this.measurePost}>
|
||||
{messageComponent}
|
||||
{this.renderShowMoreOption(style)}
|
||||
{isLongPost &&
|
||||
<ShowMoreButton
|
||||
highlight={highlight}
|
||||
onPress={this.openLongPost}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
{this.renderPostAdditionalContent(blockStyles, messageStyle, textStyles)}
|
||||
{this.renderFileAttachments()}
|
||||
|
|
@ -562,56 +516,5 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
systemMessage: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
showMoreGradient: {
|
||||
flex: 1,
|
||||
height: 50,
|
||||
position: 'absolute',
|
||||
top: -50,
|
||||
width: '100%',
|
||||
},
|
||||
showMoreContainer: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
position: 'relative',
|
||||
top: -7.5,
|
||||
},
|
||||
showMoreDividerLeft: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginRight: 10,
|
||||
},
|
||||
showMoreDividerRight: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 10,
|
||||
},
|
||||
showMoreButtonContainer: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
borderRadius: 4,
|
||||
borderWidth: 1,
|
||||
height: 37,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
showMoreButton: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
showMorePlusSign: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginRight: 8,
|
||||
},
|
||||
showMoreText: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ export default class PostHeader extends PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<React.Fragment>
|
||||
<View style={[style.postInfoContainer, (isPendingOrFailedPost && style.pendingPost)]}>
|
||||
<View style={{flexDirection: 'row', flex: 1}}>
|
||||
{this.getDisplayName(style)}
|
||||
|
|
@ -253,7 +253,7 @@ export default class PostHeader extends PureComponent {
|
|||
{this.renderCommentedOnMessage(style)}
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,9 +234,11 @@ export default class PostList extends PureComponent {
|
|||
nextConfig = await mattermostManaged.getLocalConfig();
|
||||
}
|
||||
|
||||
this.setState({
|
||||
managedConfig: nextConfig,
|
||||
});
|
||||
if (Object.keys(nextConfig).length) {
|
||||
this.setState({
|
||||
managedConfig: nextConfig,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
keyExtractor = (item) => {
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ function withLayout(WrappedComponent) {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {index, onLayoutCalled, shouldCallOnLayout, ...otherProps} = this.props; //eslint-disable-line no-unused-vars
|
||||
return (
|
||||
<View onLayout={this.onLayout}>
|
||||
<WrappedComponent {...this.props}/>
|
||||
<WrappedComponent {...otherProps}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,893 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ShowMoreButton should match, button snapshot 1`] = `
|
||||
<Component
|
||||
style={Object {}}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={Object {}}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={Object {}}
|
||||
/>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`ShowMoreButton should match, button snapshot 2`] = `
|
||||
<Component
|
||||
style={Object {}}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={Object {}}
|
||||
>
|
||||
-
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show Less"
|
||||
id="post_info.message.show_less"
|
||||
style={Object {}}
|
||||
/>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`ShowMoreButton should match, full snapshot 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <ShowMoreButton
|
||||
highlight={false}
|
||||
onPress={[MockFunction]}
|
||||
showMore={true}
|
||||
theme={
|
||||
Object {
|
||||
"centerChannelBg": "#2f3e4e",
|
||||
"centerChannelColor": "#dddddd",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<LinearGradient
|
||||
colors={
|
||||
Array [
|
||||
"rgba(47,62,78,0)",
|
||||
"rgba(47,62,78,0.75)",
|
||||
"#2f3e4e",
|
||||
]
|
||||
}
|
||||
locations={
|
||||
Array [
|
||||
0,
|
||||
0.7,
|
||||
1,
|
||||
]
|
||||
}
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
"height": 50,
|
||||
"position": "absolute",
|
||||
"top": -50,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": "center",
|
||||
"position": "relative",
|
||||
"top": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[MockFunction]}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
</TouchableOpacity>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
],
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"colors": Array [
|
||||
"rgba(47,62,78,0)",
|
||||
"rgba(47,62,78,0.75)",
|
||||
"#2f3e4e",
|
||||
],
|
||||
"locations": Array [
|
||||
0,
|
||||
0.7,
|
||||
1,
|
||||
],
|
||||
"style": Object {
|
||||
"flex": 1,
|
||||
"height": 50,
|
||||
"position": "absolute",
|
||||
"top": -50,
|
||||
"width": "100%",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[MockFunction]}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
</TouchableOpacity>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": "center",
|
||||
"position": "relative",
|
||||
"top": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"activeOpacity": 0.2,
|
||||
"children": <Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
"onPress": [MockFunction],
|
||||
"style": Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>,
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"accessible": true,
|
||||
"allowFontScaling": true,
|
||||
"children": "+",
|
||||
"ellipsizeMode": "tail",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": "+",
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"defaultMessage": "Show More",
|
||||
"id": "post_info.message.show_more",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<LinearGradient
|
||||
colors={
|
||||
Array [
|
||||
"rgba(47,62,78,0)",
|
||||
"rgba(47,62,78,0.75)",
|
||||
"#2f3e4e",
|
||||
]
|
||||
}
|
||||
locations={
|
||||
Array [
|
||||
0,
|
||||
0.7,
|
||||
1,
|
||||
]
|
||||
}
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
"height": 50,
|
||||
"position": "absolute",
|
||||
"top": -50,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": "center",
|
||||
"position": "relative",
|
||||
"top": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[MockFunction]}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
</TouchableOpacity>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
],
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"colors": Array [
|
||||
"rgba(47,62,78,0)",
|
||||
"rgba(47,62,78,0.75)",
|
||||
"#2f3e4e",
|
||||
],
|
||||
"locations": Array [
|
||||
0,
|
||||
0.7,
|
||||
1,
|
||||
],
|
||||
"style": Object {
|
||||
"flex": 1,
|
||||
"height": 50,
|
||||
"position": "absolute",
|
||||
"top": -50,
|
||||
"width": "100%",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[MockFunction]}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
</TouchableOpacity>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": "center",
|
||||
"position": "relative",
|
||||
"top": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginRight": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"activeOpacity": 0.2,
|
||||
"children": <Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
"onPress": [MockFunction],
|
||||
"style": Object {
|
||||
"backgroundColor": "#2f3e4e",
|
||||
"borderColor": "rgba(221,221,221,0.2)",
|
||||
"borderRadius": 4,
|
||||
"borderWidth": 1,
|
||||
"height": 37,
|
||||
"paddingHorizontal": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Text
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
ellipsizeMode="tail"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
+
|
||||
</Text>,
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Show More"
|
||||
id="post_info.message.show_more"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"accessible": true,
|
||||
"allowFontScaling": true,
|
||||
"children": "+",
|
||||
"ellipsizeMode": "tail",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 16,
|
||||
"fontWeight": "600",
|
||||
"marginRight": 8,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": "+",
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"defaultMessage": "Show More",
|
||||
"id": "post_info.message.show_more",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
"fontWeight": "600",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": "rgba(221,221,221,0.2)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 10,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
16
app/components/show_more_button/index.js
Normal file
16
app/components/show_more_button/index.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import ShowMoreButton from './show_more_button';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
theme: getTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ShowMoreButton);
|
||||
142
app/components/show_more_button/show_more_button.js
Normal file
142
app/components/show_more_button/show_more_button.js
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
// 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 {Text, TouchableOpacity, View} from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
export default class ShowMoreButton extends PureComponent {
|
||||
static propTypes = {
|
||||
highlight: PropTypes.bool,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
showMore: PropTypes.bool.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
showMore: true,
|
||||
};
|
||||
|
||||
renderButton(showMore, style) {
|
||||
let sign = '+';
|
||||
let textId = 'post_info.message.show_more';
|
||||
let textMessage = 'Show More';
|
||||
if (!showMore) {
|
||||
sign = '-';
|
||||
textId = 'post_info.message.show_less';
|
||||
textMessage = 'Show Less';
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.button}>
|
||||
<Text style={style.sign}>{sign}</Text>
|
||||
<FormattedText
|
||||
id={textId}
|
||||
defaultMessage={textMessage}
|
||||
style={style.text}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {highlight, showMore, theme} = this.props;
|
||||
const style = getStyleSheet(theme, showMore);
|
||||
|
||||
let gradientColors = [
|
||||
changeOpacity(theme.centerChannelBg, 0),
|
||||
changeOpacity(theme.centerChannelBg, 0.75),
|
||||
theme.centerChannelBg,
|
||||
];
|
||||
if (highlight) {
|
||||
gradientColors = [
|
||||
changeOpacity(theme.mentionHighlightBg, 0),
|
||||
changeOpacity(theme.mentionHighlightBg, 0.15),
|
||||
changeOpacity(theme.mentionHighlightBg, 0.5),
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
{showMore &&
|
||||
<LinearGradient
|
||||
colors={gradientColors}
|
||||
locations={[0, 0.7, 1]}
|
||||
style={style.gradient}
|
||||
/>
|
||||
}
|
||||
<View style={style.container}>
|
||||
<View style={style.dividerLeft}/>
|
||||
<TouchableOpacity
|
||||
onPress={this.props.onPress}
|
||||
style={style.buttonContainer}
|
||||
>
|
||||
{this.renderButton(showMore, style)}
|
||||
</TouchableOpacity>
|
||||
<View style={style.dividerRight}/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme, showMore) => {
|
||||
return {
|
||||
gradient: {
|
||||
flex: 1,
|
||||
height: 50,
|
||||
position: 'absolute',
|
||||
top: -50,
|
||||
width: '100%',
|
||||
},
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
position: 'relative',
|
||||
top: showMore ? -7.5 : 10,
|
||||
},
|
||||
dividerLeft: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginRight: 10,
|
||||
},
|
||||
buttonContainer: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
borderRadius: 4,
|
||||
borderWidth: 1,
|
||||
height: 37,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
button: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
sign: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginRight: 8,
|
||||
},
|
||||
text: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
},
|
||||
dividerRight: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
64
app/components/show_more_button/show_more_button.test.js
Normal file
64
app/components/show_more_button/show_more_button.test.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {TouchableOpacity} from 'react-native';
|
||||
import {configure, shallow} from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
configure({adapter: new Adapter()});
|
||||
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import ShowMoreButton from './show_more_button';
|
||||
|
||||
describe('ShowMoreButton', () => {
|
||||
const baseProps = {
|
||||
highlight: false,
|
||||
onPress: jest.fn(),
|
||||
showMore: true,
|
||||
theme: {
|
||||
centerChannelBg: '#2f3e4e',
|
||||
centerChannelColor: '#dddddd',
|
||||
},
|
||||
};
|
||||
|
||||
test('should match, full snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<ShowMoreButton {...baseProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match, button snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<ShowMoreButton {...baseProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper.instance().renderButton(true, {button: {}, sign: {}, text: {}})).toMatchSnapshot();
|
||||
expect(wrapper.instance().renderButton(false, {button: {}, sign: {}, text: {}})).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should LinearGradient exists', () => {
|
||||
const wrapper = shallow(
|
||||
<ShowMoreButton {...baseProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(LinearGradient).exists()).toBe(true);
|
||||
wrapper.setProps({showMore: false});
|
||||
expect(wrapper.find(LinearGradient).exists()).toBe(false);
|
||||
});
|
||||
|
||||
test('should call props.onPress on press of TouchableOpacity', () => {
|
||||
const onPress = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<ShowMoreButton
|
||||
{...baseProps}
|
||||
onPress={onPress}
|
||||
/>
|
||||
);
|
||||
|
||||
wrapper.find(TouchableOpacity).props().onPress();
|
||||
expect(onPress).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -29,6 +29,7 @@ export default class ChannelInfo extends PureComponent {
|
|||
closeGMChannel: PropTypes.func.isRequired,
|
||||
deleteChannel: PropTypes.func.isRequired,
|
||||
getChannelStats: PropTypes.func.isRequired,
|
||||
getChannel: PropTypes.func.isRequired,
|
||||
leaveChannel: PropTypes.func.isRequired,
|
||||
loadChannelsByTeamName: PropTypes.func.isRequired,
|
||||
favoriteChannel: PropTypes.func.isRequired,
|
||||
|
|
@ -202,6 +203,9 @@ export default class ChannelInfo extends PureComponent {
|
|||
displayName: channel.display_name,
|
||||
}
|
||||
);
|
||||
if (result.error.server_error_id === 'api.channel.delete_channel.deleted.app_error') {
|
||||
this.props.actions.getChannel(channel.id);
|
||||
}
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {connect} from 'react-redux';
|
|||
import {
|
||||
favoriteChannel,
|
||||
getChannelStats,
|
||||
getChannel,
|
||||
deleteChannel,
|
||||
unfavoriteChannel,
|
||||
updateChannelNotifyProps,
|
||||
|
|
@ -89,6 +90,7 @@ function mapDispatchToProps(dispatch) {
|
|||
closeGMChannel,
|
||||
deleteChannel,
|
||||
getChannelStats,
|
||||
getChannel,
|
||||
leaveChannel,
|
||||
loadChannelsByTeamName,
|
||||
favoriteChannel,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export default class EditChannel extends PureComponent {
|
|||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
patchChannel: PropTypes.func.isRequired,
|
||||
getChannel: PropTypes.func.isRequired,
|
||||
setChannelDisplayName: PropTypes.func.isRequired,
|
||||
}),
|
||||
navigator: PropTypes.object.isRequired,
|
||||
|
|
@ -204,7 +205,7 @@ export default class EditChannel extends PureComponent {
|
|||
return {error: formatMessage(messages.name_lowercase)};
|
||||
};
|
||||
|
||||
onUpdateChannel = () => {
|
||||
onUpdateChannel = async () => {
|
||||
Keyboard.dismiss();
|
||||
const {displayName, channelURL, purpose, header} = this.state;
|
||||
const {channel: {id, type}} = this.props;
|
||||
|
|
@ -230,7 +231,10 @@ export default class EditChannel extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
this.props.actions.patchChannel(id, channel);
|
||||
const data = await this.props.actions.patchChannel(id, channel);
|
||||
if (data.error && data.error.server_error_id === 'store.sql_channel.update.archived_channel.app_error') {
|
||||
this.props.actions.getChannel(id);
|
||||
}
|
||||
};
|
||||
|
||||
onNavigatorEvent = (event) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {connect} from 'react-redux';
|
|||
|
||||
import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentTeamUrl} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {patchChannel} from 'mattermost-redux/actions/channels';
|
||||
import {patchChannel, getChannel} from 'mattermost-redux/actions/channels';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {setChannelDisplayName} from 'app/actions/views/channel';
|
||||
|
|
@ -33,6 +33,7 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
patchChannel,
|
||||
getChannel,
|
||||
setChannelDisplayName,
|
||||
}, dispatch),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
import {setSystemEmojis} from 'mattermost-redux/actions/emojis';
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
|
|
@ -56,15 +57,14 @@ const lazyLoadReplyPushNotifications = () => {
|
|||
*/
|
||||
export default class Entry extends PureComponent {
|
||||
static propTypes = {
|
||||
config: PropTypes.object,
|
||||
theme: PropTypes.object,
|
||||
navigator: PropTypes.object,
|
||||
isLandscape: PropTypes.bool,
|
||||
hydrationComplete: PropTypes.bool,
|
||||
enableTimezone: PropTypes.bool,
|
||||
deviceTimezone: PropTypes.string,
|
||||
initializeModules: PropTypes.func.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
autoUpdateTimezone: PropTypes.func.isRequired,
|
||||
setDeviceToken: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
|
@ -132,6 +132,7 @@ export default class Entry extends PureComponent {
|
|||
this.setAppCredentials();
|
||||
this.setStartupThemes();
|
||||
this.handleNotification();
|
||||
this.loadSystemEmojis();
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
this.launchForAndroid();
|
||||
|
|
@ -226,6 +227,11 @@ export default class Entry extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
loadSystemEmojis = () => {
|
||||
const EmojiIndicesByAlias = require('app/utils/emojis').EmojiIndicesByAlias;
|
||||
setSystemEmojis(EmojiIndicesByAlias);
|
||||
};
|
||||
|
||||
renderLogin = () => {
|
||||
const SelectServer = lazyLoadSelectServer();
|
||||
const props = {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import {connect} from 'react-redux';
|
|||
import {setDeviceToken} from 'mattermost-redux/actions/general';
|
||||
import {autoUpdateTimezone} from 'mattermost-redux/actions/timezone';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import {isLandscape} from 'app/selectors/device';
|
||||
import {getDeviceTimezone, isTimezoneEnabled} from 'app/utils/timezone';
|
||||
|
|
@ -16,16 +15,12 @@ const lazyLoadEntry = () => {
|
|||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const config = getConfig(state);
|
||||
|
||||
const enableTimezone = isTimezoneEnabled(state);
|
||||
const deviceTimezone = getDeviceTimezone();
|
||||
|
||||
return {
|
||||
config,
|
||||
theme: getTheme(state),
|
||||
isLandscape: isLandscape(state),
|
||||
hydrationComplete: state.views.root.hydrationComplete,
|
||||
enableTimezone,
|
||||
deviceTimezone,
|
||||
};
|
||||
|
|
@ -34,8 +29,8 @@ function mapStateToProps(state) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
setDeviceToken,
|
||||
autoUpdateTimezone,
|
||||
setDeviceToken,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ import {getCurrentChannelId, filterPostIds} from 'mattermost-redux/selectors/ent
|
|||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
||||
import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils';
|
||||
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
|
||||
import {isLandscape} from 'app/selectors/device';
|
||||
import {makePreparePostIdsForSearchPosts} from 'app/selectors/post_list';
|
||||
import {handleSearchDraftChanged} from 'app/actions/views/search';
|
||||
import {getDeviceUtcOffset, getUtcOffsetForTimeZone, isTimezoneEnabled} from 'app/utils/timezone';
|
||||
|
||||
import Search from './search';
|
||||
|
||||
|
|
@ -30,6 +33,11 @@ function makeMapStateToProps() {
|
|||
const {recent} = state.entities.search;
|
||||
const {searchPosts: searchRequest} = state.requests.search;
|
||||
|
||||
const currentUser = getCurrentUser(state);
|
||||
const enableTimezone = isTimezoneEnabled(state);
|
||||
const userCurrentTimezone = enableTimezone ? getUserCurrentTimezone(currentUser.timezone) : '';
|
||||
const timezoneOffsetInSeconds = (userCurrentTimezone.length > 0 ? getUtcOffsetForTimeZone(userCurrentTimezone) : getDeviceUtcOffset()) * 60;
|
||||
|
||||
const serverVersion = state.entities.general.serverVersion;
|
||||
const enableDateSuggestion = isMinimumServerVersion(serverVersion, 5, 3);
|
||||
|
||||
|
|
@ -43,6 +51,7 @@ function makeMapStateToProps() {
|
|||
searchingStatus: searchRequest.status,
|
||||
theme: getTheme(state),
|
||||
enableDateSuggestion,
|
||||
timezoneOffsetInSeconds,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import SearchBar from 'app/components/search_bar';
|
|||
import StatusBar from 'app/components/status_bar';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {getDeviceUtcOffset} from 'app/utils/timezone';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
import ChannelDisplayName from './channel_display_name';
|
||||
|
|
@ -65,6 +64,7 @@ export default class Search extends PureComponent {
|
|||
searchingStatus: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
enableDateSuggestion: PropTypes.bool,
|
||||
timezoneOffsetInSeconds: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -469,8 +469,7 @@ export default class Search extends PureComponent {
|
|||
});
|
||||
|
||||
// timezone offset in seconds
|
||||
const timeZoneOffset = getDeviceUtcOffset() * 60;
|
||||
actions.searchPostsWithParams(currentTeamId, {terms: terms.trim(), is_or_search: isOrSearch, time_zone_offset: timeZoneOffset}, true);
|
||||
actions.searchPostsWithParams(currentTeamId, {terms: terms.trim(), is_or_search: isOrSearch, time_zone_offset: this.props.timezoneOffsetInSeconds}, true);
|
||||
};
|
||||
|
||||
handleSearchButtonPress = preventDoubleTap((text) => {
|
||||
|
|
|
|||
609
app/screens/select_team/__snapshots__/select_team.test.js.snap
Normal file
609
app/screens/select_team/__snapshots__/select_team.test.js.snap
Normal file
|
|
@ -0,0 +1,609 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SelectTeam should match snapshot for fail of teams 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <SelectTeam
|
||||
actions={
|
||||
Object {
|
||||
"getTeams": [Function],
|
||||
"handleTeamChange": [MockFunction],
|
||||
"joinTeam": [MockFunction],
|
||||
"logout": [MockFunction],
|
||||
"markChannelAsRead": [MockFunction],
|
||||
}
|
||||
}
|
||||
currentChannelId="someId"
|
||||
currentUrl="test"
|
||||
joinTeamRequest={Object {}}
|
||||
navigator={
|
||||
Object {
|
||||
"setOnNavigatorEvent": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
[Function],
|
||||
],
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
teams={Array []}
|
||||
teamsRequest={
|
||||
Object {
|
||||
"status": "failure",
|
||||
}
|
||||
}
|
||||
theme={Object {}}
|
||||
userWithoutTeams={false}
|
||||
/>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"errorDescription": Object {
|
||||
"defaultMessage": "Make sure you have an active connection and try again.",
|
||||
"id": "mobile.failed_network_action.shortDescription",
|
||||
},
|
||||
"errorTitle": Object {
|
||||
"defaultMessage": "Team Not Found",
|
||||
"id": "error.team_not_found.title",
|
||||
},
|
||||
"onRetry": [Function],
|
||||
"theme": Object {},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"errorDescription": Object {
|
||||
"defaultMessage": "Make sure you have an active connection and try again.",
|
||||
"id": "mobile.failed_network_action.shortDescription",
|
||||
},
|
||||
"errorTitle": Object {
|
||||
"defaultMessage": "Team Not Found",
|
||||
"id": "error.team_not_found.title",
|
||||
},
|
||||
"onRetry": [Function],
|
||||
"theme": Object {},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SelectTeam should match snapshot for teams 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <SelectTeam
|
||||
actions={
|
||||
Object {
|
||||
"getTeams": [Function],
|
||||
"handleTeamChange": [MockFunction],
|
||||
"joinTeam": [MockFunction],
|
||||
"logout": [MockFunction],
|
||||
"markChannelAsRead": [MockFunction],
|
||||
}
|
||||
}
|
||||
currentChannelId="someId"
|
||||
currentUrl="test"
|
||||
joinTeamRequest={Object {}}
|
||||
navigator={
|
||||
Object {
|
||||
"setOnNavigatorEvent": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
[Function],
|
||||
],
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
teams={
|
||||
Array [
|
||||
Object {
|
||||
"id": "kemjcpu9bi877yegqjs18ndp4r",
|
||||
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
|
||||
"name": "test",
|
||||
},
|
||||
]
|
||||
}
|
||||
teamsRequest={
|
||||
Object {
|
||||
"status": "success",
|
||||
}
|
||||
}
|
||||
theme={Object {}}
|
||||
userWithoutTeams={false}
|
||||
/>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Connect(StatusBar) />,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"marginHorizontal": 16,
|
||||
"marginTop": 20,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"marginRight": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
<FlatList
|
||||
data={
|
||||
Array [
|
||||
Object {
|
||||
"id": "kemjcpu9bi877yegqjs18ndp4r",
|
||||
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
|
||||
"name": "test",
|
||||
},
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
maxToRenderPerBatch={10}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
updateCellsBatchingPeriod={50}
|
||||
viewabilityConfig={
|
||||
Object {
|
||||
"viewAreaCoveragePercentThreshold": 3,
|
||||
"waitForInteraction": false,
|
||||
}
|
||||
}
|
||||
windowSize={21}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"backgroundColor": undefined,
|
||||
"flex": 1,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"marginRight": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"marginHorizontal": 16,
|
||||
"marginTop": 20,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"style": Object {
|
||||
"marginRight": 15,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"defaultMessage": "Open teams you can join",
|
||||
"id": "mobile.select_team.join_open",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"data": Array [
|
||||
Object {
|
||||
"id": "kemjcpu9bi877yegqjs18ndp4r",
|
||||
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
|
||||
"name": "test",
|
||||
},
|
||||
],
|
||||
"disableVirtualization": false,
|
||||
"horizontal": false,
|
||||
"initialNumToRender": 10,
|
||||
"keyExtractor": [Function],
|
||||
"maxToRenderPerBatch": 10,
|
||||
"numColumns": 1,
|
||||
"onEndReachedThreshold": 2,
|
||||
"renderItem": [Function],
|
||||
"scrollEventThrottle": 50,
|
||||
"updateCellsBatchingPeriod": 50,
|
||||
"viewabilityConfig": Object {
|
||||
"viewAreaCoveragePercentThreshold": 3,
|
||||
"waitForInteraction": false,
|
||||
},
|
||||
"windowSize": 21,
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Connect(StatusBar) />,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"marginHorizontal": 16,
|
||||
"marginTop": 20,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"marginRight": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
<FlatList
|
||||
data={
|
||||
Array [
|
||||
Object {
|
||||
"id": "kemjcpu9bi877yegqjs18ndp4r",
|
||||
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
|
||||
"name": "test",
|
||||
},
|
||||
]
|
||||
}
|
||||
disableVirtualization={false}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
keyExtractor={[Function]}
|
||||
maxToRenderPerBatch={10}
|
||||
numColumns={1}
|
||||
onEndReachedThreshold={2}
|
||||
renderItem={[Function]}
|
||||
scrollEventThrottle={50}
|
||||
updateCellsBatchingPeriod={50}
|
||||
viewabilityConfig={
|
||||
Object {
|
||||
"viewAreaCoveragePercentThreshold": 3,
|
||||
"waitForInteraction": false,
|
||||
}
|
||||
}
|
||||
windowSize={21}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"backgroundColor": undefined,
|
||||
"flex": 1,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": Array [
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"marginRight": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
<InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>,
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
],
|
||||
"style": Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"marginHorizontal": 16,
|
||||
"marginTop": 20,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <InjectIntl(FormattedText)
|
||||
defaultMessage="Open teams you can join"
|
||||
id="mobile.select_team.join_open"
|
||||
style={
|
||||
Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
}
|
||||
}
|
||||
/>,
|
||||
"style": Object {
|
||||
"marginRight": 15,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"defaultMessage": "Open teams you can join",
|
||||
"id": "mobile.select_team.join_open",
|
||||
"style": Object {
|
||||
"color": undefined,
|
||||
"fontSize": 13,
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"style": Object {
|
||||
"backgroundColor": undefined,
|
||||
"height": 1,
|
||||
"width": "100%",
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"data": Array [
|
||||
Object {
|
||||
"id": "kemjcpu9bi877yegqjs18ndp4r",
|
||||
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
|
||||
"name": "test",
|
||||
},
|
||||
],
|
||||
"disableVirtualization": false,
|
||||
"horizontal": false,
|
||||
"initialNumToRender": 10,
|
||||
"keyExtractor": [Function],
|
||||
"maxToRenderPerBatch": 10,
|
||||
"numColumns": 1,
|
||||
"onEndReachedThreshold": 2,
|
||||
"renderItem": [Function],
|
||||
"scrollEventThrottle": 50,
|
||||
"updateCellsBatchingPeriod": 50,
|
||||
"viewabilityConfig": Object {
|
||||
"viewAreaCoveragePercentThreshold": 3,
|
||||
"waitForInteraction": false,
|
||||
},
|
||||
"windowSize": 21,
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
@ -28,7 +28,7 @@ function mapStateToProps(state) {
|
|||
}
|
||||
|
||||
return {
|
||||
teamsRequest: state.requests.teams.getMyTeams,
|
||||
teamsRequest: state.requests.teams.getTeams,
|
||||
teams: Object.values(getJoinableTeams(state)).sort(sortTeams),
|
||||
currentChannelId: getCurrentChannelId(state),
|
||||
joinTeamRequest: state.requests.teams.joinTeam,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import FailedNetworkAction from 'app/components/failed_network_action';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import Loading from 'app/components/loading';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
|
|
@ -28,6 +29,16 @@ const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
|
|||
|
||||
const TEAMS_PER_PAGE = 200;
|
||||
|
||||
const errorTitle = {
|
||||
id: 'error.team_not_found.title',
|
||||
defaultMessage: 'Team Not Found',
|
||||
};
|
||||
|
||||
const errorDescription = {
|
||||
id: 'mobile.failed_network_action.shortDescription',
|
||||
defaultMessage: 'Make sure you have an active connection and try again.',
|
||||
};
|
||||
|
||||
export default class SelectTeam extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
|
|
@ -44,6 +55,7 @@ export default class SelectTeam extends PureComponent {
|
|||
userWithoutTeams: PropTypes.bool,
|
||||
teams: PropTypes.array.isRequired,
|
||||
theme: PropTypes.object,
|
||||
teamsRequest: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -57,9 +69,7 @@ export default class SelectTeam extends PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.actions.getTeams(0, TEAMS_PER_PAGE).then(() => {
|
||||
this.buildData(this.props);
|
||||
});
|
||||
this.getTeams();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
|
@ -77,6 +87,14 @@ export default class SelectTeam extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
getTeams = () => {
|
||||
this.setState({loading: true});
|
||||
this.props.actions.getTeams(0, TEAMS_PER_PAGE).then(() => {
|
||||
this.setState({loading: false});
|
||||
this.buildData(this.props);
|
||||
});
|
||||
}
|
||||
|
||||
buildData = (props) => {
|
||||
if (props.teams.length) {
|
||||
this.setState({teams: props.teams});
|
||||
|
|
@ -213,10 +231,21 @@ export default class SelectTeam extends PureComponent {
|
|||
const {teams} = this.state;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
if (this.state.joining) {
|
||||
if (this.state.joining || this.state.loading) {
|
||||
return <Loading/>;
|
||||
}
|
||||
|
||||
if (this.props.teamsRequest.status === RequestStatus.FAILURE) {
|
||||
return (
|
||||
<FailedNetworkAction
|
||||
onRetry={this.getTeams}
|
||||
theme={theme}
|
||||
errorTitle={errorTitle}
|
||||
errorDescription={errorDescription}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar/>
|
||||
|
|
|
|||
97
app/screens/select_team/select_team.test.js
Normal file
97
app/screens/select_team/select_team.test.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import {configure, shallow} from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
configure({adapter: new Adapter()});
|
||||
|
||||
import SelectTeam from './select_team.js';
|
||||
|
||||
jest.mock('rn-fetch-blob', () => ({
|
||||
fs: {
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('rn-fetch-blob/fs', () => ({
|
||||
dirs: {
|
||||
DocumentDir: () => jest.fn(),
|
||||
CacheDir: () => jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('app/utils/theme', () => {
|
||||
const original = require.requireActual('app/utils/theme');
|
||||
return {
|
||||
...original,
|
||||
changeOpacity: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
const getTeams = async () => {
|
||||
return {
|
||||
error: {},
|
||||
};
|
||||
};
|
||||
|
||||
describe('SelectTeam', () => {
|
||||
const actions = {
|
||||
getTeams,
|
||||
handleTeamChange: jest.fn(),
|
||||
joinTeam: jest.fn(),
|
||||
logout: jest.fn(),
|
||||
markChannelAsRead: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
actions,
|
||||
currentChannelId: 'someId',
|
||||
currentUrl: 'test',
|
||||
joinTeamRequest: {},
|
||||
navigator: {
|
||||
setOnNavigatorEvent: jest.fn(),
|
||||
},
|
||||
userWithoutTeams: false,
|
||||
teams: [],
|
||||
theme: {},
|
||||
teamsRequest: {
|
||||
status: RequestStatus.FAILURE,
|
||||
},
|
||||
};
|
||||
|
||||
test('should match snapshot for fail of teams', async () => {
|
||||
const wrapper = shallow(
|
||||
<SelectTeam {...baseProps}/>,
|
||||
);
|
||||
expect(wrapper.state('loading')).toEqual(true);
|
||||
await getTeams();
|
||||
expect(wrapper.state('loading')).toEqual(false);
|
||||
wrapper.update();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot for teams', async () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
teams: [{
|
||||
id: 'kemjcpu9bi877yegqjs18ndp4r',
|
||||
invite_id: 'ojsnudhqzbfzpk6e4n6ip1hwae',
|
||||
name: 'test',
|
||||
}],
|
||||
teamsRequest: {
|
||||
status: RequestStatus.SUCCESS,
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<SelectTeam {...props}/>,
|
||||
);
|
||||
await getTeams();
|
||||
wrapper.update();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
@ -5,13 +5,18 @@ import DeviceInfo from 'react-native-device-info';
|
|||
|
||||
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
||||
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
export function getDeviceTimezone() {
|
||||
return DeviceInfo.getTimezone();
|
||||
}
|
||||
|
||||
export function getDeviceUtcOffset() {
|
||||
const reverseOffsetInMinutes = new Date().getTimezoneOffset();
|
||||
return -reverseOffsetInMinutes;
|
||||
return moment().utcOffset();
|
||||
}
|
||||
|
||||
export function getUtcOffsetForTimeZone(timezone) {
|
||||
return moment.tz(timezone).utcOffset();
|
||||
}
|
||||
|
||||
export function isTimezoneEnabled(state) {
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ function deepDiff(o1, o2, p) {
|
|||
}
|
||||
}
|
||||
|
||||
function whyDidYouUpdate(prevProps, prevState) {
|
||||
function whyDidYouUpdate(theClass, prevProps, prevState) {
|
||||
deepDiff({props: prevProps, state: prevState},
|
||||
{props: this.props, state: this.state},
|
||||
this.constructor.name);
|
||||
{props: theClass.props, state: theClass.state},
|
||||
theClass.constructor.name);
|
||||
}
|
||||
|
||||
export default whyDidYouUpdate;
|
||||
|
|
|
|||
|
|
@ -2455,6 +2455,7 @@
|
|||
"mobile.failed_network_action.description": "There seems to be a problem with your internet connection. Make sure you have an active connection and try again.",
|
||||
"mobile.failed_network_action.retry": "Try Again",
|
||||
"mobile.failed_network_action.title": "No internet connection",
|
||||
"mobile.failed_network_action.shortDescription": "Make sure you have an active connection and try again.",
|
||||
"mobile.file_upload.browse": "Browse Files",
|
||||
"mobile.file_upload.camera": "Take Photo or Video",
|
||||
"mobile.file_upload.library": "Photo Library",
|
||||
|
|
|
|||
|
|
@ -2427,7 +2427,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 136;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -2476,7 +2476,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 136;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>135</string>
|
||||
<string>136</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.12.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>135</string>
|
||||
<string>136</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@
|
|||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>135</string>
|
||||
<string>136</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
11
package-lock.json
generated
11
package-lock.json
generated
|
|
@ -10545,8 +10545,15 @@
|
|||
"moment": {
|
||||
"version": "2.22.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz",
|
||||
"integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz",
|
||||
"integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
},
|
||||
"morgan": {
|
||||
"version": "1.9.0",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
"jsc-android": "216113.0.3",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#28be3683bff6ae8c563883bb0ff04d7bd9ea31ee",
|
||||
"mime-db": "1.33.0",
|
||||
"moment-timezone": "0.5.21",
|
||||
"prop-types": "15.6.1",
|
||||
"react": "16.3.2",
|
||||
"react-intl": "2.4.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue