diff --git a/src/components/Comment/Comment.styles.js b/src/components/Comment/Comment.styles.js index f2539edb5..812a6f71b 100644 --- a/src/components/Comment/Comment.styles.js +++ b/src/components/Comment/Comment.styles.js @@ -50,7 +50,7 @@ export default { fontSize: 12 }, replyLink: { - flexDirection: 'row', + flexDirection: 'row' }, // replyLinkText: { // fontSize: 12, diff --git a/src/components/Comments/Comments.js b/src/components/Comments/Comments.js index bec2cb461..98dc36eae 100644 --- a/src/components/Comments/Comments.js +++ b/src/components/Comments/Comments.js @@ -17,6 +17,7 @@ import { FETCH_COMMENTS } from 'store/constants' function Comments ({ postId, + selectedCommentId, header: providedHeader = null, style = {}, showMember, @@ -41,9 +42,23 @@ function Comments ({ const sectionIndex = section.comment.sectionIndex const itemIndex = section.data.find(subComment => subCommentId === subComment.id)?.itemIndex || section.data.length + 1 - commentsListRef?.current.scrollToLocation({ sectionIndex, itemIndex, viewPosition }) + commentsListRef?.current.scrollToLocation({ sectionIndex, itemIndex, viewPosition, animated: true }) }, [sections]) + const scrollToCommentById = useCallback((commentId) => { + comments.forEach(comment => { + if (comment.id === selectedCommentId) { + selectComment(comment) + } else { + comment.subComments.forEach(subComment => { + if (selectedCommentId === subComment.id) { + selectComment(subComment) + } + }) + } + }) + }) + const selectComment = useCallback(comment => { setHighlightedComment(comment) scrollToComment(comment) @@ -60,6 +75,12 @@ function Comments ({ dispatch(fetchCommentsAction({ postId })) }, [dispatch, postId]) + useEffect(() => { + if (!pending && selectedCommentId) { + scrollToCommentById(selectedCommentId) + } + }, [pending, selectedCommentId]) + const Header = () => ( <> {providedHeader} @@ -108,6 +129,8 @@ function Comments ({ ) } + if (pending) return + return ( comment.id} initialScrollIndex={0} + getItemLayout={(data, index) => ({ + length: 50, + offset: 50 * index, + index + })} // keyboardShouldPersistTaps='handled' + onScrollToIndexFailed={(error) => { + console.log('!!!! error', error) + // this.commentsListRef.scrollToOffset({ offset: error.averageItemLength * error.index, animated: false }) + // setTimeout(() => { + // if (this.state.data.length !== 0 && this.commentsListRef !== null) { + // this.commentsListRef.scrollToIndex({ index: error.index, animated: true }) + // } + // }, 100) + }} keyboardShouldPersistTaps='never' keyboardDismissMode={isIOS ? 'interactive' : 'on-drag'} {...panHandlers} diff --git a/src/screens/NotificationsList/NotificationsList.store.js b/src/screens/NotificationsList/NotificationsList.store.js index 01be414cc..d5a0cdeed 100644 --- a/src/screens/NotificationsList/NotificationsList.store.js +++ b/src/screens/NotificationsList/NotificationsList.store.js @@ -153,7 +153,7 @@ export function refineActivity ({ action, actor, comment, group, post, meta }, { body: `wrote: ${truncateHTML(comment.text)}`, header: 'mentioned you in a comment on', nameInHeader: true, - onPress: () => navigate(modalScreenName('Post Details'), { id: post.id }), + onPress: () => navigate(modalScreenName('Post Details'), { id: post.id, commentId: comment.id }), title: post.title } @@ -161,7 +161,7 @@ export function refineActivity ({ action, actor, comment, group, post, meta }, { return { body: `wrote: ${truncateHTML(comment.text)}`, header: 'New Comment on', - onPress: () => navigate(modalScreenName('Post Details'), { id: post.id }), + onPress: () => navigate(modalScreenName('Post Details'), { id: post.id, commentId: comment.id }), title: post.title } diff --git a/src/screens/NotificationsList/NotificationsList.store.test.js b/src/screens/NotificationsList/NotificationsList.store.test.js index 32ed7104c..103ec7ea6 100644 --- a/src/screens/NotificationsList/NotificationsList.store.test.js +++ b/src/screens/NotificationsList/NotificationsList.store.test.js @@ -105,7 +105,7 @@ describe('selectors/refiners', () => { const notification = session.Notification.withId('1') const actual = store.refineActivity(notification.activity, navigation) actual.onPress() - expect(navigation.navigate).toHaveBeenCalledWith(modalScreenName('Post Details'), { id: '333' }) + expect(navigation.navigate).toHaveBeenCalledWith(modalScreenName('Post Details'), { id: '333', commentId: '1' }) }) it('matches the previous ACTION_COMMENT_MENTION snapshot', () => { @@ -118,7 +118,7 @@ describe('selectors/refiners', () => { const notification = session.Notification.withId('1') const actual = store.refineActivity(notification.activity, navigation) actual.onPress() - expect(navigation.navigate).toHaveBeenCalledWith(modalScreenName('Post Details'), { id: '333' }) + expect(navigation.navigate).toHaveBeenCalledWith(modalScreenName('Post Details'), { id: '333', commentId: '1' }) }) it('matches the previous ACTION_MENTION snapshot', () => { diff --git a/src/screens/PostDetails/PostDetails.js b/src/screens/PostDetails/PostDetails.js index e2ad5f7e4..7ca69fef0 100644 --- a/src/screens/PostDetails/PostDetails.js +++ b/src/screens/PostDetails/PostDetails.js @@ -37,6 +37,7 @@ export default function PostDetails () { const postId = getRouteParam('id', route) const post = useSelector(state => getPresentedPost(state, { postId, forGroupId: currentGroup?.id })) const currentGroup = useSelector(getCurrentGroup) + const selectedCommentId = getRouteParam('commentId', route) const commentsRef = React.useRef() const isModalScreen = useIsModalScreen() @@ -89,6 +90,7 @@ export default function PostDetails () { ({ .orderBy('position').toRefArray() }) -export const getComments = createSelector( - state => orm.session(state.orm), +export const getComments = ormCreateSelector( + orm, (_, props) => props.commentId, (_, props) => props.postId, ({ Comment }, parentComment, post) => { @@ -44,12 +44,12 @@ export const getComments = createSelector( const getCommentResults = makeGetQueryResults(FETCH_COMMENTS) -export const getHasMoreComments = createSelector( - getCommentResults, - get('hasMore') -) +export const getHasMoreComments = state => { + const commentResults = getCommentResults(state) + return commentResults?.hasMore +} -export const getTotalComments = createSelector( - getCommentResults, - get('total') -) +export const getTotalComments = state => { + const commentResults = getCommentResults(state) + return commentResults?.total +} diff --git a/src/util/navigation.js b/src/util/navigation.js index a9a938b79..26353c18e 100644 --- a/src/util/navigation.js +++ b/src/util/navigation.js @@ -7,7 +7,7 @@ export const HYLO_ID_MATCH = '\\d+' export const POST_ID_MATCH = HYLO_ID_MATCH export const OPTIONAL_POST_MATCH = `:detail(post)?/:postId(${POST_ID_MATCH})?/:action(new|edit)?` export const OPTIONAL_NEW_POST_MATCH = ':detail(post)?/:action(new)?' // TODO: need this? -export const POST_DETAIL_MATCH = `:detail(post)/:postId(${POST_ID_MATCH})/:action(edit)?` +export const POST_DETAIL_MATCH = `:detail(post)/:postId(${POST_ID_MATCH})/:action(edit|comments)?/:commentId?` export const REQUIRED_EDIT_POST_MATCH = `:detail(post)/:postId(${POST_ID_MATCH})/:action(edit)` @@ -109,8 +109,8 @@ export function editPostUrl (id, opts = {}, querystringParams = {}) { return postUrl(id, { ...opts, action: 'edit' }, querystringParams) } -export function commentUrl (postId, commentId, opts = {}, querystringParams = {}) { - return `${postUrl(postId, opts, querystringParams)}#comment_${commentId}` +export function postCommentUrl ({ postId, commentId, ...opts }, querystringParams = {}) { + return `${postUrl(postId, opts, querystringParams)}/comments/${commentId}` } // Messages URLs