diff --git a/app/actions/websocket/threads.ts b/app/actions/websocket/threads.ts
index 85e9df7ed..f9791ad26 100644
--- a/app/actions/websocket/threads.ts
+++ b/app/actions/websocket/threads.ts
@@ -25,7 +25,9 @@ export function handleThreadReadChanged(msg: WebSocketMessage) {
if (msg.data.thread_id) {
const state = getState();
const thread = getThread(state, msg.data.thread_id);
- if (thread) {
+
+ // Mark only following threads as read.
+ if (thread?.is_following) {
dispatch(
handleReadChanged(
msg.data.thread_id,
diff --git a/app/components/global_threads/thread_footer/thread_footer.tsx b/app/components/global_threads/thread_footer/thread_footer.tsx
index 5e455397b..16cf25e7c 100644
--- a/app/components/global_threads/thread_footer/thread_footer.tsx
+++ b/app/components/global_threads/thread_footer/thread_footer.tsx
@@ -132,18 +132,21 @@ function ThreadFooter({actions, currentUserId, intl, location, testID, theme, th
// threadstarter should be the first one in the avatars list
const participants = React.useMemo(() => {
- let isThreadStarterFound = false;
- const participantIds = thread.participants.flatMap((participant) => {
- if (participant.id === threadStarter?.id) {
- isThreadStarterFound = true;
- return [];
+ if (thread.participants?.length) {
+ let isThreadStarterFound = false;
+ const participantIds = thread.participants.flatMap((participant) => {
+ if (participant.id === threadStarter?.id) {
+ isThreadStarterFound = true;
+ return [];
+ }
+ return participant.id;
+ });
+ if (isThreadStarterFound) {
+ participantIds.unshift(threadStarter?.id);
}
- return participant.id;
- });
- if (isThreadStarterFound) {
- participantIds.unshift(threadStarter?.id);
+ return participantIds;
}
- return participantIds;
+ return [];
}, [thread.participants, threadStarter]);
let avatars;
diff --git a/app/components/global_threads/thread_list/index.tsx b/app/components/global_threads/thread_list/index.tsx
index 6824e5f14..cdf897f14 100644
--- a/app/components/global_threads/thread_list/index.tsx
+++ b/app/components/global_threads/thread_list/index.tsx
@@ -49,7 +49,7 @@ function ThreadList({haveUnreads, intl, isLoading, loadMoreThreads, listRef, mar
threadId={item}
/>
);
- }, []);
+ }, [theme]);
const renderHeader = () => {
if (!viewingUnreads && !threadIds.length) {
diff --git a/app/components/global_threads/thread_list/thread_list_header/__snapshots__/index.test.tsx.snap b/app/components/global_threads/thread_list/thread_list_header/__snapshots__/index.test.tsx.snap
index 0bdba990a..0b12ac82b 100644
--- a/app/components/global_threads/thread_list/thread_list_header/__snapshots__/index.test.tsx.snap
+++ b/app/components/global_threads/thread_list/thread_list_header/__snapshots__/index.test.tsx.snap
@@ -75,7 +75,6 @@ exports[`Global Thread List Header Should render threads with functional tabs &
style={
Array [
undefined,
- undefined,
]
}
/>
diff --git a/app/components/global_threads/thread_list/thread_list_header/index.test.tsx b/app/components/global_threads/thread_list/thread_list_header/index.test.tsx
index 106c9228a..d149acf55 100644
--- a/app/components/global_threads/thread_list/thread_list_header/index.test.tsx
+++ b/app/components/global_threads/thread_list/thread_list_header/index.test.tsx
@@ -54,6 +54,7 @@ describe('Global Thread List Header', () => {
expect(markAllAsRead).toHaveBeenCalled();
});
+ /* @TODO: Uncomment when "mark all as read" button is disabled during no unreads.
test('Should disable mark all as read and hide dot on UNREADS tab when no unread messages are present', () => {
wrapper.setProps({
...baseProps,
@@ -66,4 +67,5 @@ describe('Global Thread List Header', () => {
expect(markAllAsReadButton.exists()).toBeTruthy();
expect(markAllAsReadButton.props().disabled).toBeTruthy();
});
+ */
});
diff --git a/app/components/global_threads/thread_list/thread_list_header/index.tsx b/app/components/global_threads/thread_list/thread_list_header/index.tsx
index fecee49b3..856a8dea5 100644
--- a/app/components/global_threads/thread_list/thread_list_header/index.tsx
+++ b/app/components/global_threads/thread_list/thread_list_header/index.tsx
@@ -62,13 +62,13 @@ function ThreadListHeader({haveUnreads, intl, markAllAsRead, style, testID, view
diff --git a/app/components/post_list/post/post.tsx b/app/components/post_list/post/post.tsx
index 80bf021ce..8a32c5de1 100644
--- a/app/components/post_list/post/post.tsx
+++ b/app/components/post_list/post/post.tsx
@@ -259,7 +259,7 @@ const Post = ({
collapsedThreadsEnabled &&
Boolean(thread) &&
post.state !== Posts.POST_DELETED &&
- thread?.participants?.length
+ (thread?.is_following || thread?.participants?.length)
) {
footer = (
-
, fallbac
if (!thread || !thread?.id) {
if (fallbackFromPosts) {
const post = getPost(state, threadId);
- if (post?.participants?.length) {
+ if (post && !post.root_id) {
const {id, is_following, reply_count, last_reply_at, participants} = post;
return {
id,
diff --git a/app/screens/post_options/index.js b/app/screens/post_options/index.js
index b0a90f585..e254bbac2 100644
--- a/app/screens/post_options/index.js
+++ b/app/screens/post_options/index.js
@@ -146,7 +146,7 @@ export function makeMapStateToProps() {
currentUserId,
isFlagged: isPostFlagged(post.id, myPreferences),
theme: getTheme(state),
- thread: isCollapsedThreadsEnabled(state) && getThread(state, post.id, true),
+ thread: isCollapsedThreadsEnabled(state) ? getThread(state, post.id, true) : null,
};
};
}
diff --git a/app/screens/post_options/post_options.js b/app/screens/post_options/post_options.js
index 8cb8322de..bbdf16043 100644
--- a/app/screens/post_options/post_options.js
+++ b/app/screens/post_options/post_options.js
@@ -14,6 +14,7 @@ import ReactionPicker from '@components/reaction_picker';
import SlideUpPanel from '@components/slide_up_panel';
import {BOTTOM_MARGIN} from '@components/slide_up_panel/slide_up_panel';
import {REACTION_PICKER_HEIGHT} from '@constants/reaction_picker';
+import {CHANNEL} from '@constants/screen';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {isSystemMessage} from '@mm-redux/utils/post_utils';
import {t} from '@utils/i18n';
@@ -110,19 +111,27 @@ export default class PostOptions extends PureComponent {
}
getFollowThreadOption = () => {
- const {thread} = this.props;
- if (!thread) {
+ const {location, thread} = this.props;
+ if (location !== CHANNEL) {
return null;
}
const key = 'follow';
let icon;
let message;
- if (thread.is_following) {
+ if (thread?.is_following) {
icon = 'message-minus-outline';
- message = {id: t('threads.unfollowThread'), defaultMessage: 'Unfollow Thread'};
+ if (thread?.participants?.length) {
+ message = {id: t('threads.unfollowThread'), defaultMessage: 'Unfollow Thread'};
+ } else {
+ message = {id: t('threads.unfollowMessage'), defaultMessage: 'Unfollow Message'};
+ }
} else {
icon = 'message-plus-outline';
- message = {id: t('threads.followThread'), defaultMessage: 'Follow Thread'};
+ if (thread?.participants?.length) {
+ message = {id: t('threads.followThread'), defaultMessage: 'Follow Thread'};
+ } else {
+ message = {id: t('threads.followMessage'), defaultMessage: 'Follow Message'};
+ }
}
const onPress = this.handleToggleFollow;
return this.getOption(key, icon, message, onPress);
diff --git a/app/screens/thread/index.js b/app/screens/thread/index.js
index 9dd50c075..c1c8121fa 100644
--- a/app/screens/thread/index.js
+++ b/app/screens/thread/index.js
@@ -29,7 +29,7 @@ function makeMapStateToProps() {
myMember: getMyCurrentChannelMembership(state),
postIds: getPostIdsForThread(state, ownProps.rootId),
theme: getTheme(state),
- thread: getThread(state, ownProps.rootId, true),
+ thread: collapsedThreadsEnabled ? getThread(state, ownProps.rootId, true) : null,
threadLoadingStatus: state.requests.posts.getPostThread,
};
};
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index 2d316f7bd..16d6f9814 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -709,9 +709,11 @@
"threads.deleted": "Original Message Deleted",
"threads.follow": "Follow",
"threads.following": "Following",
+ "threads.followMessage": "Follow Message",
"threads.followThread": "Follow Thread",
"threads.newReplies": "{count} new {count, plural, one {reply} other {replies}}",
"threads.replies": "{count} {count, plural, one {reply} other {replies}}",
+ "threads.unfollowMessage": "Unfollow Message",
"threads.unfollowThread": "Unfollow Thread",
"user.settings.display.clockDisplay": "Clock Display",
"user.settings.display.custom_theme": "Custom Theme",