Always load the thread & modify thread selector (#4771) (#4775)

* Always load the thread & modify thread selector

* review feedback

(cherry picked from commit bd7afae6f0)

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Mattermost Build 2020-09-08 12:21:04 -04:00 committed by GitHub
parent 9db54fb462
commit b51f7a0bb2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 64 additions and 91 deletions

View file

@ -31,7 +31,7 @@ import {getChannelByName as selectChannelByName, getChannelsIdForTeam} from '@mm
import EventEmitter from '@mm-redux/utils/event_emitter';
import {lastChannelIdForTeam, loadSidebarDirectMessagesProfiles} from '@actions/helpers/channels';
import {getPosts, getPostsBefore, getPostsSince, getPostThread, loadUnreadChannelPosts} from '@actions/views/post';
import {getPosts, getPostsBefore, getPostsSince, loadUnreadChannelPosts} from '@actions/views/post';
import {INSERT_TO_COMMENT, INSERT_TO_DRAFT} from '@constants/post_draft';
import {getChannelReachable} from '@selectors/channel';
import telemetry from '@telemetry';
@ -111,18 +111,6 @@ export function fetchPostActionWithRetry(action, maxTries = MAX_RETRIES) {
};
}
export function loadThreadIfNecessary(rootId) {
return (dispatch, getState) => {
const state = getState();
const {posts, postsInThread} = state.entities.posts;
const threadPosts = postsInThread[rootId];
if (!posts[rootId] || !threadPosts) {
dispatch(getPostThread(rootId));
}
};
}
export function selectInitialChannel(teamId) {
return (dispatch, getState) => {
const state = getState();

View file

@ -69,23 +69,20 @@ export const getPostsInCurrentChannel: (a: GlobalState) => Array<PostWithFormatD
export function makeGetPostIdsForThread(): (b: GlobalState, a: $ID<Post>) => Array<$ID<Post>> {
return createIdsSelector(
getAllPosts,
(state: GlobalState, rootId: string) => state.entities.posts.postsInThread[rootId] || [],
(state: GlobalState, rootId) => state.entities.posts.posts[rootId],
(posts, postsForThread, rootPost) => {
(state: GlobalState, rootId: string) => state.entities.posts.posts[rootId],
(posts, rootPost) => {
const thread: Post[] = [];
if (rootPost) {
thread.push(rootPost);
}
postsForThread.forEach((id) => {
const post = posts[id];
if (post) {
thread.push(post);
const postsArray = Object.values(posts).filter((p) => p.root_id === rootPost.id);
if (postsArray.length) {
thread.push(...postsArray);
}
});
thread.sort(comparePosts);
thread.sort(comparePosts);
}
return thread.map((post) => post.id);
},

View file

@ -30,7 +30,7 @@ export default class ChannelPostList extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
loadPostsIfNecessaryWithRetry: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
increasePostVisibility: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
recordLoadTime: PropTypes.func.isRequired,
@ -106,7 +106,7 @@ export default class ChannelPostList extends PureComponent {
const rootId = (post.root_id || post.id);
Keyboard.dismiss();
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
const screen = 'Thread';

View file

@ -12,7 +12,7 @@ describe('ChannelPostList', () => {
const baseProps = {
actions: {
loadPostsIfNecessaryWithRetry: jest.fn(),
loadThreadIfNecessary: jest.fn(),
getPostThread: jest.fn(),
increasePostVisibility: jest.fn(),
selectPost: jest.fn(),
recordLoadTime: jest.fn(),

View file

@ -4,21 +4,20 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {
loadPostsIfNecessaryWithRetry,
increasePostVisibility,
refreshChannelWithRetry,
} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {recordLoadTime} from 'app/actions/views/root';
import {Types} from '@constants';
import {selectPost} from '@mm-redux/actions/posts';
import {getPostIdsInCurrentChannel} from '@mm-redux/selectors/entities/posts';
import {getCurrentChannelId} from '@mm-redux/selectors/entities/channels';
import {getCurrentUserId} from '@mm-redux/selectors/entities/users';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {
loadPostsIfNecessaryWithRetry,
loadThreadIfNecessary,
increasePostVisibility,
refreshChannelWithRetry,
} from 'app/actions/views/channel';
import {recordLoadTime} from 'app/actions/views/root';
import {Types} from 'app/constants';
import {isLandscape} from 'app/selectors/device';
import {isLandscape} from '@selectors/device';
import ChannelPostList from './channel_post_list';
@ -44,7 +43,7 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
loadPostsIfNecessaryWithRetry,
loadThreadIfNecessary,
getPostThread,
increasePostVisibility,
selectPost,
recordLoadTime,

View file

@ -36,7 +36,7 @@ export default class FlaggedPosts extends PureComponent {
actions: PropTypes.shape({
clearSearch: PropTypes.func.isRequired,
loadChannelsByTeamName: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
getFlaggedPosts: PropTypes.func.isRequired,
selectFocusedPostId: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
@ -103,7 +103,7 @@ export default class FlaggedPosts extends PureComponent {
};
Keyboard.dismiss();
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
goToScreen(screen, title, passProps);
};

View file

@ -15,7 +15,7 @@ describe('FlaggedPosts', () => {
actions: {
clearSearch: jest.fn(),
loadChannelsByTeamName: jest.fn(),
loadThreadIfNecessary: jest.fn(),
getPostThread: jest.fn(),
getFlaggedPosts: jest.fn(),
selectFocusedPostId: jest.fn(),
selectPost: jest.fn(),

View file

@ -4,12 +4,12 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {loadChannelsByTeamName} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {selectFocusedPostId, selectPost} from '@mm-redux/actions/posts';
import {clearSearch, getFlaggedPosts} from '@mm-redux/actions/search';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
import {makePreparePostIdsForSearchPosts} from 'app/selectors/post_list';
import {makePreparePostIdsForSearchPosts} from '@selectors/post_list';
import FlaggedPosts from './flagged_posts';
@ -30,7 +30,7 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
clearSearch,
loadChannelsByTeamName,
loadThreadIfNecessary,
getPostThread,
getFlaggedPosts,
selectFocusedPostId,
selectPost,

View file

@ -35,7 +35,7 @@ LongPost {
"navigationEventListener": undefined,
"props": Object {
"actions": Object {
"loadThreadIfNecessary": [MockFunction],
"getPostThread": [MockFunction],
"selectPost": [MockFunction],
},
"intl": Object {
@ -147,7 +147,7 @@ LongPost {
"_element": <LongPost
actions={
Object {
"loadThreadIfNecessary": [MockFunction],
"getPostThread": [MockFunction],
"selectPost": [MockFunction],
}
}

View file

@ -4,13 +4,13 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getPostThread} from '@actions/views/channel';
import {selectPost} from '@mm-redux/actions/posts';
import {makeGetChannel} from '@mm-redux/selectors/entities/channels';
import {getPost} from '@mm-redux/selectors/entities/posts';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {isLandscape} from '@selectors/device';
import {loadThreadIfNecessary} from 'app/actions/views/channel';
import {isLandscape} from 'app/selectors/device';
import LongPost from './long_post';
function makeMapStateToProps() {
@ -32,7 +32,7 @@ function makeMapStateToProps() {
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
loadThreadIfNecessary,
getPostThread,
selectPost,
}, dispatch),
};

View file

@ -41,11 +41,10 @@ Animatable.initializeRegistryWithDefinitions({
export default class LongPost extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
}).isRequired,
channelName: PropTypes.string,
isPermalink: PropTypes.bool,
inThreadView: PropTypes.bool,
managedConfig: PropTypes.object,
onHashtagPress: PropTypes.func,
@ -84,7 +83,7 @@ export default class LongPost extends PureComponent {
rootId,
};
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
goToScreen(screen, title, passProps);

View file

@ -16,7 +16,7 @@ jest.mock('react-native-file-viewer', () => ({
describe('LongPost', () => {
const baseProps = {
actions: {
loadThreadIfNecessary: jest.fn(),
getPostThread: jest.fn(),
selectPost: jest.fn(),
},
postId: 'post-id',

View file

@ -4,6 +4,9 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {handleSelectChannel} from '@actions/views/channel';
import {getPostsAround, getPostThread} from '@actions/views/post';
import {handleTeamChange} from '@actions/views/select_team';
import {getChannel as getChannelAction, joinChannel} from '@mm-redux/actions/channels';
import {selectPost} from '@mm-redux/actions/posts';
import {makeGetChannel, getMyChannelMemberships} from '@mm-redux/selectors/entities/channels';
@ -11,14 +14,7 @@ import {makeGetPostIdsAroundPost, getPost} from '@mm-redux/selectors/entities/po
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams';
import {getCurrentUserId} from '@mm-redux/selectors/entities/users';
import {
handleSelectChannel,
loadThreadIfNecessary,
} from 'app/actions/views/channel';
import {getPostsAround, getPostThread} from 'app/actions/views/post';
import {handleTeamChange} from 'app/actions/views/select_team';
import {isLandscape} from 'app/selectors/device';
import {isLandscape} from '@selectors/device';
import Permalink from './permalink';
@ -66,7 +62,6 @@ function mapDispatchToProps(dispatch) {
handleSelectChannel,
handleTeamChange,
joinChannel,
loadThreadIfNecessary,
selectPost,
}, dispatch),
};

View file

@ -60,7 +60,6 @@ export default class Permalink extends PureComponent {
handleSelectChannel: PropTypes.func.isRequired,
handleTeamChange: PropTypes.func.isRequired,
joinChannel: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
}).isRequired,
channelId: PropTypes.string,
@ -147,7 +146,7 @@ export default class Permalink extends PureComponent {
rootId,
};
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
goToScreen(screen, title, passProps);

View file

@ -18,7 +18,6 @@ describe('Permalink', () => {
handleSelectChannel: jest.fn(),
handleTeamChange: jest.fn(),
joinChannel: jest.fn(),
loadThreadIfNecessary: jest.fn(),
selectPost: jest.fn(),
};

View file

@ -4,12 +4,12 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {loadChannelsByTeamName} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {selectFocusedPostId, selectPost} from '@mm-redux/actions/posts';
import {clearSearch, getPinnedPosts} from '@mm-redux/actions/search';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
import {makePreparePostIdsForSearchPosts} from 'app/selectors/post_list';
import {makePreparePostIdsForSearchPosts} from '@selectors/post_list';
import PinnedPosts from './pinned_posts';
@ -32,7 +32,7 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
clearSearch,
loadChannelsByTeamName,
loadThreadIfNecessary,
getPostThread,
getPinnedPosts,
selectFocusedPostId,
selectPost,

View file

@ -36,7 +36,7 @@ export default class PinnedPosts extends PureComponent {
actions: PropTypes.shape({
clearSearch: PropTypes.func.isRequired,
loadChannelsByTeamName: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
getPinnedPosts: PropTypes.func.isRequired,
selectFocusedPostId: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
@ -104,7 +104,7 @@ export default class PinnedPosts extends PureComponent {
rootId,
};
Keyboard.dismiss();
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
goToScreen(screen, title, passProps);
};

View file

@ -14,7 +14,7 @@ describe('PinnedPosts', () => {
actions: {
clearSearch: jest.fn(),
loadChannelsByTeamName: jest.fn(),
loadThreadIfNecessary: jest.fn(),
getPostThread: jest.fn(),
getPinnedPosts: jest.fn(),
selectFocusedPostId: jest.fn(),
selectPost: jest.fn(),

View file

@ -4,12 +4,12 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {loadChannelsByTeamName} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {selectFocusedPostId, selectPost} from '@mm-redux/actions/posts';
import {clearSearch, getRecentMentions} from '@mm-redux/actions/search';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
import {makePreparePostIdsForSearchPosts} from 'app/selectors/post_list';
import {makePreparePostIdsForSearchPosts} from '@selectors/post_list';
import RecentMentions from './recent_mentions';
@ -30,7 +30,7 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
clearSearch,
loadChannelsByTeamName,
loadThreadIfNecessary,
getPostThread,
getRecentMentions,
selectFocusedPostId,
selectPost,

View file

@ -36,13 +36,11 @@ export default class RecentMentions extends PureComponent {
actions: PropTypes.shape({
clearSearch: PropTypes.func.isRequired,
loadChannelsByTeamName: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
getRecentMentions: PropTypes.func.isRequired,
selectFocusedPostId: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
}).isRequired,
didFail: PropTypes.bool,
isLoading: PropTypes.bool,
postIds: PropTypes.array,
theme: PropTypes.object.isRequired,
};
@ -99,7 +97,7 @@ export default class RecentMentions extends PureComponent {
};
Keyboard.dismiss();
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
goToScreen(screen, title, passProps);
};

View file

@ -15,7 +15,7 @@ describe('RecentMentions', () => {
actions: {
clearSearch: jest.fn(),
loadChannelsByTeamName: jest.fn(),
loadThreadIfNecessary: jest.fn(),
getPostThread: jest.fn(),
getRecentMentions: jest.fn(),
selectFocusedPostId: jest.fn(),
selectPost: jest.fn(),

View file

@ -4,6 +4,9 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {loadChannelsByTeamName} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {handleSearchDraftChanged} from '@actions/views/search';
import {selectFocusedPostId, selectPost} from '@mm-redux/actions/posts';
import {clearSearch, removeSearchTerms, searchPostsWithParams, getMorePostsForSearch} from '@mm-redux/actions/search';
import {getCurrentChannelId, filterPostIds} from '@mm-redux/selectors/entities/channels';
@ -14,12 +17,9 @@ import {isTimezoneEnabled} from '@mm-redux/selectors/entities/timezone';
import {isMinimumServerVersion} from '@mm-redux/utils/helpers';
import {getUserCurrentTimezone} from '@mm-redux/utils/timezone_utils';
import {getCurrentUser} from '@mm-redux/selectors/entities/users';
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
import {handleSearchDraftChanged} from 'app/actions/views/search';
import {isLandscape} from 'app/selectors/device';
import {makePreparePostIdsForSearchPosts} from 'app/selectors/post_list';
import {getDeviceUtcOffset, getUtcOffsetForTimeZone} from 'app/utils/timezone';
import {isLandscape} from '@selectors/device';
import {makePreparePostIdsForSearchPosts} from '@selectors/post_list';
import {getDeviceUtcOffset, getUtcOffsetForTimeZone} from '@utils/timezone';
import Search from './search';
@ -76,7 +76,7 @@ function mapDispatchToProps(dispatch) {
clearSearch,
handleSearchDraftChanged,
loadChannelsByTeamName,
loadThreadIfNecessary,
getPostThread,
removeSearchTerms,
selectFocusedPostId,
searchPostsWithParams,

View file

@ -60,14 +60,13 @@ export default class Search extends PureComponent {
clearSearch: PropTypes.func.isRequired,
handleSearchDraftChanged: PropTypes.func.isRequired,
loadChannelsByTeamName: PropTypes.func.isRequired,
loadThreadIfNecessary: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
removeSearchTerms: PropTypes.func.isRequired,
searchPostsWithParams: PropTypes.func.isRequired,
getMorePostsForSearch: PropTypes.func.isRequired,
selectFocusedPostId: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string.isRequired,
currentTeamId: PropTypes.string.isRequired,
initialValue: PropTypes.string,
isLandscape: PropTypes.bool.isRequired,
@ -222,7 +221,7 @@ export default class Search extends PureComponent {
const rootId = (post.root_id || post.id);
Keyboard.dismiss();
actions.loadThreadIfNecessary(rootId);
actions.getPostThread(rootId);
actions.selectPost(rootId);
const screen = 'Thread';