[Gekidou MM-40096] Permalink view for replies when CRT is enabled (#6494)
* Permalink for CRT * typo * Condition refactor
This commit is contained in:
parent
102789bbd9
commit
c4c89a8f05
6 changed files with 73 additions and 21 deletions
|
|
@ -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: [],
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ const PostList = ({
|
|||
isCRTEnabled={isCRTEnabled}
|
||||
key={item.id}
|
||||
post={item}
|
||||
rootId={rootId}
|
||||
style={styles.scale}
|
||||
testID={`${testID}.post`}
|
||||
{...postProps}
|
||||
|
|
|
|||
|
|
@ -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]))),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue