diff options
author | Hailey <me@haileyok.com> | 2024-05-06 08:48:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-06 08:48:08 -0700 |
commit | ae7626ce6ed08059c161345046b6037313fc2505 (patch) | |
tree | 16c78aaba06019feaa2a5c3e1b507f1258250454 | |
parent | bc070199114a4cf5971dea09c381ce84a2c78d5f (diff) | |
download | voidsky-ae7626ce6ed08059c161345046b6037313fc2505.tar.zst |
[🐴] Finalize web message screen (#3868)
* add `onStartReached` to web list * fix `rootMargin` * Add `contain`, handle scroll events * improve types, fix typo * simplify * adjust `scrollToTop` and `scrollToOffset` to support `contain`, add `scrollToEnd` * rename `handleWindowScroll` to `handleScroll` * support basic `maintainVisibleContentPosition` * rename `contain` to `containWeb` * remove unnecessary `flex: 1` * add missing props * add root prop to `Visibility` * add root prop to `Visibility` * revert adding `maintainVisibleContentPosition` * remove unnecessary wrapper * add style * oops * maintain position for web * always apply `flex: 1` to styles when contained * add a contained list to storybook * make `onScroll` a worklet in storybook * revert test code * remove unnecessary `flex: 1`
-rw-r--r-- | src/screens/Messages/Conversation/MessagesList.tsx | 81 | ||||
-rw-r--r-- | src/view/com/util/List.web.tsx | 1 |
2 files changed, 47 insertions, 35 deletions
diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx index e00cf11cd..7068097fc 100644 --- a/src/screens/Messages/Conversation/MessagesList.tsx +++ b/src/screens/Messages/Conversation/MessagesList.tsx @@ -94,6 +94,9 @@ export function MessagesList() { // the bottom. const isAtBottom = useSharedValue(true) + // This will be used on web to assist in determing if we need to maintain the content offset + const isAtTop = useSharedValue(true) + // Used to keep track of the current content height. We'll need this in `onScroll` so we know when to start allowing // onStartReached to fire. const contentHeight = useSharedValue(0) @@ -116,6 +119,15 @@ export function MessagesList() { // we will not scroll whenever new items get prepended to the top. const onContentSizeChange = useCallback( (_: number, height: number) => { + // Because web does not have `maintainVisibleContentPosition` support, we will need to manually scroll to the + // previous offset whenever we add new content to the previous offset whenever we add new content to the list. + if (isWeb && isAtTop.value && hasInitiallyScrolled) { + flatListRef.current?.scrollToOffset({ + animated: false, + offset: height - contentHeight.value, + }) + } + contentHeight.value = height // This number _must_ be the height of the MaybeLoader component @@ -133,6 +145,7 @@ export function MessagesList() { contentHeight, hasInitiallyScrolled, isAtBottom.value, + isAtTop.value, isMomentumScrolling, ], ) @@ -164,6 +177,7 @@ export function MessagesList() { // Most apps have a little bit of space the user can scroll past while still automatically scrolling ot the bottom // when a new message is added, hence the 100 pixel offset isAtBottom.value = e.contentSize.height - 100 < bottomOffset + isAtTop.value = e.contentOffset.y <= 1 // This number _must_ be the height of the MaybeLoader component. // We don't check for zero, because the `MaybeLoader` component is always present, even when not visible, which @@ -172,7 +186,7 @@ export function MessagesList() { runOnJS(setHasInitiallyScrolled)(true) } }, - [contentHeight.value, hasInitiallyScrolled, isAtBottom], + [contentHeight.value, hasInitiallyScrolled, isAtBottom, isAtTop], ) const onMomentumEnd = React.useCallback(() => { @@ -211,40 +225,37 @@ export function MessagesList() { keyboardVerticalOffset={isIOS ? topInset : 0} behavior="padding" contentContainerStyle={a.flex_1}> - {/* This view keeps the scroll bar and content within the CenterView on web, otherwise the entire window would scroll */} - {/* @ts-expect-error web only */} - <View style={[a.flex_1, isWeb && {'overflow-y': 'scroll'}]}> - {/* Custom scroll provider so that we can use the `onScroll` event in our custom List implementation */} - <ScrollProvider onScroll={onScroll} onMomentumEnd={onMomentumEnd}> - <List - ref={flatListRef} - data={chat.status === ConvoStatus.Ready ? chat.items : undefined} - renderItem={renderItem} - keyExtractor={keyExtractor} - disableVirtualization={true} - initialNumToRender={isWeb ? 50 : 25} - maxToRenderPerBatch={isWeb ? 50 : 25} - keyboardDismissMode="on-drag" - keyboardShouldPersistTaps="handled" - maintainVisibleContentPosition={{ - minIndexForVisible: 1, - }} - contentContainerStyle={{paddingHorizontal: 10}} - removeClippedSubviews={false} - onContentSizeChange={onContentSizeChange} - onStartReached={onStartReached} - onScrollToIndexFailed={onScrollToIndexFailed} - scrollEventThrottle={100} - ListHeaderComponent={ - <MaybeLoader - isLoading={ - chat.status === ConvoStatus.Ready && chat.isFetchingHistory - } - /> - } - /> - </ScrollProvider> - </View> + {/* Custom scroll provider so that we can use the `onScroll` event in our custom List implementation */} + <ScrollProvider onScroll={onScroll} onMomentumEnd={onMomentumEnd}> + <List + ref={flatListRef} + data={chat.status === ConvoStatus.Ready ? chat.items : undefined} + renderItem={renderItem} + keyExtractor={keyExtractor} + disableVirtualization={true} + initialNumToRender={isWeb ? 50 : 25} + maxToRenderPerBatch={isWeb ? 50 : 25} + keyboardDismissMode="on-drag" + keyboardShouldPersistTaps="handled" + maintainVisibleContentPosition={{ + minIndexForVisible: 1, + }} + containWeb={true} + contentContainerStyle={{paddingHorizontal: 10}} + removeClippedSubviews={false} + onContentSizeChange={onContentSizeChange} + onStartReached={onStartReached} + onScrollToIndexFailed={onScrollToIndexFailed} + scrollEventThrottle={100} + ListHeaderComponent={ + <MaybeLoader + isLoading={ + chat.status === ConvoStatus.Ready && chat.isFetchingHistory + } + /> + } + /> + </ScrollProvider> <MessageInput onSendMessage={onSendMessage} scrollToEnd={scrollToEnd} /> </KeyboardAvoidingView> ) diff --git a/src/view/com/util/List.web.tsx b/src/view/com/util/List.web.tsx index e5c427f13..73000d95f 100644 --- a/src/view/com/util/List.web.tsx +++ b/src/view/com/util/List.web.tsx @@ -143,6 +143,7 @@ function ListImpl<ItemT>( scrollToTop() { getScrollableNode()?.scrollTo({top: 0}) }, + scrollToOffset({ animated, offset, |