From 49d9e5ef73596750ea37779fba50b640fdc0716f Mon Sep 17 00:00:00 2001 From: Mattermost Build Date: Mon, 2 Dec 2019 10:52:14 +0100 Subject: [PATCH] Automated cherry pick of #3635 (#3641) * MM-20758 MM-20762 Fix archived channels in more channels screen * Separate archived and public channels --- app/actions/views/channel.js | 22 ----- .../__snapshots__/index.test.js.snap | 10 --- app/components/custom_list/index.js | 23 +++-- app/components/custom_list/index.test.js | 1 + .../channel_members.test.js.snap | 1 + .../__snapshots__/more_channels.test.js.snap | 1 + app/screens/more_channels/index.js | 13 +-- app/screens/more_channels/more_channels.js | 84 ++++++++++++++----- .../more_channels/more_channels.test.js | 5 +- .../__snapshots__/select_team.test.js.snap | 1 + .../selector_screen.test.js.snap | 6 ++ 11 files changed, 99 insertions(+), 68 deletions(-) diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index fed9f0c7d..4d89dcd77 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -14,8 +14,6 @@ import { leaveChannel as serviceLeaveChannel, selectChannel, getChannelStats, - getChannels, - getArchivedChannels, } from 'mattermost-redux/actions/channels'; import { getPosts, @@ -75,26 +73,6 @@ export function loadChannelsByTeamName(teamName) { }; } -export function loadPublicAndArchivedChannels(teamId, publicPage, archivedPage, perPage, shouldLoadArchivedChannels) { - return async (dispatch) => { - return dispatch(getChannels( - teamId, - publicPage, - perPage - )).then(async (publicChannels) => { - if (shouldLoadArchivedChannels) { - const archivedChannels = await dispatch(getArchivedChannels( - teamId, - archivedPage, - perPage - )); - return archivedChannels; - } - return publicChannels; - }); - }; -} - export function loadProfilesAndTeamMembersForDMSidebar(teamId) { return async (dispatch, getState) => { const state = getState(); diff --git a/app/components/custom_list/__snapshots__/index.test.js.snap b/app/components/custom_list/__snapshots__/index.test.js.snap index e205d5f3e..38087a1d3 100644 --- a/app/components/custom_list/__snapshots__/index.test.js.snap +++ b/app/components/custom_list/__snapshots__/index.test.js.snap @@ -31,16 +31,6 @@ exports[`CustomList should match snapshot with FlatList 1`] = ` onEndReachedThreshold={2} onLayout={[Function]} onScroll={[Function]} - refreshControl={ - - } removeClippedSubviews={true} renderItem={[Function]} scrollEventThrottle={60} diff --git a/app/components/custom_list/index.js b/app/components/custom_list/index.js index 5b2acf0bb..33db287a5 100644 --- a/app/components/custom_list/index.js +++ b/app/components/custom_list/index.js @@ -18,6 +18,7 @@ export default class CustomList extends PureComponent { static propTypes = { data: PropTypes.array.isRequired, extraData: PropTypes.any, + canRefresh: PropTypes.bool, listType: PropTypes.oneOf([FLATLIST, SECTIONLIST]), loading: PropTypes.bool, loadingComponent: PropTypes.element, @@ -35,10 +36,11 @@ export default class CustomList extends PureComponent { }; static defaultProps = { + canRefresh: true, + isLandscape: false, listType: FLATLIST, showNoResults: true, shouldRenderSeparator: true, - isLandscape: false, }; constructor(props) { @@ -110,16 +112,19 @@ export default class CustomList extends PureComponent { }; renderFlatList = () => { - const {data, extraData, theme, onRefresh, refreshing} = this.props; + const {canRefresh, data, extraData, theme, onRefresh, refreshing} = this.props; const style = getStyleFromTheme(theme); - const refreshControl = ( - ); + let refreshControl; + if (canRefresh) { + refreshControl = ( + ); + } return ( { const baseProps = { + canRefresh: false, data: [{username: 'username_1'}, {username: 'username_2'}], listType: FLATLIST, loading: false, diff --git a/app/screens/channel_members/__snapshots__/channel_members.test.js.snap b/app/screens/channel_members/__snapshots__/channel_members.test.js.snap index 999aacad0..f9f560f33 100644 --- a/app/screens/channel_members/__snapshots__/channel_members.test.js.snap +++ b/app/screens/channel_members/__snapshots__/channel_members.test.js.snap @@ -45,6 +45,7 @@ exports[`ChannelMembers should match snapshot 1`] = ` /> { return channels.filter((c) => { - return (!myMembers[c.id] && c.type === General.OPEN_CHANNEL); + return (!myMembers[c.id] && c.type === General.OPEN_CHANNEL && c.delete_at === 0); }); } ); @@ -45,6 +45,8 @@ function mapStateToProps(state) { const channels = joinablePublicChannels(state); const archivedChannels = teamArchivedChannels(state); const currentTeamId = getCurrentTeamId(state); + const canShowArchivedChannels = config.ExperimentalViewArchivedChannels === 'true' && + isMinimumServerVersion(state.entities.general.serverVersion, 5, 18); return { canCreateChannels: showCreateOption(state, config, license, currentTeamId, General.OPEN_CHANNEL, isAdmin(roles), isSystemAdmin(roles)), @@ -54,16 +56,17 @@ function mapStateToProps(state) { archivedChannels, theme: getTheme(state), isLandscape: isLandscape(state), - canShowArchivedChannels: isMinimumServerVersion(state.entities.general.serverVersion, 5, 18), + canShowArchivedChannels, }; } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ + getArchivedChannels, + getChannels, handleSelectChannel, joinChannel, - loadPublicAndArchivedChannels, searchChannels, setChannelDisplayName, }, dispatch), diff --git a/app/screens/more_channels/more_channels.js b/app/screens/more_channels/more_channels.js index f8f00b2d3..1e80dc766 100644 --- a/app/screens/more_channels/more_channels.js +++ b/app/screens/more_channels/more_channels.js @@ -21,7 +21,7 @@ import KeyboardLayout from 'app/components/layout/keyboard_layout'; import Loading from 'app/components/loading'; import SearchBar from 'app/components/search_bar'; import StatusBar from 'app/components/status_bar'; -import {alertErrorWithFallback} from 'app/utils/general'; +import {alertErrorWithFallback, emptyFunction} from 'app/utils/general'; import {goToScreen, dismissModal, setButtons} from 'app/actions/navigation'; import { changeOpacity, @@ -33,9 +33,10 @@ import { export default class MoreChannels extends PureComponent { static propTypes = { actions: PropTypes.shape({ + getArchivedChannels: PropTypes.func.isRequired, + getChannels: PropTypes.func.isRequired, handleSelectChannel: PropTypes.func.isRequired, joinChannel: PropTypes.func.isRequired, - loadPublicAndArchivedChannels: PropTypes.func.isRequired, searchChannels: PropTypes.func.isRequired, setChannelDisplayName: PropTypes.func.isRequired, }).isRequired, @@ -65,7 +66,8 @@ export default class MoreChannels extends PureComponent { this.searchTimeoutId = 0; this.publicPage = -1; this.archivedPage = -1; - this.next = true; + this.nextPublic = true; + this.nextArchived = true; this.mounted = false; this.state = { @@ -104,6 +106,7 @@ export default class MoreChannels extends PureComponent { componentWillReceiveProps(nextProps) { const {term} = this.state; let channels; + let archivedChannels; if (this.props.theme !== nextProps.theme) { setNavigatorStyles(this.props.componentId, nextProps.theme); @@ -116,8 +119,24 @@ export default class MoreChannels extends PureComponent { } } + if (nextProps.archivedChannels !== this.props.archivedChannels) { + archivedChannels = nextProps.archivedChannels; + if (term) { + archivedChannels = this.filterChannels(nextProps.archivedChannels, term); + } + } + + const nextState = {}; if (channels) { - this.setState({channels}); + nextState.channels = channels; + } + + if (archivedChannels) { + nextState.archivedChannels = archivedChannels; + } + + if (nextState.archivedChannels || nextState.channels) { + this.setState(nextState); } } @@ -152,17 +171,30 @@ export default class MoreChannels extends PureComponent { doGetChannels = () => { const {actions, currentTeamId, canShowArchivedChannels} = this.props; - const {loading, term} = this.state; + const {loading, term, typeOfChannels} = this.state; - if (this.next && !loading && !term && this.mounted) { + if (!loading && !term && this.mounted) { this.setState({loading: true}, () => { - actions.loadPublicAndArchivedChannels( - currentTeamId, - this.publicPage + 1, - this.archivedPage + 1, - General.CHANNELS_CHUNK_SIZE, - canShowArchivedChannels, - ).then(this.loadedChannels); + switch (typeOfChannels) { + case 'public': + if (this.nextPublic) { + actions.getChannels( + currentTeamId, + this.publicPage + 1, + General.CHANNELS_CHUNK_SIZE, + ).then(this.loadedChannels); + } + break; + case 'archived': + if (canShowArchivedChannels && this.nextArchived) { + actions.getArchivedChannels( + currentTeamId, + this.archivedPage + 1, + General.CHANNELS_CHUNK_SIZE, + ).then(this.loadedChannels); + } + break; + } }); } }; @@ -191,11 +223,17 @@ export default class MoreChannels extends PureComponent { loadedChannels = ({data}) => { if (this.mounted) { - if (data && !data.length) { - this.next = false; + const {typeOfChannels} = this.state; + const isPublic = typeOfChannels === 'public'; + + if (isPublic) { + this.publicPage += 1; + this.nextPublic = (data && !data.length); + } else { + this.archivedPage += 1; + this.nextArchived = (data && !data.length); } - this.page += 1; this.setState({loading: false}); } }; @@ -253,10 +291,12 @@ export default class MoreChannels extends PureComponent { }; renderLoading = () => { - const {theme, channels} = this.props; + const {theme} = this.props; + const {typeOfChannels} = this.state; const style = getStyleFromTheme(theme); - if (!channels.length && this.page <= 0) { + if ((typeOfChannels === 'public' && !this.nextPublic) || + (typeOfChannels === 'archived' && !this.nextArchived)) { return null; } @@ -362,7 +402,10 @@ export default class MoreChannels extends PureComponent { default: typeOfChannels = this.state.typeOfChannels; } - this.setState({typeOfChannels}); + + if (typeOfChannels !== this.state.typeOfChannels) { + this.setState({typeOfChannels, loading: false}, this.doGetChannels); + } }); } @@ -370,7 +413,7 @@ export default class MoreChannels extends PureComponent { const {formatMessage} = this.context.intl; const {theme, isLandscape, canShowArchivedChannels} = this.props; const {adding, channels, archivedChannels, loading, term, typeOfChannels} = this.state; - const more = term ? () => true : this.getChannels; + const more = term ? emptyFunction : this.getChannels; const style = getStyleFromTheme(theme); const publicChannelsText = formatMessage({id: 'more_channels.showPublicChannels', defaultMessage: 'Show: Public Channels'}); @@ -440,6 +483,7 @@ export default class MoreChannels extends PureComponent { {channelDropdown} { const actions = { handleSelectChannel: jest.fn(), joinChannel: jest.fn(), - loadPublicAndArchivedChannels: jest.fn().mockResolvedValue({data: [{id: 'id2', name: 'name2', display_name: 'display_name2'}]}), + getArchivedChannels: jest.fn().mockResolvedValue({data: [{id: 'id2', name: 'name2', display_name: 'display_name2', delete_at: 123}]}), + getChannels: jest.fn().mockResolvedValue({data: [{id: 'id', name: 'name', display_name: 'display_name'}]}), searchChannels: jest.fn(), setChannelDisplayName: jest.fn(), }; @@ -25,7 +26,7 @@ describe('MoreChannels', () => { actions, canCreateChannels: true, channels: [{id: 'id', name: 'name', display_name: 'display_name'}], - archivedChannels: [{id: 'id2', name: 'archived', display_name: 'archived channel'}], + archivedChannels: [{id: 'id2', name: 'archived', display_name: 'archived channel', delete_at: 123}], closeButton: {}, currentUserId: 'current_user_id', currentTeamId: 'current_team_id', diff --git a/app/screens/select_team/__snapshots__/select_team.test.js.snap b/app/screens/select_team/__snapshots__/select_team.test.js.snap index df1241320..3d3ff3696 100644 --- a/app/screens/select_team/__snapshots__/select_team.test.js.snap +++ b/app/screens/select_team/__snapshots__/select_team.test.js.snap @@ -91,6 +91,7 @@ exports[`SelectTeam should match snapshot for teams 1`] = ` />