Skip to content

Commit

Permalink
reverted back the swipeableview, move events with web-based carousel
Browse files Browse the repository at this point in the history
  • Loading branch information
JediWattson committed Oct 19, 2022
1 parent 5b303d0 commit 0cd79cc
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 156 deletions.
39 changes: 6 additions & 33 deletions src/components/AttachmentCarousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import _ from 'lodash';
import Button from './Button';
import * as Expensicons from './Icon/Expensicons';
import styles from '../styles/styles';
import themeColors from '../styles/themes/default';
import Button from './Button';
import AttachmentView from './AttachmentView';
import SwipeableView from './SwipeableView';
import Carousel from './Carousel';
import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL';
import themeColors from '../styles/themes/default';
import reportActionPropTypes from '../pages/home/report/reportActionPropTypes';
import canUseTouchScreen from '../libs/canUseTouchscreen';
import CONFIG from '../CONFIG';
Expand Down Expand Up @@ -40,18 +40,13 @@ class AttachmentCarousel extends React.Component {
this.canUseTouchScreen = canUseTouchScreen();
this.makeAndSetArrowState = this.makeAndSetArrowState.bind(this);
this.cycleThroughAttachments = this.cycleThroughAttachments.bind(this);
this.handleArrowPress = this.handleArrowPress.bind(this);
this.onShowArrow = this.onShowArrow.bind(this);

this.state = {showArrows: this.canUseTouchScreen};
}

componentDidMount() {
this.makeAndSetArrowState();
if (this.canUseTouchScreen) {
return;
}
document.addEventListener('keydown', this.handleArrowPress);
}

componentDidUpdate(prevProps) {
Expand All @@ -63,13 +58,6 @@ class AttachmentCarousel extends React.Component {
this.makeAndSetArrowState();
}

componentWillUnmount() {
if (this.canUseTouchScreen) {
return;
}
document.removeEventListener('keydown', this.handleArrowPress);
}

/**
* Toggles the visibility of the arrows
* @param {Boolean} showArrows
Expand Down Expand Up @@ -151,20 +139,6 @@ class AttachmentCarousel extends React.Component {
});
}

/**
* Listens for keyboard shortcuts and applies the action
*
* @param {Object} e
*/
handleArrowPress(e) {
if (e.key === 'ArrowLeft') {
this.cycleThroughAttachments(-1);
}
if (e.key === 'ArrowRight') {
this.cycleThroughAttachments(1);
}
}

render() {
if (!this.state.sourceURL) {
return null;
Expand Down Expand Up @@ -199,16 +173,15 @@ class AttachmentCarousel extends React.Component {
</>
)}

<SwipeableView
isAnimated
<Carousel
styles={[styles.attachmentModalArrowsContainer]}
canSwipeLeft={!this.state.isBackDisabled}
canSwipeRight={!this.state.isForwardDisabled}
onPress={() => this.canUseTouchScreen && this.onShowArrow(!this.state.showArrows)}
onSwipeHorizontal={this.cycleThroughAttachments}
onCycleThroughAttachments={this.cycleThroughAttachments}
>
<AttachmentView onPDFPress={() => this.onShowArrow(!this.state.showArrows)} sourceURL={this.state.sourceURL} file={this.state.file} />
</SwipeableView>
</Carousel>

</View>

Expand Down
77 changes: 77 additions & 0 deletions src/components/Carousel/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Pressable} from 'react-native';
import canUseTouchScreen from '../../libs/canUseTouchscreen';

const propTypes = {
/** handles onPress events with a callback */
onPress: PropTypes.func,

/** can handle the cycling of attachments */
onCycleThroughAttachments: PropTypes.func,

/** can be set to provide styles */
styles: PropTypes.arrayOf(PropTypes.shape({})),

/** Children to render. */
children: PropTypes.oneOfType([
PropTypes.func,
PropTypes.node,
]).isRequired,
};

const defaultProps = {
styles: [],
onPress: () => {},
onCycleThroughAttachments: () => {},
};

class Carousel extends React.Component {
constructor(props) {
super(props);

this.canUseTouchScreen = canUseTouchScreen();
this.handleKeyPress = this.handleKeyPress.bind(this);
}

componentDidMount() {
if (this.canUseTouchScreen) {
return;
}
document.addEventListener('keydown', this.handleKeyPress);
}

componentWillUnmount() {
if (this.canUseTouchScreen) {
return;
}
document.removeEventListener('keydown', this.handleKeyPress);
}

/**
* Listens for keyboard shortcuts and applies the action
*
* @param {Object} e
*/
handleKeyPress(e) {
if (e.key === 'ArrowLeft') {
this.props.onCycleThroughAttachments(-1);
}
if (e.key === 'ArrowRight') {
this.props.onCycleThroughAttachments(1);
}
}

render() {
return (
<Pressable style={this.props.styles} onPress={this.props.onPress}>
{this.props.children}
</Pressable>
);
}
}

Carousel.propTypes = propTypes;
Carousel.defaultProps = defaultProps;

export default Carousel;
90 changes: 90 additions & 0 deletions src/components/Carousel/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, {Component} from 'react';
import {PanResponder, Dimensions, Animated} from 'react-native';
import PropTypes from 'prop-types';

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

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

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

/** Callback to handle a press event because PanResponder will intercept all gestures */
onPress: PropTypes.func,

/** These help to prevent a swipe animation when at either end */
canSwipeLeft: PropTypes.bool,
canSwipeRight: PropTypes.bool,
};

