Skip to content

Commit

Permalink
finished with swiping to change images
Browse files Browse the repository at this point in the history
  • Loading branch information
JediWattson committed Jul 20, 2022
1 parent ad64a2f commit e2e9633
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ const CONST = {
EMOJI_PICKER_HEADER_HEIGHT: 38,

COMPOSER_MAX_HEIGHT: 125,
MAX_HORIZONTAL_SWIPE: 75,

EMAIL: {
CONCIERGE: 'concierge@expensify.com',
Expand Down
21 changes: 15 additions & 6 deletions src/components/AttachmentCarousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Button from './Button';
import * as Expensicons from './Icon/Expensicons';
import styles from '../styles/styles';
import AttachmentView from './AttachmentView';
import SwipeableView from './SwipeableView';
import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL';
import themeColors from '../styles/themes/default';
import reportActionPropTypes from '../pages/home/report/reportActionPropTypes';
Expand All @@ -28,8 +29,8 @@ const propTypes = {

const defaultProps = {
sourceURL: '',
onArrowPress: () => {},
reportActions: {},
onArrowPress: () => {},
};

class AttachmentCarousel extends React.Component {
Expand Down Expand Up @@ -62,7 +63,7 @@ class AttachmentCarousel extends React.Component {
attachments,
sourceURL,
file,
showArrows: !canUseTouchScreen(),
showArrows: canUseTouchScreen(),
isBackDisabled: page === 0,
isForwardDisabled: page === attachments.length - 1,
};
Expand Down Expand Up @@ -113,6 +114,9 @@ class AttachmentCarousel extends React.Component {
* @param {Number} deltaSlide
*/
cycleThroughAttachments(deltaSlide) {
if ((deltaSlide < 0 && this.state.isBackDisabled) || (deltaSlide > 0 && this.state.isForwardDisabled)) {
return;
}
this.setState(({attachments, page}) => {
const nextIndex = page + deltaSlide;
const {sourceURL, file} = this.getAttachment(attachments[nextIndex]);
Expand All @@ -133,10 +137,10 @@ class AttachmentCarousel extends React.Component {
* @param {Object} e
*/
handleArrowPress(e) {
if (e.key === 'ArrowLeft' && !this.state.isBackDisabled) {
if (e.key === 'ArrowLeft') {
this.cycleThroughAttachments(-1);
}
if (e.key === 'ArrowRight' && !this.state.isForwardDisabled) {
if (e.key === 'ArrowRight') {
this.cycleThroughAttachments(1);
}
}
Expand All @@ -145,7 +149,6 @@ class AttachmentCarousel extends React.Component {
return (
<Pressable
style={[styles.attachmentModalArrowsContainer]}
onPress={() => canUseTouchScreen() && this.onShowArrow(!this.state.showArrows)}
onMouseEnter={() => this.onShowArrow(true)}
onMouseLeave={() => this.onShowArrow(false)}
>
Expand All @@ -171,7 +174,13 @@ class AttachmentCarousel extends React.Component {
/>
</>
)}
<AttachmentView sourceURL={this.state.sourceURL} file={this.state.file} />
<SwipeableView
isAnimated
onPress={() => canUseTouchScreen() && this.onShowArrow(!this.state.showArrows)}
onSwipeHorizontal={this.cycleThroughAttachments}
>
<AttachmentView sourceURL={this.state.sourceURL} file={this.state.file} />
</SwipeableView>
</Pressable>

);
Expand Down
84 changes: 68 additions & 16 deletions src/components/SwipeableView/index.native.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,90 @@
import React, {PureComponent} from 'react';
import {PanResponder, View} from 'react-native';
import React, {Component} from 'react';
import {PanResponder, View, Animated} from 'react-native';
import PropTypes from 'prop-types';

import CONST from '../../CONST';

const propTypes = {
children: PropTypes.element.isRequired,

/** Callback to fire when the user swipes down on the child content */
onSwipeDown: PropTypes.func.isRequired,
onSwipeDown: PropTypes.func,

/** Callback to fire when swiping left or right */
onSwipeHorizontal: PropTypes.func,

/** Callback to facility an press event */
onPress: PropTypes.func,

/** should the movement be animated */
isAnimated: PropTypes.bool,
};

class SwipeableView extends PureComponent {
const defaultProps = {
onSwipeDown: () => {},
onSwipeHorizontal: () => {},
onPress: () => {},
isAnimated: false,
};

class SwipeableView extends Component {
constructor(props) {
super(props);

const minimumPixelDistance = CONST.COMPOSER_MAX_HEIGHT;
this.oldY = 0;
if (this.props.isAnimated) {
this.pan = new Animated.ValueXY();
}

this.panResponder = PanResponder.create({
onMoveShouldSetPanResponderCapture: (_event, gestureState) => {
if (gestureState.dy < CONST.COMPOSER_MAX_HEIGHT) { return; }
return true;
},

// The PanResponder gets focus only when the y-axis movement is over minimumPixelDistance
// & swip direction is downwards
onMoveShouldSetPanResponderCapture:
(_event, gestureState) => {
if ((gestureState.dy - this.oldY) > 0 && gestureState.dy > minimumPixelDistance) {
return true;
}
this.oldY = gestureState.dy;
onStartShouldSetPanResponder: () => this.props.isAnimated,
onPanResponderMove: (event, gestureState) => {
if (!this.props.isAnimated) { return; }
return Animated.event([null, {
dx: this.pan.x,
dy: this.pan.y,
}], {useNativeDriver: false})(event, gestureState);
},

// Calls the callback when the swipe down is released; after the completion of the gesture
onPanResponderRelease: this.props.onSwipeDown,
onPanResponderRelease: (event, gestureState) => {
if (!this.props.isAnimated) {
return this.props.onSwipeDown();
}

// For swiping through images, I needed to catch a single press to hide the arrows
if (gestureState.dx === 0 && gestureState.dy === 0) {
return this.props.onPress();
}

if (Math.abs(gestureState.dx) > CONST.MAX_HORIZONTAL_SWIPE) {
const deltaSlide = gestureState.dx > 0 ? -1 : 1;
this.props.onSwipeHorizontal(deltaSlide);
}

Animated.spring(this.pan, {useNativeDriver: false, toValue: {x: 0, y: 0}}).start();
},
});
}

render() {
if (this.props.isAnimated) {
return (
<Animated.View
style={{
transform: [{translateX: this.pan.x}],
}}
// eslint-disable-next-line react/jsx-props-no-spreading
{...this.panResponder.panHandlers}
>
{this.props.children}
</Animated.View>
);
}

return (
// eslint-disable-next-line react/jsx-props-no-spreading
<View {...this.panResponder.panHandlers}>
Expand All @@ -44,5 +95,6 @@ class SwipeableView extends PureComponent {
}

SwipeableView.propTypes = propTypes;
SwipeableView.defaultProps = defaultProps;

export default SwipeableView;

0 comments on commit e2e9633

Please sign in to comment.