Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/common/src/context/comments/commentsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ type CommentSectionProviderProps<NavigationProp> = {
) => void
navigation?: NavigationProp
closeDrawer?: () => void
/**
* Close the comment drawer AND any open now-playing drawer behind it.
* Passed from CommentDrawerProvider and threaded through to CommentBlock
* so that tapping a user link / mention inside a comment can close both
* drawers before navigating away.
*
* This must be threaded via context (rather than calling useCommentDrawer()
* directly in CommentBlock) because @gorhom/bottom-sheet portals content
* outside the CommentDrawerContext.Provider's React tree.
*/
closeAndExitNowPlaying?: (trackId: ID) => void
uid?: string
/**
* Opaque source tag for the playback queue when the user plays the track
Expand Down Expand Up @@ -94,6 +105,7 @@ export function CommentSectionProvider<NavigationProp>(
setReplyingAndEditingState,
navigation,
closeDrawer,
closeAndExitNowPlaying,
playbackSource = 'comments'
} = props
const { data: track } = useTrack(entityId)
Expand Down Expand Up @@ -263,6 +275,7 @@ export function CommentSectionProvider<NavigationProp>(
loadMorePages: handleLoadMorePages,
navigation,
closeDrawer: handleCloseDrawer,
closeAndExitNowPlaying,
hasNewComments
}}
>
Expand Down
13 changes: 9 additions & 4 deletions packages/mobile/src/components/comments/CommentBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { UserLink } from '../user-link'
import { ArtistPick } from './ArtistPick'
import { CommentActionBar } from './CommentActionBar'
import { CommentBadge } from './CommentBadge'
import { useCommentDrawer } from './CommentDrawerContext'
import { CommentText } from './CommentText'
import { Timestamp } from './Timestamp'
import { TimestampLink } from './TimestampLink'
Expand All @@ -43,15 +42,21 @@ export const CommentBlockInternal = (
}
) => {
const { comment, isPreview, parentCommentId, highlightedCommentId } = props
const { artistId, track, navigation } = useCurrentCommentSection()
const { artistId, track, navigation, closeAndExitNowPlaying } =
useCurrentCommentSection()
// Use this for in-drawer navigation (profile pic, user link, mentions)
// so the destination screen is visible once we navigate. The section
// context's `closeDrawer` would only close the comment drawer and leave
// the now-playing drawer covering the destination.
const { closeAndExitNowPlaying } = useCommentDrawer()
//
// closeAndExitNowPlaying is threaded through CommentSectionContext rather
// than read directly from useCommentDrawer() because @gorhom/portal renders
// BottomSheetModal content at a PortalHost that sits *outside* the
// CommentDrawerContext.Provider in the React tree — calling useCommentDrawer()
// here would throw every time a comment renders.
const trackIdForCloseAll = track.track_id
const handleNavigateAway = useCallback(() => {
closeAndExitNowPlaying(trackIdForCloseAll)
closeAndExitNowPlaying?.(trackIdForCloseAll)
}, [closeAndExitNowPlaying, trackIdForCloseAll])
const {
id: commentId,
Expand Down
12 changes: 12 additions & 0 deletions packages/mobile/src/components/comments/CommentDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { ProfilePicture } from 'app/components/core'
import { UserBadges } from 'app/components/user-badges'
import { LoadingSpinner } from 'app/harmony-native/components/LoadingSpinner/LoadingSpinner'

import { useCommentDrawer } from './CommentDrawerContext'
import { CommentDrawerForm } from './CommentDrawerForm'
import { CommentDrawerHeader } from './CommentDrawerHeader'
import { CommentSkeleton } from './CommentSkeleton'
Expand Down Expand Up @@ -239,6 +240,16 @@ export const CommentDrawer = (props: CommentDrawerProps) => {
const insets = useSafeAreaInsets()
const commentListRef = useRef<BottomSheetFlatListMethods>(null)

// `closeAndExitNowPlaying` is read here (inside CommentDrawerContext.Provider)
// and threaded into CommentSectionContext so that CommentBlock can access it
// without calling useCommentDrawer() directly. We must NOT call
// useCommentDrawer() from inside the BottomSheetModal portal content because
// @gorhom/portal renders portal children at a PortalHost that is a *sibling*
// of the CommentDrawerContext.Provider in the tree, so the context is
// unreachable from there — causing a 100%-reproducible crash the moment any
// comment renders.
const { closeAndExitNowPlaying } = useCommentDrawer()

// When the drawer is opened from a lineup tile (e.g. the feed), the full
// track may not yet be in the query cache. CommentSectionProvider returns
// null until the track loads, which would render an empty bottom sheet, so
Expand Down Expand Up @@ -353,6 +364,7 @@ export const CommentDrawer = (props: CommentDrawerProps) => {
setReplyingAndEditingState={setReplyingAndEditingState}
navigation={navigation}
closeDrawer={handleCloseDrawer}
closeAndExitNowPlaying={closeAndExitNowPlaying}
playbackSource={playbackSource}
>
<CommentDrawerHeader minimal={autoCompleteActive} />
Expand Down
8 changes: 7 additions & 1 deletion packages/mobile/src/screens/app-screen/AppTabScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,13 @@ export const AppTabScreen = ({ baseScreen, Stack }: AppTabScreenProps) => {
<Stack.Screen
name='Profile'
component={ProfileScreen}
options={{ headerShown: false }}
// Profile uses a collapsible tab view (horizontal pager + vertical
// scroll). The global `fullScreenGestureEnabled: true` makes the
// swipe-to-pop recognizer span the whole screen, so a slightly diagonal
// vertical scroll gets hijacked as a back gesture. Restrict swipe-back
// to the left edge here (same treatment as the Chat screen) so
// mid-screen scrolling reaches the list untouched.
options={{ headerShown: false, fullScreenGestureEnabled: false }}
/>
<Stack.Group>
<Stack.Screen name='Followers' component={FollowersScreen} />
Expand Down
Loading