diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-01 16:15:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-01 16:15:40 -0700 |
commit | f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b (patch) | |
tree | a9da6032bcbd587d92fd1030e698aea2dbef9f72 /src/view/com/pager/Pager.tsx | |
parent | f9944b55e26fe6109bc2e7a25b88979111470ed9 (diff) | |
download | voidsky-f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b.tar.zst |
Lists updates: curate lists and blocklists (#1689)
* Add lists screen * Update Lists screen and List create/edit modal to support curate lists * Rework the ProfileList screen and add curatelist support * More ProfileList progress * Update list modals * Rename mutelists to modlists * Layout updates/fixes * More layout fixes * Modal fixes * List list screen updates * Update feed page to give more info * Layout fixes to ListAddUser modal * Layout fixes to FlatList and Feed on desktop * Layout fix to LoadLatestBtn on Web * Handle did resolution before showing the ProfileList screen * Rename the CustomFeed routes to ProfileFeed for consistency * Fix layout issues with the pager and feeds * Factor out some common code * Fix UIs for mobile * Fix user list rendering * Fix: dont bubble custom feed errors in the merge feed * Refactor feed models to reduce usage of the SavedFeeds model * Replace CustomFeedModel with FeedSourceModel which abstracts feed-generators and lists * Add the ability to pin lists * Add pinned lists to mobile * Remove dead code * Rework the ProfileScreenHeader to create more real-estate for action buttons * Improve layout behavior on web mobile breakpoints * Refactor feed & list pages to use new Tabs layout component * Refactor to ProfileSubpageHeader * Implement modlist block and mute * Switch to new api and just modify state on modlist actions * Fix some UI overflows * Fix: dont show edit buttons on lists you dont own * Fix alignment issue on long titles * Improve loading and error states for feeds & lists * Update list dropdown icons for ios * Fetch feed display names in the mergefeed * Improve rendering off offline feeds in the feed-listing page * Update Feeds listing UI to react to changes in saved/pinned state * Refresh list and feed on posts tab press * Fix pinned feed ordering UI * Fixes to list pinning * Remove view=simple qp * Add list to feed tuners * Render richtext * Add list href * Add 'view avatar' * Remove unused import * Fix missing import * Correctly reflect block by list state * Replace the <Tabs> component with the more effective <PagerWithHeader> component * Improve the responsiveness of the PagerWithHeader * Fix visual jank in the feed loading state * Improve performance of the PagerWithHeader * Fix a case that would cause the header to animate too aggressively * Add the ability to scroll to top by tapping the selected tab * Fix unit test runner * Update modlists test * Add curatelist tests * Fix: remove link behavior in ListAddUser modal * Fix some layout jank in the PagerWithHeader on iOS * Simplify ListItems header rendering * Wait for the appview to recognize the list before proceeding with list creation * Fix glitch in the onPageSelecting index of the Pager * Fix until() * Copy fix Co-authored-by: Eric Bailey <git@esb.lol> --------- Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/view/com/pager/Pager.tsx')
-rw-r--r-- | src/view/com/pager/Pager.tsx | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index 39ba29bda..531a41ee2 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -1,6 +1,10 @@ import React, {forwardRef} from 'react' import {Animated, View} from 'react-native' -import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' +import PagerView, { + PagerViewOnPageSelectedEvent, + PagerViewOnPageScrollEvent, + PageScrollStateChangedNativeEvent, +} from 'react-native-pager-view' import {s} from 'lib/styles' export type PageSelectedEvent = PagerViewOnPageSelectedEvent @@ -21,6 +25,7 @@ interface Props { initialPage?: number renderTabBar: RenderTabBarFn onPageSelected?: (index: number) => void + onPageSelecting?: (index: number) => void testID?: string } export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( @@ -31,11 +36,15 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( initialPage = 0, renderTabBar, onPageSelected, + onPageSelecting, testID, }: React.PropsWithChildren<Props>, ref, ) { const [selectedPage, setSelectedPage] = React.useState(0) + const lastOffset = React.useRef(0) + const lastDirection = React.useRef(0) + const scrollState = React.useRef('') const pagerView = React.useRef<PagerView>(null) React.useImperativeHandle(ref, () => ({ @@ -50,15 +59,61 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( [setSelectedPage, onPageSelected], ) + const onPageScroll = React.useCallback( + (e: PagerViewOnPageScrollEvent) => { + const {position, offset} = e.nativeEvent + if (offset === 0) { + // offset hits 0 in some awkward spots so we ignore it + return + } + // NOTE + // we want to call `onPageSelecting` as soon as the scroll-gesture + // enters the "settling" phase, which means the user has released it + // we can't infer directionality from the scroll information, so we + // track the offset changes. if the offset delta is consistent with + // the existing direction during the settling phase, we can say for + // certain where it's going and can fire + // -prf + if (scrollState.current === 'settling') { + if (lastDirection.current === -1 && offset < lastOffset.current) { + onPageSelecting?.(position) + lastDirection.current = 0 + } else if ( + lastDirection.current === 1 && + offset > lastOffset.current + ) { + onPageSelecting?.(position + 1) + lastDirection.current = 0 + } + } else { + if (offset < lastOffset.current) { + lastDirection.current = -1 + } else if (offset > lastOffset.current) { + lastDirection.current = 1 + } + } + lastOffset.current = offset + }, + [lastOffset, lastDirection, onPageSelecting], + ) + + const onPageScrollStateChanged = React.useCallback( + (e: PageScrollStateChangedNativeEvent) => { + scrollState.current = e.nativeEvent.pageScrollState + }, + [scrollState], + ) + const onTabBarSelect = React.useCallback( (index: number) => { pagerView.current?.setPage(index) + onPageSelecting?.(index) }, - [pagerView], + [pagerView, onPageSelecting], ) return ( - <View testID={testID}> + <View testID={testID} style={s.flex1}> {tabBarPosition === 'top' && renderTabBar({ selectedPage, @@ -66,9 +121,11 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( })} <AnimatedPagerView ref={pagerView} - style={s.h100pct} + style={s.flex1} initialPage={initialPage} - onPageSelected={onPageSelectedInner}> + onPageScrollStateChanged={onPageScrollStateChanged} + onPageSelected={onPageSelectedInner} + onPageScroll={onPageScroll}> {children} </AnimatedPagerView> {tabBarPosition === 'bottom' && |