const defaultProps = {
onSwipe: () => {},
onPress: () => {},
canSwipeLeft: false,
canSwipeRight: false,
};

class Carousel extends Component {
constructor(props) {
super(props);
this.pan = new Animated.Value(0);

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

onStartShouldSetPanResponder: () => true,
onPanResponderMove: (event, gestureState) => Animated.event([null, {
dx: this.pan,
}], {useNativeDriver: false})(event, gestureState),

onPanResponderRelease: (event, gestureState) => {
// 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();
}

const deltaSlide = gestureState.dx > 0 ? -1 : 1;
if (Math.abs(gestureState.vx) < 1.6 || (deltaSlide === -1 && !this.props.canSwipeLeft) || (deltaSlide === 1 && !this.props.canSwipeRight)) {
return Animated.spring(this.pan, {useNativeDriver: false, toValue: 0}).start();
}

const width = Dimensions.get('window').width;
const slideLength = deltaSlide * (width * (3 / 4));
Animated.timing(this.pan, {useNativeDriver: false, duration: 100, toValue: -slideLength}).start(({finished}) => {
if (!finished) {
return;
}
this.props.onSwipe(deltaSlide);
this.pan.setValue(slideLength);
Animated.timing(this.pan, {useNativeDriver: false, duration: 100, toValue: 0}).start();
});
},
});
}

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

Carousel.propTypes = propTypes;
Carousel.defaultProps = defaultProps;

export default Carousel;
1 change: 0 additions & 1 deletion src/components/PDFView/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ class PDFView extends Component {
}
}

PDFView.displayName = 'PDFView';
PDFView.propTypes = pdfViewPropTypes.propTypes;
PDFView.defaultProps = pdfViewPropTypes.defaultProps;

Expand Down
37 changes: 2 additions & 35 deletions src/components/SwipeableView/index.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Pressable} from 'react-native';
export default ({children}) => children;

const propTypes = {
/** this could be set to provide events */
onPress: PropTypes.func,

/** can be set to provide styles */
styles: PropTypes.arrayOf(PropTypes.shape({})),

/** Children to render. */
children: PropTypes.oneOfType([
PropTypes.func,
PropTypes.node,
]).isRequired,
};

const defaultProps = {
onPress: () => {},
styles: [],
};

// Swipeable View is available just on Android/iOS for now. Still need to utilize events
function SwipeableView(props) {
return (
<Pressable style={props.styles} onPress={props.onPress}>
{props.children}
</Pressable>
);
}

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

export default SwipeableView;
// Swipeable View is available just on Android/iOS for now.
Loading

0 comments on commit 0cd79cc

Please sign in to comment.