Skip to content

Commit

Permalink
comment chain screen
Browse files Browse the repository at this point in the history
  • Loading branch information
gkasdorf committed Oct 14, 2023
1 parent 6a8ee05 commit 65c706b
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 17 deletions.
13 changes: 8 additions & 5 deletions src/api/common/ApiInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ class ApiInstance {
async getComments(
postId: number,
addToPost = true,
parentId?: number,
): Promise<GetCommentsResponse | undefined> {
const settings = useSettingsStore.getState();
const post = usePostStore.getState().posts.get(postId);
Expand All @@ -537,18 +538,20 @@ class ApiInstance {
max_depth: 5,
limit: 1,
sort: settings.defaultCommentSort,
...(parentId != null && { parent_id: parentId }),
});

if (res === undefined || !addToPost) {
return res;
}
if (res == null) return res;

const builtComments = buildCommentChains(res.comments);

addCommentsToPost(postId, builtComments.commentInfo);
addComments(res.comments);

return res;
if (addToPost) {
addCommentsToPost(postId, builtComments.commentInfo);
}

return undefined;
} catch (e: any) {
ApiInstance.handleError(e.toString());
return undefined;
Expand Down
11 changes: 7 additions & 4 deletions src/components/Comment/components/CommentChain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import React, { useCallback } from 'react';
import { ICommentInfo } from '@src/types';
import { PressableComment } from '@components/Comment/components/Comment';
import { setPostCommentHidden } from '@src/state/post/actions/setPostCommentHidden';
import { ViewToken } from 'react-native';
import { SharedValue } from 'react-native-reanimated';
import CommentShowMoreButton from '@components/Comment/components/CommentShowMoreButton';

interface IProps {
commentInfo: ICommentInfo;
viewableItems: SharedValue<ViewToken[]>;
ignoreLoadMore?: boolean;
}

function CommentChain({
commentInfo,
viewableItems,
ignoreLoadMore = false,
}: IProps): React.JSX.Element | null {
const onCommentPress = useCallback(() => {
setPostCommentHidden(commentInfo, !commentInfo.collapsed);
Expand All @@ -22,6 +21,10 @@ function CommentChain({
return null;
}

if (commentInfo.showLoadMore && !ignoreLoadMore) {
return <CommentShowMoreButton commentInfo={commentInfo} />;
}

return (
<PressableComment
onPress={onCommentPress}
Expand Down
48 changes: 48 additions & 0 deletions src/components/Comment/components/CommentShowMoreButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useCallback } from 'react';
import { ICommentInfo } from '@src/types';
import VStack from '@components/Common/Stack/VStack';
import { Separator, Text } from 'tamagui';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useNavigation } from '@react-navigation/core';
import { Pressable } from 'react-native';

interface IProps {
commentInfo: ICommentInfo;
}

function CommentShowMoreButton({ commentInfo }: IProps): React.JSX.Element {
const navigation = useNavigation<NativeStackNavigationProp<any>>();

const onPress = useCallback(() => {
navigation.navigate('CommentChain', {
commentInfo,
});
}, []);

return (
<Pressable onPress={onPress}>
<VStack backgroundColor="$fg">
<VStack
marginLeft={commentInfo.depth * 10}
marginVertical="$2"
borderLeftColor="$secondary"
borderLeftWidth={2}
paddingHorizontal="$2"
paddingVertical="$1"
>
<Text
color="$secondary"
fontStyle="italic"
marginBottom="$1"
margin="auto"
>
Show More Comments...
</Text>
</VStack>
<Separator borderColor="$bg" marginLeft={commentInfo.depth * 10 + 10} />
</VStack>
</Pressable>
);
}

export default React.memo(CommentShowMoreButton);
54 changes: 54 additions & 0 deletions src/components/Comment/screens/CommentChainScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useCallback, useMemo } from 'react';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import VStack from '@components/Common/Stack/VStack';
import { ICommentInfo } from '@src/types';
import { usePostCommentsInfo } from '@src/state/post/postStore';
import { FlatList, ListRenderItemInfo } from 'react-native';
import CommentChain from '@components/Comment/components/CommentChain';

interface IProps {
navigation: NativeStackNavigationProp<any>;
route: any;
}

const keyExtractor = (item: ICommentInfo): string => item.commentId.toString();

export default function CommentChainScreen({
navigation,
route,
}: IProps): React.JSX.Element {
const params = route.params;
const commentInfo = params.commentInfo as ICommentInfo;

const commentsInfo = usePostCommentsInfo(commentInfo.postId);

const commentsToShow = useMemo(
() =>
commentsInfo?.filter((item) =>
item.path.includes(commentInfo.parentId!.toString()),
),
[],
);

const renderItem = useCallback(
({ item }: ListRenderItemInfo<ICommentInfo>): React.JSX.Element => {
return <CommentChain commentInfo={item} ignoreLoadMore />;
},
[],
);

return (
<VStack flex={1} backgroundColor="$bg">
<FlatList
renderItem={renderItem}
data={commentsToShow}
keyExtractor={keyExtractor}
initialNumToRender={10}
maxToRenderPerBatch={5}
updateCellsBatchingPeriod={300}
windowSize={10}
removeClippedSubviews={true}
/>
</VStack>
);
}
9 changes: 9 additions & 0 deletions src/components/Navigation/MainScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NativeStackNavigatorProps } from 'react-native-screens/lib/typescript/n
import FeedIndexScreen from '@components/Feed/screens/FeedIndexScreen';
import PostScreen from '@components/Post/screens/PostScreen';
import MainFeed from '@components/Feed/components/MainFeed';
import CommentChainScreen from '@components/Comment/screens/CommentChainScreen';

export default function MainScreens(
stack: TypedNavigator<
Expand Down Expand Up @@ -46,6 +47,14 @@ export default function MainScreens(
headerShown: true,
}}
/>
<stack.Screen
name="CommentChain"
component={CommentChainScreen}
options={{
headerShown: true,
headerTitle: 'More Comments',
}}
/>
<stack.Screen
name="Community"
component={MainFeed}
Expand Down
13 changes: 7 additions & 6 deletions src/components/Post/screens/PostScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import {
usePostCommentsInfo,
Expand All @@ -11,10 +11,9 @@ import Post from '@components/Post/components/Post';
import instance from '@api/Instance';
import { ICommentInfo } from '@src/types';
import CommentChain from '@components/Comment/components/CommentChain';
import { FlatList, ViewToken } from 'react-native';
import { FlatList } from 'react-native';
import { useLoadData } from '@hooks/useLoadData';
import FeedLoadingIndicator from '@components/Feed/components/Feed/FeedLoadingIndicator';
import { useSharedValue } from 'react-native-reanimated';

interface RenderItem {
item: ICommentInfo;
Expand All @@ -37,7 +36,9 @@ export default function PostScreen({
const postTitle = usePostTitle(postId);
const postCommentsInfo = usePostCommentsInfo(postId);

const viewableItems = useSharedValue<ViewToken[]>([]);
const postsToShow = useMemo(() => {
return postCommentsInfo?.filter((commentInfo) => commentInfo.showInPost);
}, [postCommentsInfo]);

const { isLoading, isError } = useLoadData(async () => {
return await instance.getComments(postId);
Expand All @@ -50,7 +51,7 @@ export default function PostScreen({
}, [postTitle]);

const renderItem = useCallback(({ item }: RenderItem): React.JSX.Element => {
return <CommentChain commentInfo={item} viewableItems={viewableItems} />;
return <CommentChain commentInfo={item} />;
}, []);

if (!postLoaded) return <LoadingScreen />;
Expand All @@ -59,7 +60,7 @@ export default function PostScreen({
<VStack flex={1}>
<FlatList
renderItem={renderItem}
data={postCommentsInfo}
data={postsToShow}
keyExtractor={keyExtractor}
initialNumToRender={10}
maxToRenderPerBatch={5}
Expand Down
18 changes: 17 additions & 1 deletion src/helpers/comments/buildCommentChains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ let flattenedComments: ICommentInfo[] = [];
const flattenComments = (commentsInfo: ICommentInfo[]): void => {
for (const commentInfo of commentsInfo) {
flattenedComments.push(commentInfo);
flattenComments(commentInfo.replies);

if (commentInfo.replies != null) {
flattenComments(commentInfo.replies);
}
}
};

Expand Down Expand Up @@ -39,6 +42,9 @@ export const buildCommentChains = (
collapsed: false,
hidden: false,
path,
showInPost: true,
showLoadMore: false,
topId: pathIds[1],
});
}
}
Expand All @@ -64,12 +70,16 @@ const buildReplies = (
view.comment.path.includes(`.${parentId}.`),
);

let i = 0;

for (const view of replyCommentViews) {
const { path, id } = view.comment;

const pathIds = path.split('.').map(Number);
const currentParentId = pathIds[pathIds.length - 2];

const depth = pathIds.length - 2;

if (parentId === currentParentId) {
replies.push({
postId: view.post.id,
Expand All @@ -79,7 +89,13 @@ const buildReplies = (
collapsed: false,
hidden: false,
path,
showInPost: depth <= 1 && i <= 1,
showLoadMore: depth === 1 && i === 1,
topId: pathIds[1],
parentId: pathIds[pathIds.length - 2],
});

i++;
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/types/ICommentInfo.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
export interface ICommentInfo {
postId: number;
commentId: number;
replies: ICommentInfo[];
replies: ICommentInfo[] | undefined;
depth: number;
hidden: boolean;
collapsed: boolean;
path: string;
topId: number;
parentId?: number;

showInPost: boolean;
showLoadMore: boolean;
}

0 comments on commit 65c706b

Please sign in to comment.