[Gekidou MM-40096] Permalink view for replies when CRT is enabled (#6494)

* Permalink for CRT

* typo

* Condition refactor
This commit is contained in:
Anurag Shivarathri 2022-07-22 17:44:39 +05:30 committed by GitHub
parent 102789bbd9
commit c4c89a8f05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 21 deletions

View file

@ -570,7 +570,7 @@ export const fetchPostAuthors = async (serverUrl: string, posts: Post[], fetchOn
}
};
export async function fetchPostThread(serverUrl: string, postId: string, fetchOnly = false): Promise<PostsRequest> {
export async function fetchPostThread(serverUrl: string, postId: string, fetchOnly = false) {
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
if (!operator) {
return {error: `${serverUrl} database not found`};
@ -587,12 +587,15 @@ export async function fetchPostThread(serverUrl: string, postId: string, fetchOn
const isCRTEnabled = await getIsCRTEnabled(operator.database);
const data = await client.getPostThread(postId, isCRTEnabled, isCRTEnabled);
const result = processPostsFetched(data);
let posts: Model[] = [];
if (!fetchOnly) {
const models = await operator.handlePosts({
const models: Model[] = [];
posts = await operator.handlePosts({
...result,
actionType: ActionType.POSTS.RECEIVED_IN_THREAD,
prepareRecordsOnly: true,
});
models.push(...posts);
const {authors} = await fetchPostAuthors(serverUrl, result.posts, true);
if (authors?.length) {
@ -611,7 +614,7 @@ export async function fetchPostThread(serverUrl: string, postId: string, fetchOn
}
await operator.batchRecords(models);
}
return result;
return {posts: extractRecordsForTable<PostModel>(posts, MM_TABLES.SERVER.POST)};
} catch (error) {
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
return {error};
@ -641,7 +644,7 @@ export async function fetchPostsAround(serverUrl: string, channelId: string, pos
const preData: PostResponse = {
posts: {
...filterPostsInOrderedArray(after.posts, after.order),
postId: post.posts![postId],
[postId]: post.posts![postId],
...filterPostsInOrderedArray(before.posts, before.order),
},
order: [],

View file

@ -27,6 +27,7 @@ type BodyProps = {
hasReactions: boolean;
highlight: boolean;
highlightReplyBar: boolean;
isCRTEnabled?: boolean;
isEphemeral: boolean;
isFirstReply?: boolean;
isJumboEmoji: boolean;
@ -75,7 +76,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
const Body = ({
appsEnabled, hasFiles, hasReactions, highlight, highlightReplyBar,
isEphemeral, isFirstReply, isJumboEmoji, isLastReply, isPendingOrFailed, isPostAddChannelMember,
isCRTEnabled, isEphemeral, isFirstReply, isJumboEmoji, isLastReply, isPendingOrFailed, isPostAddChannelMember,
location, post, searchPatterns, showAddReaction, theme,
}: BodyProps) => {
const style = getStyleSheet(theme);
@ -90,7 +91,7 @@ const Body = ({
const hasContent = (post.metadata?.embeds?.length || (appsEnabled && post.props?.app_bindings?.length)) || post.props?.attachments?.length;
const replyBarStyle = useCallback((): StyleProp<ViewStyle>|undefined => {
if (!isReplyPost) {
if (!isReplyPost || (isCRTEnabled && location === Screens.PERMALINK)) {
return undefined;
}

View file

@ -53,6 +53,7 @@ type PostProps = {
isPostAddChannelMember: boolean;
location: string;
post: PostModel;
rootId?: string;
previousPost?: PostModel;
hasReactions: boolean;
searchPatterns?: SearchPattern[];
@ -105,7 +106,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
const Post = ({
appsEnabled, canDelete, currentUser, differentThreadSequence, hasFiles, hasReplies, highlight, highlightPinnedOrSaved = true, highlightReplyBar,
isCRTEnabled, isConsecutivePost, isEphemeral, isFirstReply, isSaved, isJumboEmoji, isLastReply, isPostAddChannelMember,
location, post, hasReactions, searchPatterns, shouldRenderReplyButton, skipSavedHeader, skipPinnedHeader, showAddReaction = true, style,
location, post, rootId, hasReactions, searchPatterns, shouldRenderReplyButton, skipSavedHeader, skipPinnedHeader, showAddReaction = true, style,
testID, thread, previousPost,
}: PostProps) => {
const pressDetected = useRef(false);
@ -140,8 +141,8 @@ const Post = ({
const isValidSystemMessage = isAutoResponder || !isSystemPost;
if (post.deleteAt === 0 && isValidSystemMessage && !isPendingOrFailed) {
if ([Screens.CHANNEL, Screens.PERMALINK].includes(location)) {
const rootId = post.rootId || post.id;
fetchAndSwitchToThread(serverUrl, rootId);
const postRootId = post.rootId || post.id;
fetchAndSwitchToThread(serverUrl, postRootId);
}
} else if ((isEphemeral || post.deleteAt > 0)) {
removePost(serverUrl, post);
@ -278,6 +279,7 @@ const Post = ({
hasReactions={hasReactions}
highlight={Boolean(highlightedStyle)}
highlightReplyBar={highlightReplyBar}
isCRTEnabled={isCRTEnabled}
isEphemeral={isEphemeral}
isFirstReply={isFirstReply}
isJumboEmoji={isJumboEmoji}
@ -295,7 +297,7 @@ const Post = ({
let unreadDot;
let footer;
if (isCRTEnabled && thread && location !== Screens.THREAD) {
if (isCRTEnabled && thread && location !== Screens.THREAD && !(rootId && location === Screens.PERMALINK)) {
if (thread.replyCount > 0 || thread.isFollowing) {
footer = (
<Footer

View file

@ -312,6 +312,7 @@ const PostList = ({
isCRTEnabled={isCRTEnabled}
key={item.id}
post={item}
rootId={rootId}
style={styles.scale}
testID={`${testID}.post`}
{...postProps}

View file

@ -34,6 +34,9 @@ const enhance = withObservables([], ({database, postId, teamName}: OwnProps) =>
channel: post.pipe(
switchMap((p) => (p ? p.channel.observe() : of$(undefined))),
),
rootId: post.pipe(
switchMap((p) => of$(p?.rootId)),
),
isTeamMember: team.pipe(
switchMap((t) => (t ? queryMyTeamsByIds(database, [t.id]).observe() : of$(undefined))),
switchMap((ms) => of$(Boolean(ms?.[0]))),

View file

@ -7,7 +7,7 @@ import Animated from 'react-native-reanimated';
import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import {fetchChannelById, joinChannel, switchToChannelById} from '@actions/remote/channel';
import {fetchPostById, fetchPostsAround} from '@actions/remote/post';
import {fetchPostById, fetchPostsAround, fetchPostThread} from '@actions/remote/post';
import {addUserToTeam, fetchTeamByName, removeUserFromTeam} from '@actions/remote/team';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
@ -34,6 +34,7 @@ import type PostModel from '@typings/database/models/servers/post';
type Props = {
channel?: ChannelModel;
rootId?: string;
teamName?: string;
isTeamMember?: boolean;
currentUserId: string;
@ -88,6 +89,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
color: theme.centerChannelColor,
...typography('Heading', 300),
},
description: {
color: theme.centerChannelColor,
...typography('Body', 100),
},
postList: {
flex: 1,
},
@ -116,8 +121,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
}),
);
const POSTS_LIMIT = 5;
function Permalink({
channel,
rootId,
isCRTEnabled,
postId,
teamName,
@ -144,12 +152,18 @@ function Permalink({
useEffect(() => {
(async () => {
if (channelId) {
const data = await fetchPostsAround(serverUrl, channelId, postId, 5, isCRTEnabled);
let data;
const loadThreadPosts = isCRTEnabled && rootId;
if (loadThreadPosts) {
data = await fetchPostThread(serverUrl, rootId);
} else {
data = await fetchPostsAround(serverUrl, channelId, postId, POSTS_LIMIT, isCRTEnabled);
}
if (data.error) {
setError({unreachable: true});
}
if (data?.posts) {
setPosts(data.posts);
setPosts(loadThreadPosts ? processThreadPosts(data.posts, postId) : data.posts);
}
setLoading(false);
return;
@ -241,7 +255,7 @@ function Permalink({
});
setLoading(false);
})();
}, [channelId, teamName]);
}, [channelId, rootId, isCRTEnabled, teamName]);
const handleClose = useCallback(() => {
if (error?.joinedTeam && error.teamId) {
@ -295,11 +309,13 @@ function Permalink({
<View style={style.postList}>
<PostList
highlightedId={postId}
isCRTEnabled={isCRTEnabled}
posts={posts}
location={Screens.PERMALINK}
lastViewedAt={0}
shouldShowJoinLeaveMessages={false}
channelId={channel!.id}
rootId={rootId}
testID='permalink.post_list'
nativeID={Screens.PERMALINK}
highlightPinnedOrSaved={false}
@ -343,13 +359,32 @@ function Permalink({
/>
</TouchableOpacity>
<View style={style.titleContainer}>
<Text
ellipsizeMode='tail'
numberOfLines={1}
style={style.title}
>
{channel?.displayName}
</Text>
{isCRTEnabled && rootId ? (
<FormattedText
id='thread.header.thread'
defaultMessage='Thread'
style={style.title}
/>
) : (
<Text
ellipsizeMode='tail'
numberOfLines={1}
style={style.title}
>
{channel?.displayName}
</Text>
)}
{Boolean(isCRTEnabled && rootId) && (
<FormattedText
ellipsizeMode='tail'
id='thread.header.thread_in'
defaultMessage='in {channelName}'
values={{
channelName: channel?.displayName,
}}
style={style.description}
/>
)}
</View>
</View>
{showHeaderDivider && (
@ -363,4 +398,11 @@ function Permalink({
);
}
// Get the posts around the focused post
function processThreadPosts(posts: PostModel[], postId: string) {
posts.sort((a, b) => b.createAt - a.createAt);
const postIndex = posts.findIndex((p) => p.id === postId);
return posts.slice(postIndex - POSTS_LIMIT, postIndex + POSTS_LIMIT + 1);
}
export default Permalink;