Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract gesture logic from MultiGestureCanvas to hooks and improve code #33756

Merged
Merged
Show file tree
Hide file tree
Changes from 129 commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
15b35b3
start migration
chrispader Dec 14, 2023
83df849
continue
chrispader Dec 14, 2023
3a8a606
further type stuff
chrispader Dec 14, 2023
1da2e9a
fix: better gestures
Dec 28, 2023
3d1691d
further improve variable names
Dec 29, 2023
4c0d2c5
extract gesture code to hooks
Dec 29, 2023
2632f75
further simplify
Dec 29, 2023
1413871
improve styles in Lightbox
Dec 29, 2023
dae44fc
rename "isScrolling" prop
Dec 29, 2023
7bcf3f5
add more docs
Dec 29, 2023
a08e2bb
further improve component
Dec 29, 2023
8755916
add and improve comments
chrispader Jan 3, 2024
0e7fe03
remove "swipe down to close gesture"
chrispader Jan 3, 2024
70bd5b7
remove unused props
chrispader Jan 3, 2024
f95f9c6
rename variable
chrispader Jan 3, 2024
610f59f
simplify pinch gesture
chrispader Jan 3, 2024
730a998
fix: variable names
chrispader Jan 3, 2024
0b20554
fix: calculation of total pinch translation
chrispader Jan 3, 2024
9483b8f
rename variables
chrispader Jan 3, 2024
16f2497
improve comments and remove aliases
chrispader Jan 3, 2024
ba75ac9
improve pan gesture code
chrispader Jan 3, 2024
1de9b25
fix: pinch gesture
chrispader Jan 3, 2024
3d93b5e
improve pan gesture code and remove inter-depdendencies of gestures
chrispader Jan 3, 2024
f0c542b
improve pan gesture code
chrispader Jan 3, 2024
58fe25b
simplify pinch gesture callback
chrispader Jan 3, 2024
60b6404
improve comments
chrispader Jan 3, 2024
b1b592a
add more comments
chrispader Jan 3, 2024
55c2662
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 3, 2024
4b48f28
fix: types
chrispader Jan 3, 2024
103e1b2
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 3, 2024
8856caf
fix: eslint
chrispader Jan 3, 2024
b6bbdec
fix: eslint
chrispader Jan 3, 2024
330c1a8
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 4, 2024
f8445e4
remove pager ref
chrispader Jan 4, 2024
937b4b1
update comments
Jan 4, 2024
7e148ee
improve lightbox styles
Jan 4, 2024
da5dca5
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 4, 2024
9b6c8fe
remove onPinchGestureChange callback
Jan 4, 2024
351eb53
fix: carousel arrows
Jan 4, 2024
fe9f43b
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 5, 2024
91b1e17
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 5, 2024
39bcb22
Merge branch '@chrispader/restructure-multi-gesture-canvas' into @chr…
chrispader Jan 5, 2024
fcfa059
migrate hooks
chrispader Jan 5, 2024
2b1793a
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 7, 2024
945fd35
move types
chrispader Jan 7, 2024
369d61d
migrate Lightbox
chrispader Jan 7, 2024
d209ac2
restructure
chrispader Jan 7, 2024
24d34a5
add back propTypes
chrispader Jan 7, 2024
083f37c
simplify props
chrispader Jan 7, 2024
5953370
improve Lightbox
chrispader Jan 7, 2024
8715d7c
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 7, 2024
818f797
Merge branch '@chrispader/restructure-multi-gesture-canvas' into @chr…
chrispader Jan 7, 2024
9c393c4
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 7, 2024
d55844b
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 7, 2024
616e8cb
remove comment
chrispader Jan 8, 2024
3055579
update error supression
chrispader Jan 8, 2024
1f6db1e
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 8, 2024
0b741dd
revert Lightbox changes
chrispader Jan 8, 2024
9429921
fix: revert changes
chrispader Jan 8, 2024
a869e63
fix: hook deps
chrispader Jan 8, 2024
b42422b
more fixes
chrispader Jan 8, 2024
7214c92
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 8, 2024
b10e600
update propTypes
Jan 8, 2024
f1a6f9b
fix: import
chrispader Jan 8, 2024
22ce23e
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 12, 2024
f9ae229
Merge branch 'main' into @chrispader/attachment-gallery-ts-migration
chrispader Jan 12, 2024
a003b32
Merge branch '@chrispader/attachment-gallery-ts-migration' into @chri…
chrispader Jan 12, 2024
95b2e84
remove propTypes
chrispader Jan 12, 2024
b21c8a7
Update src/components/MultiGestureCanvas/useTapGestures.ts
chrispader Jan 15, 2024
6651977
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 15, 2024
e944dc2
address GH comments
chrispader Jan 15, 2024
ac5dff2
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 16, 2024
905ba17
improve and clean up PR
chrispader Jan 16, 2024
71135aa
more improvements
chrispader Jan 16, 2024
397c1aa
rename context type
chrispader Jan 16, 2024
993afa8
further address comments
chrispader Jan 16, 2024
74343c5
simplify Lightbox from https://github.com/Expensify/App/pull/34080
chrispader Jan 16, 2024
27aeea9
fix: arrow buttons
chrispader Jan 16, 2024
6d92147
fix: pager not swiping
chrispader Jan 16, 2024
710a3fb
remove undefined
chrispader Jan 16, 2024
c338116
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 17, 2024
5d8799f
fix: problems
chrispader Jan 17, 2024
c06219a
fix: arrows not showable
chrispader Jan 17, 2024
19350f9
fix: callback deps
chrispader Jan 17, 2024
05ade3c
fix: pdf; don't allow tap when zoomed in
chrispader Jan 18, 2024
fcee0f2
fix: callback prop
chrispader Jan 18, 2024
395e25c
move style
chrispader Jan 18, 2024
8164ff5
memoize style
chrispader Jan 18, 2024
5cba6a8
fix: wrong condition
chrispader Jan 18, 2024
ef114a0
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 18, 2024
e90de14
fix: arrows not shown after pdf is unzoomed
chrispader Jan 18, 2024
773b4dc
improve style memo
chrispader Jan 18, 2024
5a988f6
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 19, 2024
b61949d
fix: arrows in pdf delayed
chrispader Jan 19, 2024
1049b84
improve Lightbox on Android
chrispader Jan 19, 2024
5221cff
fix: lightbox flashing
chrispader Jan 19, 2024
2dc798d
simplify lightbox concurrency
chrispader Jan 19, 2024
08a6c41
add comment
chrispader Jan 19, 2024
0c0e157
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 22, 2024
0446a6d
improve
Jan 22, 2024
acadc33
improve types
Jan 22, 2024
e07475e
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 23, 2024
6d21d62
fix: pdf scroll
Jan 23, 2024
c8770bb
fix: worklet error
Jan 23, 2024
f3b7de5
improve pdf
Jan 23, 2024
c3d1443
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 23, 2024
cc5bb33
remove unused prop
Jan 23, 2024
4b8f183
fix: console errors
Jan 23, 2024
7db6a92
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 23, 2024
7e1e2b3
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 23, 2024
4d00c87
remove redundant isScrollEnabled change
Jan 23, 2024
5f17f2b
remove round function
Jan 23, 2024
5ad1817
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 23, 2024
80bf0ad
move logic to AttachmenCarouselPager
chrispader Jan 23, 2024
a83a16e
remove unusedProp
chrispader Jan 23, 2024
aff821c
fix: onScaleChanged prop
chrispader Jan 23, 2024
1ea4d70
fix: prop types
chrispader Jan 23, 2024
8c6cb24
fix: pager
chrispader Jan 23, 2024
d8d4a29
fix: wrong condition
chrispader Jan 23, 2024
bb91b85
improve readability
chrispader Jan 23, 2024
f54a4b9
fix: state setter
chrispader Jan 24, 2024
fce6a6f
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 24, 2024
2a254de
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 24, 2024
2a2f007
fix: loading issues
chrispader Jan 24, 2024
33dea64
remove unused code
chrispader Jan 24, 2024
a058e3b
simplify condition
chrispader Jan 24, 2024
8fec0d5
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
chrispader Jan 25, 2024
49a6469
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 25, 2024
7bc6f98
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 25, 2024
3a7b24c
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 26, 2024
57d1f7e
add comment
Jan 26, 2024
1594b72
remove empty line?
Jan 26, 2024
d6da8e9
add comment
Jan 26, 2024
f2e4057
add comment
Jan 26, 2024
3817512
simplify usePageScrollHandler
Jan 26, 2024
6aae70b
rename type
Jan 26, 2024
62c1d4f
add cp,,emt
Jan 26, 2024
2d5eb62
improve
Jan 26, 2024
4eaad5a
remove empty line
Jan 26, 2024
9a5a833
rename variable
Jan 26, 2024
55d36a6
add comment
Jan 26, 2024
9a53061
add comment
Jan 26, 2024
718acf0
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 27, 2024
8ddbf36
Merge branch 'main' into @chrispader/restructure-multi-gesture-canvas
Jan 29, 2024
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
1 change: 0 additions & 1 deletion src/components/AttachmentModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,6 @@ function AttachmentModal(props) {
report={props.report}
onNavigate={onNavigate}
source={props.source}
onClose={closeModal}
pecanoro marked this conversation as resolved.
Show resolved Hide resolved
onToggleKeyboard={updateConfirmButtonVisibility}
setDownloadButtonVisibility={setDownloadButtonVisibility}
/>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type {ForwardedRef} from 'react';
import {createContext} from 'react';
import type PagerView from 'react-native-pager-view';
import type {SharedValue} from 'react-native-reanimated';

type AttachmentCarouselPagerContextValue = {
pagerRef: ForwardedRef<PagerView>;
isPagerScrolling: SharedValue<boolean>;
isScrollEnabled: SharedValue<boolean>;
onTap: () => void;
chrispader marked this conversation as resolved.
Show resolved Hide resolved
onScaleChanged: (scale: number) => void;
};

const AttachmentCarouselPagerContext = createContext<AttachmentCarouselPagerContextValue | null>(null);

export default AttachmentCarouselPagerContext;
export type {AttachmentCarouselPagerContextValue};
172 changes: 0 additions & 172 deletions src/components/Attachments/AttachmentCarousel/Pager/index.js

This file was deleted.

143 changes: 143 additions & 0 deletions src/components/Attachments/AttachmentCarousel/Pager/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import type {ForwardedRef} from 'react';
import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {NativeViewGestureHandlerProps} from 'react-native-gesture-handler';
import {createNativeWrapper} from 'react-native-gesture-handler';
import type {PagerViewProps} from 'react-native-pager-view';
import PagerView from 'react-native-pager-view';
import Animated, {useAnimatedProps, useSharedValue} from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';
import AttachmentCarouselPagerContext from './AttachmentCarouselPagerContext';
import usePageScrollHandler from './usePageScrollHandler';

const WrappedPagerView = createNativeWrapper(PagerView) as React.ForwardRefExoticComponent<
PagerViewProps & NativeViewGestureHandlerProps & React.RefAttributes<React.Component<PagerViewProps>>
>;
const AnimatedPagerView = Animated.createAnimatedComponent(WrappedPagerView);

type AttachmentCarouselPagerHandle = {
setPage: (selectedPage: number) => void;
};

type PagerItem = {
key: string;
url: string;
source: string;
};

type AttachmentCarouselPagerProps = {
items: PagerItem[];
renderItem: (props: {item: PagerItem; index: number; isActive: boolean}) => React.ReactNode;
initialIndex: number;
onPageSelected: () => void;
onRequestToggleArrows: (showArrows?: boolean) => void;
};

function AttachmentCarouselPager({items, renderItem, initialIndex, onPageSelected, onRequestToggleArrows}: AttachmentCarouselPagerProps, ref: ForwardedRef<AttachmentCarouselPagerHandle>) {
const styles = useThemeStyles();
const pagerRef = useRef<PagerView>(null);

const scale = useRef(1);
const isPagerScrolling = useSharedValue(false);
const isScrollEnabled = useSharedValue(true);

const activePage = useSharedValue(initialIndex);
const [activePageState, setActivePageState] = useState(initialIndex);

const pageScrollHandler = usePageScrollHandler(
{
onPageScroll: (e) => {
'worklet';

activePage.value = e.position;
isPagerScrolling.value = e.offset !== 0;
},
},
[],
);

useEffect(() => {
setActivePageState(initialIndex);
activePage.value = initialIndex;
}, [activePage, initialIndex]);

const handleScaleChange = useCallback(
chrispader marked this conversation as resolved.
Show resolved Hide resolved
(newScale: number) => {
if (newScale === scale.current) {
return;
}

scale.current = newScale;

const newIsScrollEnabled = newScale === 1;

chrispader marked this conversation as resolved.
Show resolved Hide resolved
if (isScrollEnabled.value === newIsScrollEnabled) {
return;
}

isScrollEnabled.value = newIsScrollEnabled;
onRequestToggleArrows(newIsScrollEnabled);
},
[isScrollEnabled, onRequestToggleArrows],
);

const onTap = useCallback(() => {
chrispader marked this conversation as resolved.
Show resolved Hide resolved
if (!isScrollEnabled.value) {
return;
}

onRequestToggleArrows();
}, [isScrollEnabled.value, onRequestToggleArrows]);

const contextValue = useMemo(
() => ({
pagerRef,
isPagerScrolling,
isScrollEnabled,
onTap,
onScaleChanged: handleScaleChange,
}),
[isPagerScrolling, isScrollEnabled, onTap, handleScaleChange],
);

const animatedProps = useAnimatedProps(() => ({
scrollEnabled: isScrollEnabled.value,
}));

useImperativeHandle<AttachmentCarouselPagerHandle, AttachmentCarouselPagerHandle>(
chrispader marked this conversation as resolved.
Show resolved Hide resolved
ref,
() => ({
setPage: (selectedPage) => {
pagerRef.current?.setPage(selectedPage);
},
}),
[],
);

return (
<AttachmentCarouselPagerContext.Provider value={contextValue}>
<AnimatedPagerView
pageMargin={40}
offscreenPageLimit={1}
onPageScroll={pageScrollHandler}
onPageSelected={onPageSelected}
ref={pagerRef}
style={styles.flex1}
initialPage={initialIndex}
animatedProps={animatedProps}
>
{items.map((item, index) => (
<View
key={item.source}
style={styles.flex1}
>
{renderItem({item, index, isActive: index === activePageState})}
</View>
))}
</AnimatedPagerView>
</AttachmentCarouselPagerContext.Provider>
);
}
AttachmentCarouselPager.displayName = 'AttachmentCarouselPager';

export default React.forwardRef(AttachmentCarouselPager);
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type {PagerViewProps} from 'react-native-pager-view';
import {useEvent, useHandler} from 'react-native-reanimated';

type PageScrollHandler = NonNullable<PagerViewProps['onPageScroll']>;

type PageScrollEventData = Parameters<PageScrollHandler>[0]['nativeEvent'];
type PageScrollContext = Record<string, unknown>;

// Reanimated doesn't expose the type for animated event handlers, therefore we must infer it from the useHandler hook.
// The AnimatedPageScrollHandler type is the type of the onPageScroll prop from react-native-pager-view as an animated handler.
type AnimatedHandlers = Parameters<typeof useHandler<PageScrollEventData, PageScrollContext>>[0];
type AnimatedPageScrollHandler = AnimatedHandlers[string];

type Handlers = {
onPageScroll?: AnimatedPageScrollHandler;
};
type Deps = Parameters<typeof useHandler>[1];

const usePageScrollHandler = (handlers: Handlers, dependencies: Deps): PageScrollHandler => {
chrispader marked this conversation as resolved.
Show resolved Hide resolved
const {context, doDependenciesDiffer} = useHandler(handlers, dependencies);
const subscribeForEvents = ['onPageScroll'];

return useEvent(
(event) => {
'worklet';

const {onPageScroll} = handlers;
if (onPageScroll && event.eventName.endsWith('onPageScroll')) {
onPageScroll(event, context);
}
},
subscribeForEvents,
doDependenciesDiffer,
);
};

export default usePageScrollHandler;
Loading
Loading