Remove ChannelPeek (#3897)
Introduced large number of unnecessary re-renders when opening channels, and ideally should not be a part of the channel switching/opening code path. Although this was discovered while trying to investigate an [Android-specific issue](https://mattermost.atlassian.net/browse/MM-22253), this extra code path made it difficult to see what Android is potentially doing differently than iOS. Functionality originally introduced in #1203. Conversation for removal is [here](https://community.mattermost.com/core/pl/hfcogf6pr7rw8k3ryq14c69c7e)
This commit is contained in:
parent
6806337b23
commit
b7970c3a34
13 changed files with 709 additions and 918 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -4,13 +4,11 @@
|
|||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Animated,
|
||||
TouchableHighlight,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import {General} from 'mattermost-redux/constants';
|
||||
import {paddingLeft as padding} from 'app/components/safe_area_view/iphone_x_spacing';
|
||||
|
|
@ -19,8 +17,6 @@ import ChannelIcon from 'app/components/channel_icon';
|
|||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
const {View: AnimatedView} = Animated;
|
||||
|
||||
export default class ChannelItem extends PureComponent {
|
||||
static propTypes = {
|
||||
channelId: PropTypes.string.isRequired,
|
||||
|
|
@ -40,7 +36,6 @@ export default class ChannelItem extends PureComponent {
|
|||
unreadMsgs: PropTypes.number.isRequired,
|
||||
isSearchResult: PropTypes.bool,
|
||||
isBot: PropTypes.bool.isRequired,
|
||||
previewChannel: PropTypes.func,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -61,27 +56,6 @@ export default class ChannelItem extends PureComponent {
|
|||
});
|
||||
});
|
||||
|
||||
onPreview = ({reactTag}) => {
|
||||
const {channelId, previewChannel} = this.props;
|
||||
if (previewChannel) {
|
||||
const {intl} = this.context;
|
||||
const passProps = {
|
||||
channelId,
|
||||
};
|
||||
const options = {
|
||||
preview: {
|
||||
reactTag,
|
||||
actions: [{
|
||||
id: 'action-mark-as-read',
|
||||
title: intl.formatMessage({id: 'mobile.channel.markAsRead', defaultMessage: 'Mark As Read'}),
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
previewChannel(passProps, options);
|
||||
}
|
||||
};
|
||||
|
||||
showChannelAsUnread = () => {
|
||||
return this.props.mentions > 0 || (this.props.unreadMsgs > 0 && this.props.showUnreadForMsgs);
|
||||
};
|
||||
|
|
@ -192,29 +166,25 @@ export default class ChannelItem extends PureComponent {
|
|||
);
|
||||
|
||||
return (
|
||||
<AnimatedView>
|
||||
<Navigation.TouchablePreview
|
||||
touchableComponent={TouchableHighlight}
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
|
||||
onPress={this.onPress}
|
||||
onPressIn={this.onPreview}
|
||||
>
|
||||
<View style={[style.container, mutedStyle, padding(isLandscape)]}>
|
||||
{extraBorder}
|
||||
<View style={[style.item, extraItemStyle]}>
|
||||
{icon}
|
||||
<Text
|
||||
style={[style.text, extraTextStyle]}
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
>
|
||||
{channelDisplayName}
|
||||
</Text>
|
||||
{badge}
|
||||
</View>
|
||||
<TouchableHighlight
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
|
||||
onPress={this.onPress}
|
||||
>
|
||||
<View style={[style.container, mutedStyle, padding(isLandscape)]}>
|
||||
{extraBorder}
|
||||
<View style={[style.item, extraItemStyle]}>
|
||||
{icon}
|
||||
<Text
|
||||
style={[style.text, extraTextStyle]}
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
>
|
||||
{channelDisplayName}
|
||||
</Text>
|
||||
{badge}
|
||||
</View>
|
||||
</Navigation.TouchablePreview>
|
||||
</AnimatedView>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import {TouchableHighlight} from 'react-native';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ describe('ChannelItem', () => {
|
|||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
|
||||
wrapper.find(Navigation.TouchablePreview).simulate('press');
|
||||
wrapper.find(TouchableHighlight).simulate('press');
|
||||
jest.runAllTimers();
|
||||
|
||||
const expectedChannelParams = {id: baseProps.channelId, display_name: baseProps.displayName, fake: channel.fake, type: channel.type};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ export default class ChannelsList extends PureComponent {
|
|||
onShowTeams: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
drawerOpened: PropTypes.bool,
|
||||
previewChannel: PropTypes.func,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -98,7 +97,6 @@ export default class ChannelsList extends PureComponent {
|
|||
const {
|
||||
onShowTeams,
|
||||
theme,
|
||||
previewChannel,
|
||||
isLandscape,
|
||||
} = this.props;
|
||||
|
||||
|
|
@ -112,7 +110,6 @@ export default class ChannelsList extends PureComponent {
|
|||
onSelectChannel={this.onSelectChannel}
|
||||
styles={styles}
|
||||
term={term}
|
||||
previewChannel={previewChannel}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
|
@ -120,7 +117,6 @@ export default class ChannelsList extends PureComponent {
|
|||
<List
|
||||
onSelectChannel={this.onSelectChannel}
|
||||
styles={styles}
|
||||
previewChannel={previewChannel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ class FilteredList extends Component {
|
|||
styles: PropTypes.object.isRequired,
|
||||
term: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
previewChannel: PropTypes.func,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -350,7 +349,6 @@ class FilteredList extends Component {
|
|||
isUnread={item.isUnread}
|
||||
mentions={0}
|
||||
onSelectChannel={this.onSelectChannel}
|
||||
previewChannel={this.props.previewChannel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ export default class List extends PureComponent {
|
|||
styles: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
orderedChannelIds: PropTypes.array.isRequired,
|
||||
previewChannel: PropTypes.func,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -309,7 +308,7 @@ export default class List extends PureComponent {
|
|||
};
|
||||
|
||||
renderItem = ({item}) => {
|
||||
const {favoriteChannelIds, unreadChannelIds, previewChannel} = this.props;
|
||||
const {favoriteChannelIds, unreadChannelIds} = this.props;
|
||||
|
||||
return (
|
||||
<ChannelItem
|
||||
|
|
@ -317,7 +316,6 @@ export default class List extends PureComponent {
|
|||
isUnread={unreadChannelIds.includes(item)}
|
||||
isFavorite={favoriteChannelIds.includes(item)}
|
||||
onSelectChannel={this.onSelectChannel}
|
||||
previewChannel={previewChannel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ export default class ChannelSidebar extends Component {
|
|||
currentUserId: PropTypes.string.isRequired,
|
||||
teamsCount: PropTypes.number.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
previewChannel: PropTypes.func,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
|
|
@ -318,7 +317,6 @@ export default class ChannelSidebar extends Component {
|
|||
const {
|
||||
teamsCount,
|
||||
theme,
|
||||
previewChannel,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
|
|
@ -372,7 +370,6 @@ export default class ChannelSidebar extends Component {
|
|||
onSearchEnds={this.onSearchEnds}
|
||||
theme={theme}
|
||||
drawerOpened={this.state.drawerOpened}
|
||||
previewChannel={previewChannel}
|
||||
/>
|
||||
</View>,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import PostTextbox from 'app/components/post_textbox';
|
|||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import {DeviceTypes} from 'app/constants';
|
||||
import {peek} from 'app/actions/navigation';
|
||||
|
||||
import LocalConfig from 'assets/config';
|
||||
|
||||
|
|
@ -25,14 +24,6 @@ const CHANNEL_POST_TEXTBOX_CURSOR_CHANGE = 'onChannelTextBoxCursorChange';
|
|||
const CHANNEL_POST_TEXTBOX_VALUE_CHANGE = 'onChannelTextBoxValueChange';
|
||||
|
||||
export default class ChannelIOS extends ChannelBase {
|
||||
previewChannel = (passProps, options) => {
|
||||
const screen = 'ChannelPeek';
|
||||
|
||||
peek(screen, passProps, options);
|
||||
};
|
||||
|
||||
optionalProps = {previewChannel: this.previewChannel};
|
||||
|
||||
render() {
|
||||
const {height} = Dimensions.get('window');
|
||||
const {currentChannelId} = this.props;
|
||||
|
|
@ -84,6 +75,6 @@ export default class ChannelIOS extends ChannelBase {
|
|||
</React.Fragment>
|
||||
);
|
||||
|
||||
return this.renderChannel(drawerContent, this.optionalProps);
|
||||
return this.renderChannel(drawerContent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ export default class ChannelBase extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
renderChannel(drawerContent, optionalProps = {}) {
|
||||
renderChannel(drawerContent) {
|
||||
const {
|
||||
channelsRequestFailed,
|
||||
currentChannelId,
|
||||
|
|
@ -318,7 +318,6 @@ export default class ChannelBase extends PureComponent {
|
|||
<MainSidebar
|
||||
ref={this.channelSidebarRef}
|
||||
blurPostTextBox={this.blurPostTextBox}
|
||||
{...optionalProps}
|
||||
>
|
||||
<SettingsSidebar
|
||||
ref={this.settingsSidebarRef}
|
||||
|
|
|
|||
|
|
@ -1,103 +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 {Platform, View} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import {getLastPostIndex} from 'mattermost-redux/utils/post_list';
|
||||
|
||||
import PostList from 'app/components/post_list';
|
||||
import {makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
export default class ChannelPeek extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
loadPostsIfNecessaryWithRetry: PropTypes.func.isRequired,
|
||||
markChannelViewedAndRead: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
channelId: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string,
|
||||
lastViewedAt: PropTypes.number,
|
||||
postIds: PropTypes.array,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
postVisibility: 15,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
props.actions.loadPostsIfNecessaryWithRetry(props.channelId);
|
||||
this.state = {
|
||||
visiblePostIds: this.getVisiblePostIds(props),
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.navigationEventListener = Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {postIds: nextPostIds} = nextProps;
|
||||
|
||||
let visiblePostIds = this.state.visiblePostIds;
|
||||
|
||||
if (nextPostIds !== this.props.postIds) {
|
||||
visiblePostIds = this.getVisiblePostIds(nextProps);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
visiblePostIds,
|
||||
});
|
||||
}
|
||||
|
||||
navigationButtonPressed({buttonId}) {
|
||||
if (buttonId === 'action-mark-as-read') {
|
||||
const {actions, channelId} = this.props;
|
||||
actions.markChannelViewedAndRead(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
getVisiblePostIds = (props) => {
|
||||
return props.postIds?.slice(0, 15) || [];
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
channelId,
|
||||
currentUserId,
|
||||
lastViewedAt,
|
||||
theme,
|
||||
} = this.props;
|
||||
|
||||
const {visiblePostIds} = this.state;
|
||||
const style = getStyle(theme);
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<PostList
|
||||
postIds={visiblePostIds}
|
||||
lastPostIndex={Platform.OS === 'android' ? getLastPostIndex(visiblePostIds) : -1}
|
||||
renderReplies={true}
|
||||
indicateNewMessages={true}
|
||||
currentUserId={currentUserId}
|
||||
lastViewedAt={lastViewedAt}
|
||||
channelId={channelId}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyle = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getPostIdsInChannel} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getMyChannelMember} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {loadPostsIfNecessaryWithRetry, markChannelViewedAndRead} from 'app/actions/views/channel';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import ChannelPeek from './channel_peek';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const channelId = ownProps.channelId;
|
||||
const myMember = getMyChannelMember(state, channelId);
|
||||
|
||||
return {
|
||||
channelId,
|
||||
currentUserId: getCurrentUserId(state),
|
||||
postIds: getPostIdsInChannel(state, channelId),
|
||||
lastViewedAt: myMember && myMember.last_viewed_at,
|
||||
theme: getTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
loadPostsIfNecessaryWithRetry,
|
||||
markChannelViewedAndRead,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChannelPeek);
|
||||
|
|
@ -26,7 +26,6 @@ export function registerScreens(store, Provider) {
|
|||
Navigation.registerComponent('ChannelAddMembers', () => wrapper(require('app/screens/channel_add_members').default), () => require('app/screens/channel_add_members').default);
|
||||
Navigation.registerComponent('ChannelInfo', () => wrapper(require('app/screens/channel_info').default), () => require('app/screens/channel_info').default);
|
||||
Navigation.registerComponent('ChannelMembers', () => wrapper(require('app/screens/channel_members').default), () => require('app/screens/channel_members').default);
|
||||
Navigation.registerComponent('ChannelPeek', () => wrapper(require('app/screens/channel_peek').default), () => require('app/screens/channel_peek').default);
|
||||
Navigation.registerComponent('ClientUpgrade', () => wrapper(require('app/screens/client_upgrade').default), () => require('app/screens/client_upgrade').default);
|
||||
Navigation.registerComponent('ClockDisplaySettings', () => wrapper(require('app/screens/settings/clock_display').default), () => require('app/screens/settings/clock_display').default);
|
||||
Navigation.registerComponent('Code', () => wrapper(require('app/screens/code').default), () => require('app/screens/code').default);
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@
|
|||
"mobile.channel_list.not_member": "NOT A MEMBER",
|
||||
"mobile.channel_list.unreads": "UNREADS",
|
||||
"mobile.channel_members.add_members_alert": "You must select at least one member to add to the channel.",
|
||||
"mobile.channel.markAsRead": "Mark As Read",
|
||||
"mobile.client_upgrade": "Update App",
|
||||
"mobile.client_upgrade.can_upgrade_subtitle": "A new version is available for download.",
|
||||
"mobile.client_upgrade.can_upgrade_title": "Update Available",
|
||||
|
|
|
|||
Loading…
Reference in a new issue