diff --git a/app/components/autocomplete/at_mention/at_mention.js b/app/components/autocomplete/at_mention/at_mention.js
index 9f35032fa8..1e8aa87d54 100644
--- a/app/components/autocomplete/at_mention/at_mention.js
+++ b/app/components/autocomplete/at_mention/at_mention.js
@@ -9,7 +9,6 @@ import {RequestStatus} from '@mm-redux/constants';
import {AT_MENTION_REGEX, AT_MENTION_SEARCH_REGEX} from 'app/constants/autocomplete';
import AtMentionItem from 'app/components/autocomplete/at_mention_item';
-import AutocompleteDivider from 'app/components/autocomplete/autocomplete_divider';
import AutocompleteSectionHeader from 'app/components/autocomplete/autocomplete_section_header';
import SpecialMentionItem from 'app/components/autocomplete/special_mention_item';
import GroupMentionItem from 'app/components/autocomplete/at_mention_group/at_mention_group';
@@ -67,7 +66,7 @@ export default class AtMention extends PureComponent {
mentionComplete: false,
sections: [],
});
-
+ this.props.onResultCountChange(0);
return;
}
@@ -208,12 +207,14 @@ export default class AtMention extends PureComponent {
};
renderSectionHeader = ({section}) => {
+ const isFirstSection = section.id === this.state.sections[0].id;
return (
);
};
@@ -270,7 +271,6 @@ export default class AtMention extends PureComponent {
sections={sections}
renderItem={this.renderItem}
renderSectionHeader={this.renderSectionHeader}
- ItemSeparatorComponent={AutocompleteDivider}
initialNumToRender={10}
nestedScrollEnabled={nestedScrollEnabled}
/>
@@ -282,6 +282,7 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
listView: {
backgroundColor: theme.centerChannelBg,
+ borderRadius: 4,
},
};
});
diff --git a/app/components/autocomplete/at_mention_item/at_mention_item.js b/app/components/autocomplete/at_mention_item/at_mention_item.js
index 0def8606be..1ef9938bf0 100644
--- a/app/components/autocomplete/at_mention_item/at_mention_item.js
+++ b/app/components/autocomplete/at_mention_item/at_mention_item.js
@@ -12,7 +12,7 @@ import ProfilePicture from 'app/components/profile_picture';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import {BotTag, GuestTag} from 'app/components/tag';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
-import {makeStyleSheetFromTheme} from 'app/utils/theme';
+import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
import FormattedText from 'app/components/formatted_text';
export default class AtMentionItem extends PureComponent {
@@ -28,6 +28,7 @@ export default class AtMentionItem extends PureComponent {
theme: PropTypes.object.isRequired,
isLandscape: PropTypes.bool.isRequired,
isCurrentUser: PropTypes.bool.isRequired,
+ showFullName: PropTypes.string,
};
static defaultProps = {
@@ -40,11 +41,24 @@ export default class AtMentionItem extends PureComponent {
onPress(username);
};
+ renderNameBlock = () => {
+ let name = '';
+ const {showFullName, firstName, lastName, nickname} = this.props;
+ const hasNickname = nickname.length > 0;
+
+ if (showFullName === 'true') {
+ name += `${firstName} ${lastName} `;
+ }
+
+ if (hasNickname) {
+ name += `(${nickname})`;
+ }
+
+ return name;
+ }
+
render() {
const {
- firstName,
- lastName,
- nickname,
userId,
username,
theme,
@@ -55,46 +69,52 @@ export default class AtMentionItem extends PureComponent {
} = this.props;
const style = getStyleFromTheme(theme);
- const hasFullName = firstName.length > 0 && lastName.length > 0;
- const hasNickname = nickname.length > 0;
+ const name = this.renderNameBlock();
return (
-
-
+
+
+
+
+
+
+ {name}
+ {isCurrentUser &&
+ }
+
+
+ {` @${username}`}
+
- {`@${username}`}
-
-
- {hasFullName && {' - '}}
-
- {hasFullName && `${firstName} ${lastName}`}
- {hasNickname && ` (${nickname}) `}
- {isCurrentUser &&
- }
-
);
}
@@ -103,24 +123,28 @@ export default class AtMentionItem extends PureComponent {
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
row: {
+ height: 40,
paddingVertical: 8,
+ paddingTop: 4,
+ paddingHorizontal: 16,
flexDirection: 'row',
alignItems: 'center',
- backgroundColor: theme.centerChannelBg,
},
rowPicture: {
- marginHorizontal: 8,
- width: 20,
+ marginRight: 10,
+ marginLeft: 2,
+ width: 24,
alignItems: 'center',
justifyContent: 'center',
},
- rowUsername: {
- fontSize: 13,
+ rowFullname: {
+ fontSize: 15,
color: theme.centerChannelColor,
},
- rowFullname: {
+ rowUsername: {
color: theme.centerChannelColor,
- opacity: 0.6,
+ fontSize: 15,
+ opacity: 0.56,
flex: 1,
},
};
diff --git a/app/components/autocomplete/at_mention_item/index.js b/app/components/autocomplete/at_mention_item/index.js
index ce297025da..6fe8e84cc3 100644
--- a/app/components/autocomplete/at_mention_item/index.js
+++ b/app/components/autocomplete/at_mention_item/index.js
@@ -6,6 +6,7 @@ import {connect} from 'react-redux';
import {getCurrentUserId, getUser} from '@mm-redux/selectors/entities/users';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
+import {getConfig} from '@mm-redux/selectors/entities/general';
import AtMentionItem from './at_mention_item';
@@ -14,12 +15,13 @@ import {isGuest} from 'app/utils/users';
function mapStateToProps(state, ownProps) {
const user = getUser(state, ownProps.userId);
-
+ const config = getConfig(state);
return {
firstName: user.first_name,
lastName: user.last_name,
nickname: user.nickname,
username: user.username,
+ showFullName: config.ShowFullName,
isBot: Boolean(user.is_bot),
isGuest: isGuest(user),
theme: getTheme(state),
diff --git a/app/components/autocomplete/autocomplete.js b/app/components/autocomplete/autocomplete.js
index c05ca56a52..3b202cfc62 100644
--- a/app/components/autocomplete/autocomplete.js
+++ b/app/components/autocomplete/autocomplete.js
@@ -36,8 +36,9 @@ export default class Autocomplete extends PureComponent {
valueEvent: PropTypes.string,
cursorPositionEvent: PropTypes.string,
nestedScrollEnabled: PropTypes.bool,
- expandDown: PropTypes.bool,
onVisible: PropTypes.func,
+ offsetY: PropTypes.number,
+ onKeyboardOffsetChanged: PropTypes.func,
style: ViewPropTypes.style,
};
@@ -47,6 +48,8 @@ export default class Autocomplete extends PureComponent {
enableDateSuggestion: false,
nestedScrollEnabled: false,
onVisible: emptyFunction,
+ onKeyboardOffsetChanged: emptyFunction,
+ offsetY: 80,
};
static getDerivedStateFromProps(props, state) {
@@ -149,10 +152,12 @@ export default class Autocomplete extends PureComponent {
keyboardDidShow = (e) => {
const {height} = e.endCoordinates;
this.setState({keyboardOffset: height});
+ this.props.onKeyboardOffsetChanged(height);
};
keyboardDidHide = () => {
this.setState({keyboardOffset: 0});
+ this.props.onKeyboardOffsetChanged(0);
};
maxListHeight() {
@@ -166,42 +171,37 @@ export default class Autocomplete extends PureComponent {
offset = 90;
}
- maxHeight = this.props.deviceHeight - offset - this.state.keyboardOffset;
+ maxHeight = (this.props.deviceHeight / 2) - offset;
}
return maxHeight;
}
render() {
- const {theme, isSearch, expandDown} = this.props;
+ const {atMentionCount, channelMentionCount, emojiCount, commandCount, dateCount, cursorPosition, value} = this.state;
+ const {theme, isSearch, offsetY} = this.props;
const style = getStyleFromTheme(theme);
-
+ const maxListHeight = this.maxListHeight();
const wrapperStyles = [];
- const containerStyles = [];
+ const containerStyles = [style.borders];
+
+ if (Platform.OS === 'ios') {
+ wrapperStyles.push(style.shadow);
+ }
+
if (isSearch) {
- wrapperStyles.push(style.base, style.searchContainer);
- containerStyles.push(style.content);
+ wrapperStyles.push(style.base, style.searchContainer, {height: maxListHeight});
} else {
- const containerStyle = expandDown ? style.containerExpandDown : style.container;
+ const containerStyle = {bottom: offsetY};
containerStyles.push(style.base, containerStyle);
}
- // We always need to render something, but we only draw the borders when we have results to show
- const {atMentionCount, channelMentionCount, emojiCount, commandCount, dateCount, cursorPosition, value} = this.state;
- if (atMentionCount + channelMentionCount + emojiCount + commandCount + dateCount > 0) {
- if (this.props.isSearch) {
- wrapperStyles.push(style.bordersSearch);
- } else {
- containerStyles.push(style.borders);
- }
+ // Hide when there are no active autocompletes
+ if (atMentionCount + channelMentionCount + emojiCount + commandCount + dateCount === 0) {
+ wrapperStyles.push(style.hidden);
+ containerStyles.push(style.hidden);
}
- if (this.props.style) {
- containerStyles.push(this.props.style);
- }
-
- const maxListHeight = this.maxListHeight();
-
return (
{
return {
base: {
- left: 0,
- overflow: 'hidden',
+ left: 8,
position: 'absolute',
- right: 0,
+ right: 8,
},
borders: {
borderWidth: 1,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
- borderBottomWidth: 0,
+ overflow: 'hidden',
+ borderRadius: 4,
},
- bordersSearch: {
- borderWidth: 1,
- borderColor: changeOpacity(theme.centerChannelColor, 0.2),
- },
- container: {
- bottom: 0,
- },
- containerExpandDown: {
- top: 0,
- },
- content: {
- flex: 1,
+ hidden: {
+ display: 'none',
},
searchContainer: {
- flex: 1,
...Platform.select({
android: {
- top: 46,
+ top: 42,
},
ios: {
- top: 44,
+ top: 55,
},
}),
},
+ shadow: {
+ shadowColor: '#000',
+ shadowOpacity: 0.12,
+ shadowRadius: 8,
+ shadowOffset: {
+ width: 0,
+ height: 8,
+ },
+ },
};
});
diff --git a/app/components/autocomplete/autocomplete_divider/autocomplete_divider.js b/app/components/autocomplete/autocomplete_divider/autocomplete_divider.js
deleted file mode 100644
index e8ddcccc0b..0000000000
--- a/app/components/autocomplete/autocomplete_divider/autocomplete_divider.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 {View} from 'react-native';
-
-import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
-
-export default class AutocompleteDivider extends PureComponent {
- static propTypes = {
- theme: PropTypes.object.isRequired,
- };
-
- render() {
- const {theme} = this.props;
- const style = getStyleFromTheme(theme);
-
- return (
-
- );
- }
-}
-
-const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
- return {
- divider: {
- height: 1,
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
- },
- };
-});
diff --git a/app/components/autocomplete/autocomplete_divider/index.js b/app/components/autocomplete/autocomplete_divider/index.js
deleted file mode 100644
index 8e7799ef4f..0000000000
--- a/app/components/autocomplete/autocomplete_divider/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import {connect} from 'react-redux';
-
-import {getTheme} from '@mm-redux/selectors/entities/preferences';
-
-import AutocompleteDivider from './autocomplete_divider';
-
-function mapStateToProps(state) {
- return {
- theme: getTheme(state),
- };
-}
-
-export default connect(mapStateToProps)(AutocompleteDivider);
diff --git a/app/components/autocomplete/autocomplete_section_header.js b/app/components/autocomplete/autocomplete_section_header.js
index 0fb6f6d806..d86d057676 100644
--- a/app/components/autocomplete/autocomplete_section_header.js
+++ b/app/components/autocomplete/autocomplete_section_header.js
@@ -16,6 +16,7 @@ export default class AutocompleteSectionHeader extends PureComponent {
loading: PropTypes.bool,
theme: PropTypes.object.isRequired,
isLandscape: PropTypes.bool.isRequired,
+ isFirstSection: PropTypes.bool,
};
static defaultProps = {
@@ -23,12 +24,17 @@ export default class AutocompleteSectionHeader extends PureComponent {
};
render() {
- const {defaultMessage, id, loading, theme, isLandscape} = this.props;
+ const {defaultMessage, id, loading, theme, isLandscape, isFirstSection} = this.props;
const style = getStyleFromTheme(theme);
+ const sectionStyles = [style.section, padding(isLandscape)];
+
+ if (!isFirstSection) {
+ sectionStyles.push(style.borderTop);
+ }
return (
-
+
{
return {
- section: {
- justifyContent: 'center',
- paddingHorizontal: 8,
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
+ borderTop: {
borderTopWidth: 1,
borderTopColor: changeOpacity(theme.centerChannelColor, 0.2),
+ },
+ section: {
+ justifyContent: 'center',
+ position: 'relative',
+ top: -1,
flexDirection: 'row',
},
sectionText: {
fontSize: 12,
- color: changeOpacity(theme.centerChannelColor, 0.7),
- paddingVertical: 7,
+ fontWeight: '600',
+ textTransform: 'uppercase',
+ color: changeOpacity(theme.centerChannelColor, 0.56),
+ paddingTop: 16,
+ paddingBottom: 8,
+ paddingHorizontal: 16,
flex: 1,
},
sectionWrapper: {
diff --git a/app/components/autocomplete/channel_mention/channel_mention.js b/app/components/autocomplete/channel_mention/channel_mention.js
index e72509682a..8a9ab874af 100644
--- a/app/components/autocomplete/channel_mention/channel_mention.js
+++ b/app/components/autocomplete/channel_mention/channel_mention.js
@@ -184,6 +184,7 @@ export default class ChannelMention extends PureComponent {
};
renderSectionHeader = ({section}) => {
+ const isFirstSection = section.id === this.state.sections[0].id;
return (
);
};
@@ -235,6 +237,7 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
listView: {
backgroundColor: theme.centerChannelBg,
+ borderRadius: 4,
},
};
});
diff --git a/app/components/autocomplete/channel_mention_item/channel_mention_item.js b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
index 4619f5ff49..d3f9731e6e 100644
--- a/app/components/autocomplete/channel_mention_item/channel_mention_item.js
+++ b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
@@ -5,14 +5,15 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Text,
+ View,
} from 'react-native';
+import VectorIcon from 'app/components/vector_icon.js';
import {General} from '@mm-redux/constants';
-import AutocompleteDivider from 'app/components/autocomplete/autocomplete_divider';
import {BotTag, GuestTag} from 'app/components/tag';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
-import {makeStyleSheetFromTheme} from 'app/utils/theme';
+import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
export default class ChannelMentionItem extends PureComponent {
static propTypes = {
@@ -49,8 +50,12 @@ export default class ChannelMentionItem extends PureComponent {
} = this.props;
const style = getStyleFromTheme(theme);
-
+ let iconName = 'public';
let component;
+ if (type === General.PRIVATE_CHANNEL) {
+ iconName = 'private';
+ }
+
if (type === General.DM_CHANNEL || type === General.GM_CHANNEL) {
if (!displayName) {
return null;
@@ -79,11 +84,19 @@ export default class ChannelMentionItem extends PureComponent {
- {displayName}
- {` (~${name})`}
+
+
+ {displayName}
+ {` ~${name}`}
+
);
}
@@ -91,7 +104,6 @@ export default class ChannelMentionItem extends PureComponent {
return (
{component}
-
);
}
@@ -99,19 +111,26 @@ export default class ChannelMentionItem extends PureComponent {
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
+ icon: {
+ fontSize: 18,
+ marginRight: 11,
+ color: theme.centerChannelColor,
+ opacity: 0.56,
+ },
row: {
- padding: 8,
+ paddingHorizontal: 16,
+ height: 40,
flexDirection: 'row',
alignItems: 'center',
- backgroundColor: theme.centerChannelBg,
},
rowDisplayName: {
- fontSize: 13,
+ fontSize: 15,
color: theme.centerChannelColor,
},
rowName: {
+ fontSize: 15,
color: theme.centerChannelColor,
- opacity: 0.6,
+ opacity: 0.56,
},
};
});
diff --git a/app/components/autocomplete/date_suggestion/date_suggestion.js b/app/components/autocomplete/date_suggestion/date_suggestion.js
index e7b56c5b7c..925151fad8 100644
--- a/app/components/autocomplete/date_suggestion/date_suggestion.js
+++ b/app/components/autocomplete/date_suggestion/date_suggestion.js
@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
-import {Dimensions, Platform, StyleSheet} from 'react-native';
+import {Dimensions, Platform, View} from 'react-native';
import PropTypes from 'prop-types';
import {CalendarList, LocaleConfig} from 'react-native-calendars';
import {intlShape} from 'react-intl';
@@ -10,7 +10,7 @@ import {intlShape} from 'react-intl';
import {memoizeResult} from '@mm-redux/utils/helpers';
import {DATE_MENTION_SEARCH_REGEX, ALL_SEARCH_FLAGS_REGEX} from 'app/constants/autocomplete';
-import {changeOpacity} from 'app/utils/theme';
+import {makeStyleSheetFromTheme, changeOpacity} from '@utils/theme';
export default class DateSuggestion extends PureComponent {
static propTypes = {
@@ -37,6 +37,7 @@ export default class DateSuggestion extends PureComponent {
this.state = {
mentionComplete: false,
+ active: false,
sections: [],
};
}
@@ -45,18 +46,37 @@ export default class DateSuggestion extends PureComponent {
this.setCalendarLocale();
}
+ onLayout = (e) => {
+ this.setState({calendarWidth: e.nativeEvent.layout.width});
+ };
+
componentDidUpdate(prevProps) {
- const {locale, matchTerm} = this.props;
+ const {locale, matchTerm, enableDateSuggestion} = this.props;
+ const {mentionComplete} = this.state;
if ((matchTerm !== prevProps.matchTerm && matchTerm === null) || this.state.mentionComplete) {
this.resetComponent();
}
+ if (matchTerm === null || mentionComplete || !enableDateSuggestion) {
+ this.setCalendarActive(false);
+ return;
+ }
+
+ if (matchTerm !== null) {
+ this.props.onResultCountChange(1);
+ this.setCalendarActive(true);
+ }
+
if (locale !== prevProps.locale) {
this.setCalendarLocale();
}
}
+ setCalendarActive = (active) => {
+ this.setState({active});
+ }
+
completeMention = (day) => {
const mention = day.dateString;
const {cursorPosition, onChangeText, value} = this.props;
@@ -118,10 +138,11 @@ export default class DateSuggestion extends PureComponent {
};
render() {
- const {mentionComplete} = this.state;
- const {matchTerm, enableDateSuggestion, theme} = this.props;
+ const {active, calendarWidth} = this.state;
+ const {theme} = this.props;
+ const styles = getStyleFromTheme(theme);
- if (matchTerm === null || mentionComplete || !enableDateSuggestion) {
+ if (!active) {
// If we are not in an active state or the mention has been completed return null so nothing is rendered
// other components are not blocked.
return null;
@@ -131,22 +152,29 @@ export default class DateSuggestion extends PureComponent {
const calendarStyle = calendarTheme(theme);
return (
-
+ >
+ {Boolean(calendarWidth) &&
+
+ }
+
);
}
}
@@ -197,9 +225,13 @@ const calendarTheme = memoizeResult((theme) => ({
},
}));
-const styles = StyleSheet.create({
- calList: {
- height: 1700,
- paddingTop: 5,
- },
+const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
+ return {
+ calList: {
+ paddingTop: 5,
+ width: '100%',
+ borderRadius: 4,
+ backgroundColor: theme.centerChannelBg,
+ },
+ };
});
diff --git a/app/components/autocomplete/emoji_suggestion/__snapshots__/emoji_suggestion.test.js.snap b/app/components/autocomplete/emoji_suggestion/__snapshots__/emoji_suggestion.test.js.snap
index 81e7c8d8d0..06b6ff3db3 100644
--- a/app/components/autocomplete/emoji_suggestion/__snapshots__/emoji_suggestion.test.js.snap
+++ b/app/components/autocomplete/emoji_suggestion/__snapshots__/emoji_suggestion.test.js.snap
@@ -4,7 +4,6 @@ exports[`components/autocomplete/emoji_suggestion should match snapshot 1`] = `n
exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
{
const style = getStyleFromTheme(this.props.theme);
-
+ const completeSuggestion = () => this.completeSuggestion(item);
return (
this.completeSuggestion(item)}
- style={style.row}
- type={'opacity'}
+ onPress={completeSuggestion}
+ underlayColor={changeOpacity(this.props.theme.buttonBg, 0.08)}
+ type={'native'}
>
-
-
+
+
+
+
+ {`:${item}:`}
- {`:${item}:`}
);
};
@@ -199,12 +200,14 @@ export default class EmojiSuggestion extends PureComponent {
return values;
}, []);
const data = results.sort(sorter);
+ this.props.onResultCountChange(data.length);
this.setState({
active: data.length > 0,
dataSource: data,
});
}, 100);
} else {
+ this.props.onResultCountChange(emojis.length);
this.setState({
active: emojis.length > 0,
dataSource: emojis.sort(sorter),
@@ -229,7 +232,6 @@ export default class EmojiSuggestion extends PureComponent {
data={this.state.dataSource}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
- ItemSeparatorComponent={AutocompleteDivider}
pageSize={10}
initialListSize={10}
nestedScrollEnabled={nestedScrollEnabled}
@@ -244,7 +246,7 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
marginRight: 5,
},
emojiName: {
- fontSize: 13,
+ fontSize: 15,
color: theme.centerChannelColor,
},
emojiText: {
@@ -252,14 +254,17 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
fontWeight: 'bold',
},
listView: {
+ paddingTop: 16,
backgroundColor: theme.centerChannelBg,
+ borderRadius: 4,
},
row: {
- height: 40,
flexDirection: 'row',
alignItems: 'center',
- paddingHorizontal: 8,
- backgroundColor: theme.centerChannelBg,
+ overflow: 'hidden',
+ paddingBottom: 8,
+ paddingHorizontal: 16,
+ height: 40,
},
};
});
diff --git a/app/components/autocomplete/slash_suggestion/slash_suggestion.js b/app/components/autocomplete/slash_suggestion/slash_suggestion.js
index 91a23780f6..de79bd61ea 100644
--- a/app/components/autocomplete/slash_suggestion/slash_suggestion.js
+++ b/app/components/autocomplete/slash_suggestion/slash_suggestion.js
@@ -8,7 +8,6 @@ import {
Platform,
} from 'react-native';
-import AutocompleteDivider from 'app/components/autocomplete/autocomplete_divider';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
import SlashSuggestionItem from './slash_suggestion_item';
@@ -211,7 +210,6 @@ export default class SlashSuggestion extends PureComponent {
data={this.state.dataSource}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
- ItemSeparatorComponent={AutocompleteDivider}
pageSize={10}
initialListSize={10}
nestedScrollEnabled={nestedScrollEnabled}
@@ -225,6 +223,8 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
listView: {
flex: 1,
backgroundColor: theme.centerChannelBg,
+ paddingTop: 8,
+ borderRadius: 4,
},
};
});
diff --git a/app/components/autocomplete/slash_suggestion/slash_suggestion_item.js b/app/components/autocomplete/slash_suggestion/slash_suggestion_item.js
index 00adc7ad8d..98d3a466df 100644
--- a/app/components/autocomplete/slash_suggestion/slash_suggestion_item.js
+++ b/app/components/autocomplete/slash_suggestion/slash_suggestion_item.js
@@ -3,11 +3,12 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
-import {Text} from 'react-native';
+import {Image, Text, View} from 'react-native';
-import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
-import TouchableWithFeedback from 'app/components/touchable_with_feedback';
-import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+import {paddingHorizontal as padding} from '@components/safe_area_view/iphone_x_spacing';
+import TouchableWithFeedback from '@components/touchable_with_feedback';
+import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
+import slashIcon from '@assets/images/autocomplete/slash_command.png';
export default class SlashSuggestionItem extends PureComponent {
static propTypes = {
@@ -39,11 +40,30 @@ export default class SlashSuggestionItem extends PureComponent {
return (
- {`${suggestion} ${hint}`}
- {description}
+
+
+
+
+
+ {`${suggestion.substring(1)} ${hint}`}
+
+ {description}
+
+
+
);
}
@@ -51,32 +71,38 @@ export default class SlashSuggestionItem extends PureComponent {
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
- row: {
- paddingVertical: 8,
+ icon: {
+ fontSize: 24,
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.08),
+ width: 35,
+ height: 35,
+ marginRight: 12,
+ borderRadius: 4,
justifyContent: 'center',
- paddingHorizontal: 8,
- backgroundColor: theme.centerChannelBg,
- borderLeftWidth: 1,
- borderLeftColor: changeOpacity(theme.centerChannelColor, 0.2),
- borderRightWidth: 1,
- borderRightColor: changeOpacity(theme.centerChannelColor, 0.2),
+ alignItems: 'center',
+ marginTop: 8,
},
- rowDisplayName: {
- fontSize: 13,
- color: theme.centerChannelColor,
+ iconColor: {
+ tintColor: theme.centerChannelColor,
},
- rowName: {
- color: theme.centerChannelColor,
- opacity: 0.6,
+ container: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingBottom: 8,
+ paddingHorizontal: 16,
+ overflow: 'hidden',
+ },
+ suggestionContainer: {
+ flex: 1,
},
suggestionDescription: {
- fontSize: 11,
- color: changeOpacity(theme.centerChannelColor, 0.6),
+ fontSize: 12,
+ color: changeOpacity(theme.centerChannelColor, 0.56),
},
suggestionName: {
- fontSize: 13,
+ fontSize: 15,
color: theme.centerChannelColor,
- marginBottom: 5,
+ marginBottom: 4,
},
};
});
diff --git a/app/components/autocomplete/special_mention_item.js b/app/components/autocomplete/special_mention_item.js
index 090afa6bf9..4054b49439 100644
--- a/app/components/autocomplete/special_mention_item.js
+++ b/app/components/autocomplete/special_mention_item.js
@@ -42,25 +42,27 @@ export default class SpecialMentionItem extends PureComponent {
return (
-
-
+
+
+
+
+
+ {`@${completeHandle}`}
+ {' - '}
+
+
-
- {`@${completeHandle}`}
- {' - '}
-
-
);
}
@@ -68,10 +70,11 @@ export default class SpecialMentionItem extends PureComponent {
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
row: {
+ height: 40,
paddingVertical: 8,
+ paddingHorizontal: 9,
flexDirection: 'row',
alignItems: 'center',
- backgroundColor: theme.centerChannelBg,
},
rowPicture: {
marginHorizontal: 8,
@@ -81,10 +84,10 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
},
rowIcon: {
color: changeOpacity(theme.centerChannelColor, 0.7),
- fontSize: 14,
+ fontSize: 18,
},
rowUsername: {
- fontSize: 13,
+ fontSize: 15,
color: theme.centerChannelColor,
},
rowFullname: {
diff --git a/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap b/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
index 72f9370698..3b312dc24c 100644
--- a/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
+++ b/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
@@ -309,18 +309,28 @@ exports[`EditChannelInfo should match snapshot 1`] = `
-
-
+
`;
diff --git a/app/components/edit_channel_info/edit_channel_info.js b/app/components/edit_channel_info/edit_channel_info.js
index edbecc2f72..4ea8a9ccfd 100644
--- a/app/components/edit_channel_info/edit_channel_info.js
+++ b/app/components/edit_channel_info/edit_channel_info.js
@@ -9,11 +9,10 @@ import {
View,
} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scrollview';
-import {KeyboardTrackingView} from 'react-native-keyboard-tracking-view';
import {General} from '@mm-redux/constants';
-import Autocomplete from 'app/components/autocomplete';
+import Autocomplete, {AUTOCOMPLETE_MAX_HEIGHT} from 'app/components/autocomplete';
import ErrorText from 'app/components/error_text';
import FormattedText from 'app/components/formatted_text';
import Loading from 'app/components/loading';
@@ -71,6 +70,7 @@ export default class EditChannelInfo extends PureComponent {
this.state = {
keyboardVisible: false,
+ keyboardPosition: 0,
};
}
@@ -174,6 +174,10 @@ export default class EditChannelInfo extends PureComponent {
this.setState({keyboardVisible: false});
}
+ onKeyboardOffsetChanged = (keyboardPosition) => {
+ this.setState({keyboardPosition});
+ }
+
onHeaderFocus = () => {
if (this.state.keyboardVisible) {
this.scrollHeaderToTop();
@@ -201,8 +205,13 @@ export default class EditChannelInfo extends PureComponent {
error,
saving,
} = this.props;
- const {keyboardVisible} = this.state;
-
+ const {keyboardVisible, keyboardPosition} = this.state;
+ const bottomStyle = {
+ bottom: Platform.select({
+ ios: keyboardPosition,
+ android: 0,
+ }),
+ };
const style = getStyleSheet(theme);
const displayHeaderOnly = channelType === General.DM_CHANNEL ||
@@ -354,16 +363,18 @@ export default class EditChannelInfo extends PureComponent {
-
+
-
+
);
}
@@ -375,6 +386,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
position: undefined,
},
autocompleteContainer: {
+ position: 'absolute',
+ width: '100%',
+ flex: 1,
justifyContent: 'flex-end',
},
container: {
diff --git a/app/components/post_draft/draft_input/draft_input.js b/app/components/post_draft/draft_input/draft_input.js
index 18481386c3..3836b22dcd 100644
--- a/app/components/post_draft/draft_input/draft_input.js
+++ b/app/components/post_draft/draft_input/draft_input.js
@@ -415,16 +415,6 @@ export default class DraftInput extends PureComponent {
theme={theme}
registerTypingAnimation={registerTypingAnimation}
/>
- {Platform.OS === 'android' &&
-
- }
+ {Platform.OS === 'android' &&
+
+ }
>
);
}
@@ -513,4 +513,4 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
borderTopColor: changeOpacity(theme.centerChannelColor, 0.20),
},
};
-});
\ No newline at end of file
+});
diff --git a/app/screens/channel/channel.ios.js b/app/screens/channel/channel.ios.js
index 31ad4c01fc..40089f8a7f 100644
--- a/app/screens/channel/channel.ios.js
+++ b/app/screens/channel/channel.ios.js
@@ -64,15 +64,6 @@ export default class ChannelIOS extends ChannelBase {
updateNativeScrollView={this.updateNativeScrollView}
registerTypingAnimation={this.registerTypingAnimation}
/>
-
-
-
{LocalConfig.EnableMobileClientUpgrade && }
>
);
@@ -102,6 +93,15 @@ export default class ChannelIOS extends ChannelBase {
valueEvent={CHANNEL_POST_TEXTBOX_VALUE_CHANGE}
/>
}
+
+
+
>
);
diff --git a/app/screens/edit_post/__snapshots__/edit_post.test.js.snap b/app/screens/edit_post/__snapshots__/edit_post.test.js.snap
index 51ce60621e..c0d001ee22 100644
--- a/app/screens/edit_post/__snapshots__/edit_post.test.js.snap
+++ b/app/screens/edit_post/__snapshots__/edit_post.test.js.snap
@@ -87,6 +87,7 @@ exports[`EditPost should match snapshot 1`] = `
cursorPosition={0}
maxHeight={200}
nestedScrollEnabled={true}
+ offsetY={8}
onChangeText={[Function]}
onVisible={[Function]}
style={
diff --git a/app/screens/edit_post/edit_post.js b/app/screens/edit_post/edit_post.js
index 6974514864..6c7687ea81 100644
--- a/app/screens/edit_post/edit_post.js
+++ b/app/screens/edit_post/edit_post.js
@@ -281,6 +281,7 @@ export default class EditPost extends PureComponent {
value={message}
nestedScrollEnabled={true}
onVisible={this.onAutocompleteVisible}
+ offsetY={8}
style={style.autocomplete}
/>
diff --git a/app/screens/thread/__snapshots__/thread.ios.test.js.snap b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
index 1ae9d69f86..39823cb2ba 100644
--- a/app/screens/thread/__snapshots__/thread.ios.test.js.snap
+++ b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
@@ -48,18 +48,6 @@ exports[`thread should match snapshot, has root post 1`] = `
scrollViewNativeID="threadPostList"
/>
-
-
-
+
+
+
`;
@@ -96,6 +96,18 @@ exports[`thread should match snapshot, no root post, loading 1`] = `
style={Object {}}
/>
+
+
+
`;
@@ -166,5 +178,17 @@ exports[`thread should match snapshot, render footer 3`] = `
style={Object {}}
/>
+
+
+
`;
diff --git a/app/screens/thread/thread.ios.js b/app/screens/thread/thread.ios.js
index 82b4974876..f683134134 100644
--- a/app/screens/thread/thread.ios.js
+++ b/app/screens/thread/thread.ios.js
@@ -56,16 +56,6 @@ export default class ThreadIOS extends ThreadBase {
scrollViewNativeID={SCROLLVIEW_NATIVE_ID}
/>
-
-
-
>
);
@@ -101,6 +91,16 @@ export default class ThreadIOS extends ThreadBase {
{content}
{postDraft}
+
+
+
);
}
diff --git a/assets/base/images/autocomplete/slash_command.png b/assets/base/images/autocomplete/slash_command.png
new file mode 100644
index 0000000000..a6111db5b4
Binary files /dev/null and b/assets/base/images/autocomplete/slash_command.png differ
diff --git a/assets/base/images/autocomplete/slash_command@2x.png b/assets/base/images/autocomplete/slash_command@2x.png
new file mode 100644
index 0000000000..fc26022205
Binary files /dev/null and b/assets/base/images/autocomplete/slash_command@2x.png differ
diff --git a/assets/base/images/autocomplete/slash_command@3x.png b/assets/base/images/autocomplete/slash_command@3x.png
new file mode 100644
index 0000000000..a0252a593f
Binary files /dev/null and b/assets/base/images/autocomplete/slash_command@3x.png differ